diff options
author | Manuel Pégourié-Gonnard <mpg@elzevir.fr> | 2008-09-11 19:22:09 +0000 |
---|---|---|
committer | Manuel Pégourié-Gonnard <mpg@elzevir.fr> | 2008-09-11 19:22:09 +0000 |
commit | c8da6304f2038c75e61e08c5345c1a2abaef802e (patch) | |
tree | 21f5c078d2cf00909a41a05fd88f30a7845e9adc /Master/texmf-dist/doc/generic/xlop | |
parent | 4b8d19ed7a69c2b86e10d0a9f0b57fdf89373ea1 (diff) |
new generic package xlop
git-svn-id: svn://tug.org/texlive/trunk@10556 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/doc/generic/xlop')
-rw-r--r-- | Master/texmf-dist/doc/generic/xlop/LISEZ.MOI | 58 | ||||
-rw-r--r-- | Master/texmf-dist/doc/generic/xlop/README | 49 | ||||
-rw-r--r-- | Master/texmf-dist/doc/generic/xlop/XLOP03 | 35 | ||||
-rw-r--r-- | Master/texmf-dist/doc/generic/xlop/fr-user.pdf | bin | 0 -> 283832 bytes | |||
-rw-r--r-- | Master/texmf-dist/doc/generic/xlop/fr-user.tex | 2387 | ||||
-rw-r--r-- | Master/texmf-dist/doc/generic/xlop/history.txt | 55 | ||||
-rw-r--r-- | Master/texmf-dist/doc/generic/xlop/xlop.tex | 3948 |
7 files changed, 6532 insertions, 0 deletions
diff --git a/Master/texmf-dist/doc/generic/xlop/LISEZ.MOI b/Master/texmf-dist/doc/generic/xlop/LISEZ.MOI new file mode 100644 index 00000000000..01be2e2d666 --- /dev/null +++ b/Master/texmf-dist/doc/generic/xlop/LISEZ.MOI @@ -0,0 +1,58 @@ +PRÉSENTATION RAPIDE +------------------- +L'extension xlop s'articule autour de deux fonctionnalités +générales. La première consiste à afficher les opérations de façon +automatique (posées ou en ligne), c'est-à-dire en ne fournissant que +les opérandes de l'opération. La seconde consiste à permettre de +manipuler des nombres de taille quelconque, la seule limitation étant +la mémoire de TeX. Ces manipulations incluent toutes les opérations +usuelles, les entrées-sorties, la notion de variable numérique, les +tests et quelques opérations de haut niveau (sans permettre les +opérations nécessitant un traitement infini telles que la racine +carrée, l'exponentielle, les fonctions trigonométriques, etc.). + +DISTRIBUTION +------------ +Contenu +------- +La distribution comporte les fichiers suivants : + - LISEZ.MOI (celui que vous êtes en train de lire) ; + - README (la même en anglais) ; + - XLOP03 qui indique ce que devrait fournir la version prochaine ; + - history.txt qui retrace l'historique rapide du projet ; + - manual.sty qui est le fichier de style nécessaire à la compilation + du fichier fr-user.tex ; + - fr-user.tex qui est le source du manuel de l'utilisateur de xlop ; + - fr-user.pdf qui est le manuel de l'utilisateur de xlop ; + - xlop.tex qui contient le code de l'extension ; + - xlop.sty qui permet d'utiliser xlop comme une extension LaTeX. + +Installation +------------ +L'extension étant prévue pour pouvoir fonctionner aussi bien sous TeX +que sous LaTeX, les recommandations de la TDS indiquent que l'endroit +le plus correct pour placer ces fichiers (xlop.tex et xlop.sty) est : +[texmf]/tex/generic/xlop/. + +Il reste les fichiers de documentation (LISEZ.MOI, README, +history.txt, manual.sty et fr-user.*). Leur place normale devrait +être [texmf]/doc/generic/xlop/. + +Il reste à rafraichir la base en lançant la commande texhash (ou +mktexlsr, ou ...) et tout devrait être opérationnel. + +BOGUES ET AUTRES DÉSAGREMENTS +----------------------------- +Si vous détectez un bogue, quel que soit sa gravité (cela peut +simplement être des espaces parasites par exemple) essayez de réaliser +un exemple le plus court possible reproduisant le bogue. En +particulier, ne mettez aucune autre extension non nécessaire. Envoyez +le source ainsi qu'une explication, éventuellement très courte, du +problème rencontré à l'adresse suivante : + +Jean-Come.Charpentier@wanadoo.fr + +Si vous souhaitez une certaine fonctionnalité pour une version +ultérieure de l'extension, n'hésitez pas à en faire part à +l'auteur. Pour aider mon logiciel antispam, écrivez 'xlop' dans le +sujet du message. diff --git a/Master/texmf-dist/doc/generic/xlop/README b/Master/texmf-dist/doc/generic/xlop/README new file mode 100644 index 00000000000..c87c71c828a --- /dev/null +++ b/Master/texmf-dist/doc/generic/xlop/README @@ -0,0 +1,49 @@ +OVERVIEW +-------- +Package xlop proposes two main features. First, xlop prints +operations (displayed or running), that is, user write only +operands. Second, xlop is able to deal with unlimited numbers, in +fact, limitations are due to TeX memory. This features include +basic arithmetic operations, input/ouput, numeric variables, tests, +and some high level operation (without operations which imply infinite +processing such roots, exponential, trigonometric functions, etc.). + +DISTRIBUTION +------------ +Contents +-------- +Distribution consists of files: + * README (the file you are reading) + * LISEZ.MOI (same in french) + * XLOP03 indicates what features the next version should be provide + * history.txt relates project history + * manual.sty package file to compile fr-user.tex + * fr-user.tex xlop user's manual input file + * fr-user.pdf xlop user's manual + * xlop.tex xlop code + * xlop.sty allow the use of xlop as LaTeX package + +Installation +------------ +xlop can be used under TeX or LaTeX. Thus, TDS recommendations are +that the best place to put files (xlop.tex and xlop.sty) is +[texmf]/tex/generic/xlop/. + +For documentation files (README, history.txt, manual.sty, and +fr-user.*), best place should be [texmf]/doc/generic/xlop/. + +You have just to run texhash command (or mktexlsr, or ...) to refresh +your texmf base and all should work fine. + +BUGS AND TROUBLES +----------------------------- +If you detect some bug, whatever its seriousness (that could be just +spurious spaces), try to illustre this error with an example as short +as possible. Particularly, don't use unecessary package. Sent your +code with a short explanation at: + +Jean-Come.Charpentier@wanadoo.fr + +If you wish for some feature in a future version, ask to the author. +To help my antispam soft, could you please write 'xlop' in the message +subject? diff --git a/Master/texmf-dist/doc/generic/xlop/XLOP03 b/Master/texmf-dist/doc/generic/xlop/XLOP03 new file mode 100644 index 00000000000..b742723029a --- /dev/null +++ b/Master/texmf-dist/doc/generic/xlop/XLOP03 @@ -0,0 +1,35 @@ +xlop is still under construction. In fact, xlop 0.2 is just a beta +release; xlop 0.3 will provide: + + * Full redefinition about internal number representation (faster + and less memory space). + * Some macros improved (\opprint, \opdisplay, \opput, ...). + * New parameters (format=normal/sci/eng, carrymul, + hyphen (multiline for very long numbers), fine division and + multiplication control, ...) + * Calculation on basis 2 to 36 + e.g. \opadd[style=text]{"2"11010}{"2"10010} will display + 11010 + 10010 = 101100 + * Support language (languages defined in babel, oldrussian, and + babylon) e.g. \div[displayintermediary=all]{33}{2} displays + + language= french english + + 33 | 2 16.5 + -2 |--- ______ + --- | 16,5 2 ) 33 + 13 | 20 + -12 | -- + ---- | 13 + 10 | 12 + -10 | ---- + --- | 1.0 + 0 | 1.0 + --- + 0 + Language define decimal separator, thousand separator, type of + displayed multiplication, type of displayed division (Author knows + 3 types of multiplications and 2 types of divisions) . + * High level functions (exp, log, sin, asin, sinh, argsin, (idem + for cos, tan, and cot), sqrt, root). + * last but not least, english documentation! diff --git a/Master/texmf-dist/doc/generic/xlop/fr-user.pdf b/Master/texmf-dist/doc/generic/xlop/fr-user.pdf Binary files differnew file mode 100644 index 00000000000..4e30e3edc6c --- /dev/null +++ b/Master/texmf-dist/doc/generic/xlop/fr-user.pdf diff --git a/Master/texmf-dist/doc/generic/xlop/fr-user.tex b/Master/texmf-dist/doc/generic/xlop/fr-user.tex new file mode 100644 index 00000000000..9a8a37be4fc --- /dev/null +++ b/Master/texmf-dist/doc/generic/xlop/fr-user.tex @@ -0,0 +1,2387 @@ +\documentclass[12pt]{report} +\usepackage{manual} +\usepackage[frenchb]{babel} +\fvset{label=source}% français + +\begin{document} +\begin{titlepage} + \null\par\vfill + \begin{center} + \begin{minipage}{0.75\linewidth} + \hrule width\linewidth height2pt depth0pt + \hrule width0pt height3pt depth0pt + \hrule width\linewidth height1pt depth0pt + \hrule width0pt height18pt depth0pt + \begin{center} + \Huge\bfseries XLOP v \fileversion\par\vskip18pt + Manuel de l'utilisateur + \end{center} + \hrule width0pt height6pt depth0pt + \hrule width\linewidth height1pt depth0pt + \hrule width0pt height3pt depth0pt + \hrule width\linewidth height2pt depth0pt + \end{minipage} + \end{center} + \vfill + \begin{center} + Jean-Côme Charpentier\\ + \today + \end{center} + \vfill\null\par +\end{titlepage} +\newpage +\pagenumbering{roman} +\tableofcontents +\newpage +\pagenumbering{arabic} + +\chapter{Présentation} +\label{chap:Présentation} +L'extension \package{xlop} a été développée pour permettre de réaliser +automatiquement des calculs arithmétiques sur des nombres de taille +quelconque et d'afficher les résultats sous forme posée ou en +ligne. Voici un premier exemple permettant de donner un aperçu de la +syntaxe de base : +\begin{SideBySideExample} + \opadd{45,05}{78,4} +\end{SideBySideExample} +Ce premier exemple appelle quelques commentaires qui permettront de +donner une idée sur la façon de manipuler l'extension. + +L'addition est posée \og comme à l'école \fg{} : il s'agit de la +présentation par défaut. On a un alignement sur la virgule des +opérandes et du résultat, le symbole opératoire placé à gauche est +centrée verticalement entre les deux opérandes et le séparateur +décimal est un point malgré le fait d'avoir indiquer les opérandes +avec une virgule dans l'appel de la macro. Enfin, on notera la +présence d'une retenue au dessus de la première opérande. + +Mis à part l'alignement sur la virgule qui est obligatoire pour +l'addition posée, toutes les autres caractéristiques décrites +ci-dessus sont paramétrables. Certaines macros de l'extension et, en +tout cas, toutes les macros affichant les opérations arithmétiques +admettent un argument optionnel qui permettra de contrôler la +présentation. Pour cela, on utilisera une syntaxe \og à la keyval +\fg{} : on spécifie une suite de modifications de paramètres par une +liste d'affectations séparées par des virgules. Une affectation a +une des deux syntaxes possibles ci-dessous : +\begin{verbatim} + <paramètres>=<valeur> + <paramètre> +\end{verbatim} +la seconde possibilité étant en fait un raccourci pour : +\begin{verbatim} + <paramètre>=true +\end{verbatim} +Dans cette liste d'affectation, on peut faire suivre les virgules par +un ou plusieurs espaces mais il ne faut pas mettre d'espace de part et +d'autre du signe égal ou avant la virgule : un paramètre ou une valeur +pouvant (potentiellement) comporter le caractère espace. + +Ainsi, si l'on veut un séparateur décimal qui soit une virgule, un +symbole opératoire placé en face de la seconde opérande et en +supprimant la présence des retenues, il suffit d'indiquer : +\begin{SideBySideExample} + \opadd[decimalsepsymbol={,}, + voperator=bottom, + carryadd=false]{45.05}{78.4} +\end{SideBySideExample} +On notera la petite astuce consistant à mettre la virgule entre +accolades dans la définition du symbole du séparateur décimal. En +effet, la syntaxe : +\begin{Verbatim}[xrightmargin=0pt] + \opadd[decimalsepsymbol=,,voperator=bottom, + carryadd=false]{45.05}{78.4} +\end{Verbatim} +est fautive : \package{xlop} ne comprenant plus trop bien ce qu'est +cette \og liste \fg{} ! + +Un autre point important quoique moins visible, est que les chiffres +sont disposés à des emplacements très précis. Chaque chiffre est placé +dans une boîte de largeur et de hauteur fixes (paramétrables), le +séparateur décimal est, par défaut, placé dans une boîte de largeur +nulle et toutes les lignes sont régulièrement espacées qu'il y ait ou +non un trait horizontal. Cela permet d'obtenir des alignements +rigoureux et permet également de placer ce que l'on veut à +l'emplacement que l'on veut. +\begin{SideBySideExample} + \psset{xunit=\opcolumnwidth, + yunit=\oplineheight} + \opadd{45.05}{78.4} + \oplput(1.5,3){retenue} + \psline{->}(1,3.15)(-3.25,3.15) +\end{SideBySideExample} +Cet exemple a été réalisé en utilisant l'extension +\package{pstricks}\index{pstricks@\package{pstricks}} + +Nous avons dit précédemment que \package{xlop} était capable de +manipuler des nombres de taille quelconque. Nous reviendrons plus en +détail sur cette possibilité et nous nous contenterons ici de ne donner +qu'un exemple de ce que cela peut offrir. Ne regardez pas trop le +code, les explications seront données plus loin dans ce manuel, pour +l'instant, admirez seulement le résultat ! +\begin{CenterExample}[xrightmargin=0pt] + \opdiv[style=text,period]{1}{49} +\end{CenterExample} + +L'extension \package{xlop} offre quelques autres fonctionnalités. Il +est ainsi possible de manipuler les nombres par l'intermédiaire de +variables, ces variables pouvant être créées par une assignation +simple ou bien comme résultat d'un calcul. On peut également manipuler +les chiffres de façon individuelle : +\begin{SideBySideExample} + \opadd*{45.05}{78.4}{r}% + Le premier chiffre après la virgule de + $45.05+78.4$ est un + \opgetdecimaldigit{r}{1}{d}% + $\opprint{d}$. +\end{SideBySideExample} +effectuer des tests : +\begin{SideBySideExample} + \opadd*{45.05}{78.4}{r}% + La somme $45.05+78.4$ est + \opcmp{r}{100}% + \ifopgt strictement supérieure + \else\ifoplt strictement inférieure + \else égale + \fi\fi + à $100$. +\end{SideBySideExample} +avoir accès à quelques opérations ou fonctions : +\begin{SideBySideExample} + Le pgcd de $182$ et $442$ est + \opgcd{182}{442}{d}$\opprint{d}$ +\end{SideBySideExample} +pouvoir réaliser des calculs complexes sous forme infixe : +\begin{SideBySideExample} + \opexpr{(2+3^2)/(gcd(22,33))}{r}% + $$\frac{2+3^2}{\gcd(22,33)} = + \opprint{r}$$ +\end{SideBySideExample} + +\chapter{Instruction \package{xlop}} +\`A quelques exceptions près qui seront étudiées en temps voulu, les +macros de \package{xlop} peuvent éventuellement avoir un argument +optionnel entre crochets pour modifier localement la valeur des +paramètres de fonctionnement, les autres arguments (obligatoires) +étant des nombres. Les deux sections de ce chapitre décrivent en +détail ce qu'est un nombre pour \package{xlop} et comment se servir +de ses paramètres. + +\section{Au début était le nombre} +\label{sec:Au début etait le nombre} +\subsection{Taille} +\label{subsec:Taille} +Avant de voir la syntaxe générale d'un nombre, nous allons nous +pencher sur la particularité de \package{xlop} qui est de pouvoir +manipuler des nombres de taille quelconque. + +\index{nombre!taille}Pour être tout à fait précis, la taille théorique +maximum d'un nombre est de $2^{31}-1$ chiffres. En pratique, cette +limite ne pourra pas être atteinte pour deux raisons essentielles. La +première est qu'une multiplication avec deux opérandes ayant $2^{25}$ +chiffres demanderait plus de $7\,000$ années de calcul sur +l'ordinateur de l'auteur ! La seconde est beaucoup plus restrictive +car elle est liée aux limites de taille des piles de \TeX{}. Voici un +tableau indiquant une compilation sous \TeX{} avec une multiplication +de deux opérandes de même taille sur une machine Linux, pentium~II~600 +et 256~Mo de RAM : +\begin{center} + \begin{tabular}{|l|*{6}{c|}} + \hline + nombre de chiffres & 100 & 200 & 300 & 400 & 425 & 450 \\\hline + temps de compilation (s) & 2 & 8 & 18 & 32 & 36 & crash \\\hline + \end{tabular} +\end{center} +Le \og crash \fg{} indiqué dans le tableau est dû au débordement de la +table de hachage (hash table). +\index{hash table}% +\index{depassement de capacite@dépassement de capacité}% +Sous \LaTeX{}, la limite avant crash sera plus réduite. D'autre part, +ces tests ont été effectués sur un fichier minimum : avec un document +source classique, cette limite sera un peu plus basse. Une autre +limite qui risque d'être atteinte relativement rapidement est la +taille du spouleur (spool size). +\index{spool size}% +Pour composer ce document qui contient un grand nombre d'appel aux +macros de \package{xlop}, l'auteur a augmenté la taille du spouleur +à~$250\,000$ ($125\,000$ s'étant révélé insuffisante) en éditant la +ligne \verb+pool_size+ du fichier \file{texmf.cnf}. De même, la table +de hachage a dû être augmentée en stipulant la valeur \texttt{1000} au +niveau de la ligne \verb+hash_extra+ du fichier \file{texmf.cnf}. + +\subsection{Syntaxe} +\label{subsec:Syntaxe} +Nous allons présenter cette syntaxe avec la grammaire BNF mais des +explications plus humaines suivront : +\begin{syntaxBNF} + \*nombre* & \{\*signe*\}\*nombre_positif* \alt \*nom* \\ + \*signe* & + \alt - \\ + \*nombre_positif* & \*entier* \alt \*sep*\*entier* \alt \\ + \sameline \*entier*\*sep* \alt \*entier*\*sep*\*entier* \\ + \*sep* & . \alt , \\ + \*entier* & \*chiffre*\{\*chiffre*\} \\ + \*nom* & \*début*\{caractère\} \\ + \*début* & caractère \textnormal{autre que } \*signe*\textnormal{,} + \*sep* \\ + \sameline \textnormal{et} \*chiffre* +\end{syntaxBNF} + +Le symbole \texttt{caractère} désigne presque n'importe quel caractère +accepté par \TeX{}. Les seules exceptions sont les caractères \verb+%+, +et \verb+#+ qui sont totalement interdits. En fait, les caractères +actifs risquent de poser des problèmes. Par exemple, la définition de +\verb+~+ sous \LaTeX{} empêche ce caractère de pouvoir faire partie +d'un nom. D'autre part, le caractère \verb+\ +conserve sont rôle de +caractère d'échappement, c'est-à-dire que le nom sera celui obtenu +après développement de la macro introduite. Il n'y a aucune autre +contrainte comme le montre le code suivant : +\begin{SideBySideExample} + \newcommand\prefix{a/b} + \opadd*{2}{2}{a/b_{^c}!&$} + \opprint{\prefix_{^c}!&$} +\end{SideBySideExample} +On notera en particulier que \verb+a/b_{^c}!&$+ et +\verb+\prefix_{^c}!&$+ représentent exactement le même nom, si +\verb+\prefix+ a la définition adéquate évidemment. Cette possibilité +d'obtenir un nom en utilisant des macros peut sembler inutile mais il +n'en est rien. On peut ainsi réaliser des boucles avec des noms tels +que \verb+r1+, \verb+r2+, \ldots, \verb+r<n>+ en utilisant le code +\verb+r\the\cpt+ comme nom où \verb+cpt+ est un compteur (au sens +\TeX{}, le mécanisme des compteurs avec \LaTeX{} empêche d'être aussi +flexible). Nous verrons un exemple d'utilisation de cette forme à la +section~\ref{sec:Creation d'operations complexes} +page~\pageref{sec:Creation d'operations complexes}. + +\index{nombre!valide}En pratique, que signifient toutes ces règles ? +Elles indiquent d'abord qu'un nombre écrit sous forme décimale peut +être précédé par n'importe quelle séquence de signes plus et moins. +Évidemment, le nombre sera négatif lorsqu'il y aura un nombre impair +de signes moins. Ensuite, un nombre ne peut comporter qu'un seul +séparateur décimal qui peut être le point ou la virgule, celui-ci +pouvant être placé n'importe où dans le nombre. Enfin, l'écriture d'un +nombre s'effectue obligatoirement en base~10. Attention : ces règles +signifient également que \verb+-a+ n'est pas valide. + +L'extension utilise quelques noms de façon interne et il est plus +prudent de ne pas commencer un nom de variable par le caractère +\texttt{@}. + +\section{Paramètres de \package{xlop}} +\label{sec:Parametres de xlop} +\index{parametre@paramètre!syntaxe|(} +Les affectations de paramètres restent locales à la macro lorsqu'elles +sont indiquées au niveau de son argument optionnel. Pour rendre de +telles affectations globales, il faut utiliser la macro +\macro{opset}. Par exemple +\begin{Verbatim}[xrightmargin=0pt] + \opset{decimalsepsymbol={,}} +\end{Verbatim} +fera que le symbole du séparateur décimal sera la virgule pour tout le +reste du document, ou, du moins, jusqu'à une prochaine redéfinition +par la macro \verb+\opset+. Dans ce manuel, ce sera le cas à partir de +maintenant.\opset{decimalsepsymbol={,}} + +\subsection{Symboles} +\label{subsecSymboles} +Le paramètre \parameter{afterperiodsymbol} indique le symbole qui +suit l'écriture d'un quotient en ligne lors d'une division avec +recherche de période. Sa valeur par défaut est \verb+$\ldots$+ + +Le paramètre \parameter{equalsymbol} indique le symbole utilisé pour +l'égalité. Sa valeur par défaut est \verb+$=$+. En réalité, le +paramètre est défini avec : +\begin{Verbatim}[xrightmargin=0pt] + \opset{equalsymbol={$=$}} +\end{Verbatim} +c'est-à-dire avec des accolades pour protéger le signe égal. Sans les +accolades, il y aurait une erreur à la compilation. On doit procéder +de cette façon lorsque la valeur comporte le signe égal ou une +virgule\index{parametre@paramètre!avec \og = \fg{} ou \og ,\fg} + +Le paramètre \parameter{approxsymbol} indique le symbole utilisé pour +les approximations. Sa valeur par défaut est \verb+$\approx$+. + +Le paramètre \parameter{decimalsepsymbol} indique le symbole utilisé +pour le séparateur décimal. Sa valeur par défaut est le point. + +Les paramètres \parameter{addsymbol}, \parameter{subsymbol}, +\parameter{mulsymbol} et \parameter{divsymbol} indiquent les symboles +utilisés pour les quatre opérations arithmétiques. Les valeurs par +défaut sont respectivement \verb!$+$!, \verb!$-$!, \verb!$\times$! et +\verb!$\div$!. + +\subsection{Présentation générale} +\label{subsec:Presentation generale} +Le paramètre \parameter{voperation} indique la façon dont une +opération posée sera placée par rapport à la ligne de base. Les +valeurs possibles sont \verb+top+, \verb+center+ et \verb+bottom+ +(valeur par défaut). +\begin{SideBySideExample} + top\quad + \opadd[voperation=top]{45}{172}\par + center\quad + \opadd[voperation=center]{45}{172}\par + bottom\quad + \opadd[voperation=bottom]{45}{172} +\end{SideBySideExample} + +Le paramètre \parameter{voperator} indique comment sera placé le +symbole opératoire par rapport aux opérandes. Les valeurs possibles +sont \verb+top+, \verb+center+ (valeur par défaut) et \verb+bottom+. +\begin{SideBySideExample} + top\quad + \opadd[voperator=top]{45}{172}\par + center\quad + \opadd[voperator=center]{45}{172}\par + bottom\quad + \opadd[voperator=bottom]{45}{172} +\end{SideBySideExample} + +Le paramètre \parameter{deletezero} indique si certains nombres d'une +opération doivent être affichés avec ou sans les zéros non +significatifs. Le rôle exact de ce paramètre varie en fonction de +l'opération et nous y reviendrons lors de la présentation des +différentes opérations. + +Le paramètre \parameter{style} indique si l'opération doit être posée +(valeur \verb+display+ qui est la valeur par défaut) ou bien être +affichée en ligne (valeur \verb+text+). On reviendra sur ce paramètre +lors de la présentation de la division car les possibilités sont alors +un peu plus nombreuses. +\begin{SideBySideExample} + \opadd[style=text]{45}{172} +\end{SideBySideExample} +Dans les opérations en ligne, \package{xlop} fait attention à ne pas +composer la formule en mode mathématique de façon directe. Cela permet +de spécifier ce que l'on veut comme dans l'exemple qui suit et c'est +également pour cela qu'il faut indiquer les valeurs classiques des +symboles entre délimiteurs mathématiques. +\begin{SideBySideExample} + \opadd[addsymbol=plus, + equalsymbol=\'egal, + style=text]{42}{172} +\end{SideBySideExample} +Cependant, \package{xlop} introduit exactement les mêmes pénalités de +coupures et exactement les mêmes espacements que pour une formule +mathématique. + +Le paramètre \parameter{parenthesisnegative} indique comment composer +les nombres négatifs dans les opérations en ligne. Les valeurs +possibles sont : +\begin{itemize} +\item \texttt{none} qui compose les nombres négatifs sans parenthèse ; +\item \texttt{all} qui compose les nombres négatifs en les plaçant + entre parenthèses ; +\item \texttt{last} qui compose les nombres négatifs en les plaçant + entre parenthèses s'il ne s'agit pas de la première opérande. +\end{itemize} +\begin{SideBySideExample} + \opadd[style=text, + parenthesisnegative=none] + {-12}{-23}\par + \opadd[style=text, + parenthesisnegative=all] + {-12}{-23}\par + \opadd[style=text, + parenthesisnegative=last] + {-12}{-23} +\end{SideBySideExample} + +\subsection{Dimensions} +\label{subsec:Dimensions} +Dans les opérations posées, les chiffres sont placés dans des boîtes +de dimensions fixées. La largeur est donnée par le paramètre +\parameter{columnwidth} et la hauteur par le paramètre +\parameter{lineheight}. La valeur par défaut de \texttt{lineheight} +est \verb+\baselineskip+ ce qui fait que les lignes des opérations +seront espacées, par défaut, comme les lignes d'un paragraphe. La +valeur par défaut de \texttt{columnwidth} est de \texttt{2ex} car la +largeur \og normale \fg{} des chiffres aurait donné des résultats peu +lisibles. +\begin{SideBySideExample} + \opadd[columnwidth=0.5em] + {45.89}{127.5} +\end{SideBySideExample} +Ce piètre résultat est dû en partie au fait que la virgule est placé +dans une boîte dont la largeur est contrôlée par le paramètre +\parameter{decimalsepwidth} dont la valeur par défaut est nulle. Un +essai d'amélioration peut être effectué en donnant à ce paramètre la +largeur \fg{} normale \og d'une virgule. +\begin{SideBySideExample} + \opadd[columnwidth=0.5em, + decimalsepwidth=0.27778em] + {45.89}{127.5} +\end{SideBySideExample} +C'est meilleur mais le fait de donner une largeur non nulle à la boîte +contenant le séparateur décimal risque de poser des difficultés si +l'on veut placer des éléments externes : cela va à l'encontre de +l'idée de placer les chiffres dans une grille fixe. Ceci est donc à +éviter en temps normal. + +Les deux paramètres \parameter{columnwidth} et \parameter{lineheight} +correspondent aux deux seules dimensions que l'extension rend +publiques, à savoir respectivement +\verb+\opcolumnwidth+\index{opcolumnwidth@\texttt{$\backslash$opcolumnwidth}} +et +\verb+\oplineheight+\index{oplineheight@\texttt{$\backslash$oplineheight}}. +Il est cependant dangereux de vouloir modifier ces dimensions de façon +directe puisque une modification par voie normale n'a pas pour seule +conséquence d'obtenir une nouvelle valeur pour ces +dimensions. L'extension \package{xlop} a rendu ces dimensions +publiques uniquement pour pouvoir les lire, pas pour les modifier. + +Les deux paramètres suivants permettent de spécifier les largeurs des +traits horizontaux et verticaux tracés par \package{xlop}. Il s'agit +des paramètres \parameter{hrulewidth} et \parameter{vrulewidth} dont +la valeur par défaut est \texttt{0.4pt}. + +Ces traits sont composés sans perturber la grille, c'est-à-dire sans +ajouter d'espace vertical. Ainsi, avec des valeurs importantes pour +l'épaisseur, les traits risquent de déborder au niveau des opérandes. +\begin{SideBySideExample} + \opadd[hrulewidth=8pt]{42}{172} +\end{SideBySideExample} + +Il existe également un paramètre permettant de contrôler le décalage +horizontal du séparateur décimal. Il s'agit de +\parameter{decimalsepoffset} dont la valeur par défaut est égale +à~\texttt{-0.35}. Cette valeur par défaut indique une longueur en +prenant \verb+\opcolumnwidth+ comme unité. Un exemple d'utilisation de +ce paramètre sera donné à la section~\ref{sec:Division} +page~\pageref{sec:Division}. + +\subsection{Styles des chiffres} +\label{subsec:Styles des chiffres} +L'extension \package{xlop} distingue cinq types de nombres et y +associe cinq paramètres de style : +\begin{itemize} +\item les opérandes avec \parameter{operandstyle} ; +\item le résultat avec \parameter{resultstyle} ; +\item les restes avec \parameter{remainderstyle} ; +\item les résultats intermédiaires avec \parameter{intermediarystyle} + ; +\item les retenues avec \parameter{carrystyle}. +\end{itemize} +\begin{SideBySideExample} + \opadd[operandstyle=\blue, + resultstyle=\red, + carrystyle=\scriptsize\green] + {45.89}{127.5} +\end{SideBySideExample} +Rappelons que dans ce manuel, nous utilisons l'extension +\package{pstricks}\index{pstricks}. + +\index{parametre@paramètre!indexé|(}% +En réalité, la gestion de ces styles est encore plus puissante car on +peut distinguer les différents nombres d'une même classe. Dans une +même opération, on a plusieurs opérandes et, éventuellement plusieurs +restes et plusieurs nombres intermédiaires. On accède alors au style +de ces nombres individuels en indexant le paramètre de style +correspondant. +\begin{SideBySideExample} + \opadd[operandstyle=\blue, + operandstyle.1=\lightgray, + resultstyle=\red, + carrystyle=\scriptsize\green] + {45.89}{127.5} +\end{SideBySideExample} +Sur cet exemple, on a indiqué que la première opérande devait être +composée avec le style \verb+\lightgray+ et comme rien n'était indiqué +pour la seconde opérande, celle-ci a repris le style de base de sa +classe (donc a été composée avec le style \verb+\blue+). + +Ce mécanisme va encore plus loin car on peut indicer à deux niveaux +les styles des classes opérande, reste et nombre intermédiaire et à un +niveau les styles des classes résultat et retenue pour accéder au +style de chacun des chiffres de ces nombres. Afin de rendre les +indexations plus facile à gérer, un index positif indiquera le rang +d'un chiffre de la partie entière (numérotée de droite à gauche, +l'index~1 correspondant au chiffre des unités) et un index négatif +indiquera le rang d'un chiffre de la partie décimale (numérotée de +gauche à droite, l'index $-1$ correspondant au chiffre des dixièmes). +\begin{SideBySideExample} + \opadd[operandstyle.1.1=\white, + operandstyle.1.-2=\white, + operandstyle.2.3=\white, + resultstyle.2=\white, + deletezero=false] + {045.89}{127.50} +\end{SideBySideExample} +On peut également utiliser une macro à un paramètre comme style. +\begin{SideBySideExample} + \newcommand\hole[1]{$\bullet$} + \opadd[operandstyle.1.1=\hole, + operandstyle.1.-2=\hole, + operandstyle.2.3=\hole, + resultstyle.2=\hole] + {45.89}{127.5} +\end{SideBySideExample} +Lorsque le style est une macro, le chiffre constitue le dernier +argument de cette macro. Voici un exemple plus compliqué et utilisant +l'extension \package{pst-node} de la suite \package{pstricks} : +\begin{SideBySideExample} + \newcommand\OPoval[3]{% + \dimen1=#2\opcolumnwidth + \ovalnode{#1} + {\kern\dimen1 #3\kern\dimen1}} + \opadd[voperation=top, + operandstyle.1.1=\OPoval{A}{0}, + operandstyle.2.2=\OPoval{C}{0.8}] + {45}{172}\qquad + \begin{minipage}[t]{2cm} + \pnode(0,0.2em){B}\ chiffre + \ncarc{->}{A}{B}\par + \pnode(0,0.2em){D}\ nombre + \ncarc{<-}{D}{C} + \end{minipage} +\end{SideBySideExample} + +Comme les chiffres, le séparateur décimal tient compte du style d'un +nombre. Pour accéder au style du séparateur décimal de façon +individuelle, il faut employer l'indice \texttt{d} au lieu des indices +numériques des chiffres. +\begin{SideBySideExample} + \newcommand\hole[1]{\texttt{\_}} + \opmul[intermediarystyle=\hole, + resultstyle=\hole, + resultstyle.d=\white]{2.46}{35.7} +\end{SideBySideExample} +\index{parametre@paramètre!indexé|)}% +\index{parametre@paramètre!syntaxe|)} + +\chapter{Opérations arithmétiques} +\label{chap:Opérations arithmétiques} +\section{Addition} +\label{sec:Addition} +L'addition est gérée par la macro \macro{opadd}. L'addition, +lorsqu'elle est posée, n'affiche que des nombres positifs. Cela va +avoir comme conséquence d'afficher une soustraction lorsqu'une des +opérandes est négative.% +\index{nombre!négatifs dans une opération posée} +\begin{SideBySideExample} + \opadd{-245}{72} +\end{SideBySideExample} +De façon générale, le principe est de poser l'opération qui permet de +retrouver le résultat comme on le ferait à la main. En revanche, +l'affichage en ligne donnera toujours une addition puisqu'on peut +maintenant écrire des nombres négatifs. +\begin{SideBySideExample} + \opadd[style=text]{-245}{72} +\end{SideBySideExample} + Outre les paramètres généraux décrits à la + section~\ref{sec:Parametres de xlop}, la macro \verb+\opadd+ est + sensible aux paramètres \texttt{carryadd}, \texttt{lastcarry} et + \texttt{deletezero}. + +Le paramètre \parameter{carryadd} est un paramètre +booléen\index{parametre@paramètre!booléen} c'est-à-dire n'acceptant +que les valeurs \texttt{true} et \texttt{false}. Comme il d'usage, +l'omission du signe égal et de la partie droite de l'affectation +équivaut à \texttt{=true}. Ce paramètre indique si les retenues +doivent être ou non affichées. Sa valeur par défaut est +\texttt{true}. + +Le paramètre \parameter{lastcarry} est également un paramètre +booléen. Il indique si une retenue sans chiffre correspondant au +niveau des deux opérandes doit être ou non affichée. Sa valeur par +défaut est \texttt{false}. On fera attention au rôle exact de ce +paramètre. Ainsi, si la seconde opérande dans l'exemple qui suit avait +été~15307, la dernière retenue aurait été affichée quelle que soit la +valeur du paramètre \texttt{lastcarry} puisqu'il y aurait eu un +chiffre correspondant au niveau de la seconde opérande. +\begin{SideBySideExample} + \opadd{4825}{5307} +\end{SideBySideExample} +\begin{SideBySideExample} + \opadd[carryadd=false]{4825}{5307} +\end{SideBySideExample} +\begin{SideBySideExample} + \opadd[lastcarry]{4825}{5307} +\end{SideBySideExample} + +Le paramètre \parameter{deletezero} est également un paramètre booléen +et son rôle et d'indiquer si les zéros non significatifs doivent être +supprimés ou non. Sa valeur par défaut est \texttt{true}. Si ce +paramètre vaut \texttt{false}, les opérandes et le résultats auront le +même nombre de chiffres, \package{xlop} ajoutant des zéros non +significatifs pour y parvenir. Les zéros non significatifs des +opérandes ne sont pas supprimés également. +\begin{SideBySideExample} + \opadd{012.3427}{5.2773}\par + \opadd[deletezero=false] + {012.3427}{5.2773} +\end{SideBySideExample} + +Ce paramètre a exactement le même rôle dans l'affichage en ligne que +dans l'affichage posé. +\begin{SideBySideExample} + \opadd[style=text]{02.8}{1.2}\par + \opadd[style=text, + deletezero=false]{02.8}{1.2}\par +\end{SideBySideExample} + +\section{Soustraction} +\label{sec:soustraction} +La soustraction est gérée par la macro \macro{opsub}. La soustraction, +lorsqu'elle est posée n'affiche que des nombres positifs. Cela va +avoir pour conséquence d'affficher une addition lorsqu'une des +opérandes est négative. +\begin{SideBySideExample} + \opsub{-245}{72} +\end{SideBySideExample} +De façon générale, le principe est de poser l'opération qui permet de +retrouver le résultat comme on le ferait à la main. En revanche, +l'affichage en ligne donnera toujours une soustraction puisqu'on peut +maintenant écrire des nombres négatifs. +\begin{SideBySideExample} + \opsub[style=text]{-245}{72} +\end{SideBySideExample} +Ce principe s'applique également lorsque la première opérande est +inférieure à la seconde (cas positif) où on aura une inversion des +opérandes. +\begin{SideBySideExample} + \opsub{1.2}{2.45} +\end{SideBySideExample} +Bien entendu, l'opération en ligne donnera le résultat exact. +\begin{SideBySideExample} + \opsub[style=text]{1.2}{2.45} +\end{SideBySideExample} + + +Outre les paramètres généraux vus à la section~\ref{sec:Parametres de + xlop}, \verb+\opsub+ est sensible aux paramètres +\texttt{carrysub}, \texttt{lastcarry}, \texttt{offsetcarry}, +\texttt{deletezero} et \texttt{behaviorsub}. + +Le paramètre \parameter{carrysub} est un paramètre booléen +qui indique si les retenues doivent être ou non présentes. Sa valeur +par défaut est \texttt{false} (rappelons que le paramètre +\texttt{carryadd} avait une valeur par défaut égale à \texttt{true}). +\begin{SideBySideExample} + \opsub[carrysub]{1234}{567} +\end{SideBySideExample} + +Dans l'exemple précédent, nous pouvons voir qu'il manque en fait une +retenue au niveau du dernier chiffre de 1234, cette façon de faire +étant assez courante. Néanmoins, on peut contrôler l'affichage de +cette dernière retenue avec le paramètre \parameter{lastcarry}. Ce +paramètre n'a pas tout à fait le même rôle que pour l'addition puisque +la dernière retenue ne sera pas affichée dans le cas où la seconde +opérande n'a pas de chiffre correspondant (alors que pour l'addition, +il fallait que les deux opérandes n'aient pas de chiffres +correspondant). +\begin{SideBySideExample} + \opsub[carrysub,lastcarry]{1234}{567} +\end{SideBySideExample} +On peut noter dans ce dernier cas qu'il est sans doute préférable de +mettre le paramètre \parameter{deletezero} à \texttt{false} pour +obtenir une présentation plus correcte. +\begin{SideBySideExample} + \opsub[carrysub, + lastcarry, + deletezero=false]{1234}{567} +\end{SideBySideExample} + +L'affichage des retenues au niveau des soustractions peut sembler un +peu trop compact. On peut élargir la boîte des chiffres avec le +paramètre \parameter{opcolumnwidth} mais également indiquer le +décalage des retenues avec le paramètre \parameter{offsetcarry}. La +valeur par défaut de ce paramètre est \texttt{-0.35}. +\begin{SideBySideExample} + \opsub[carrysub, + lastcarry, + deletezero=false]{12.34}{5.67} + + \bigskip + \opsub[carrysub, + lastcarry, + columnwidth=2.5ex, + offsetcarry=-0.4, + decimalsepoffset=-3pt, + deletezero=false]{12.34}{5.67} +\end{SideBySideExample} + +Il peut arriver qu'une soustraction de deux nombres positifs, le +premier étant inférieur au second, soit le signe d'une erreur de +l'utilisateur. Dans ce cas, et uniquement dans ce cas, le paramètre +\parameter{behaviorsub} permet d'obtenir un rappel à l'ordre. Les +trois valeurs possibles de ce paramètre sont \texttt{silent} qui est +la valeur par défaut et qui donne le résultat, \texttt{warning} qui +donne également le résultat mais affiche le message d'avertissement : +\begin{Verbatim}[xrightmargin=0pt,frame=none] + xlop warning. Substraction with first operand less than second one + See documentation for further information. +\end{Verbatim} +et enfin \texttt{error} qui affichera le message d'erreur : +\begin{Verbatim}[xrightmargin=0pt,frame=none] + xlop error. See documentation for further information. + Type H <return> for immediate help. + ! Substraction with first operand less than second one. +\end{Verbatim} +et l'opération ne sera pas effectuée. + +\section{Multiplication} +\label{sec:Multiplication} +La multiplication est gérée par la macro \macro{opmul}. + +Nous présenterons les paramètres \texttt{hfactor}, +\texttt{displayintermediary}, \texttt{shiftintermediarysymbol}, +\texttt{displayshiftintermediary} et finalement \texttt{deletezero}, +les autres paramètres ayant été vus à la section~\ref{sec:Parametres + de xlop}. + +Le paramètre \parameter{shiftintermediarysymbol} indique quel symbole +sera utilisé (sa valeur par défaut est \verb+$\cdot$+) pour visualiser +les décalages des nombres intermédiaires. Le paramètre +\parameter{displayshiftintermediary} peut prendre les valeurs +\texttt{shift} (valeur par défaut) qui ne montre ce symbole que +lorsque le décalage est supérieur à un rang, \texttt{all} qui indique +que ce symbole de décalage sera systématiquement affiché et +\texttt{none} qui indique que ce symbole ne sera jamais affiché. +\begin{CenterExample}[xrightmargin=0pt] + \opmul[displayshiftintermediary=shift]{453}{1001205}\qquad + \opmul[displayshiftintermediary=all]{453}{1001205}\qquad + \opmul[displayshiftintermediary=none]{453}{1001205} +\end{CenterExample} + +En réalité, le non affichage des nombres intermédiaires nuls est dû à +la valeur par défaut \texttt{none} du paramètre +\parameter{displayintermediary}. La valeur \texttt{all} va afficher +tous les nombres intermédiaires. +\begin{SideBySideExample} + \opmul[displayintermediary=all] + {453}{1001205} +\end{SideBySideExample} +On notera que les nombres intermédiaires nuls sont affichés avec +autant de chiffres que le premier facteur. + +Le paramètre \parameter{displayintermediary} admet la valeur +\texttt{nonzero} qui a le même rôle que la valeur \texttt{none} sauf +dans le cas où le second facteur ne comporte qu'un seul chiffre. +\begin{CenterExample}[xrightmargin=0pt] + \opmul{3.14159}{4}\qquad + \opmul[displayintermediary=nonzero]{3.14159}{4} +\end{CenterExample} + +Le paramètre \parameter{hfactor} permet d'indiquer comment doit se +faire l'alignement des opérandes. La valeur par défaut \texttt{right} +donne une composition au fer à droite tandis que la valeur +\texttt{decimal} donne un alignement au niveau de la virgule. +\begin{CenterExample}[xrightmargin=0pt] + \opmul{3.1416}{12.8}\qquad\opmul[hfactor=decimal]{3.1416}{12.8} +\end{CenterExample} + +Pour la multiplication posée, le paramètre \parameter{deletezero} ne +concerne que les opérandes, le résultat gardant ses éventuels zéros +non significatifs puisque ceux-ci sont nécessaires pour effectuer +correctement le décalage de la virgule lorsqu'on travaille \og à la +main \fg{}. +\begin{CenterExample}[xrightmargin=0pt] + \opmul[deletezero=false]{01.44}{25}\qquad + \opmul{01.44}{25} +\end{CenterExample} +En revanche, dans la multiplication en ligne, ce paramètre retrouve +son comportement normal. +\begin{CenterExample}[xrightmargin=0pt] + \opmul[deletezero=false,style=text]{01.44}{25}\qquad + \opmul[style=text]{01.44}{25} +\end{CenterExample} + +\section{Division} +\label{sec:Division} +L'extension gère la division \og classique \fg{} avec la macro +\macro{opdiv} et la division euclidienne avec la macro +\macro{opidiv}. En raison de sa complexité, la division est l'opération +qui prend en compte le plus de paramètres. + +\subsection{Contrôle de l'arrêt} +\label{subsec:Controle de l'arret} +Dans ce qui suivra, le terme d'\emph{étape} indique l'ensemble des +calculs permettant d'obtenir un chiffre au niveau du quotient. Ce +nombre d'étapes est contrôlé en partie par les paramètres +\parameter{maxdivstep}, \parameter{safedivstep} et \parameter{period}. +En partie seulement car une division classique s'arrêtera +automatiquement lors de l'obtention d'un reste nul, quelles que que +soient les valeurs de ces trois paramètres et une division euclidienne +s'arrêtera sur un quotient entier, sans tenir compte de ces trois +paramètres. +\begin{SideBySideExample} + \opdiv{25}{7} +\end{SideBySideExample} +\begin{SideBySideExample} + \opidiv{25}{7} +\end{SideBySideExample} +Le premier exemple s'arrête en raison de la valeur de +\parameter{maxdivstep} qui est égale, par défaut, à~10. On prendra +garde à ce que le nombre maximum d'étapes peut entraîner des résultats +aberrants lorsqu'il est trop faible. +\begin{SideBySideExample} + \opdiv[maxdivstep=2]{1248}{3} +\end{SideBySideExample} +Le résultat précédent est clairement faux mais \package{xlop} a fait +ce qu'on lui a demandé, en l'occurrence avoir deux chiffres (maximum) +au quotient. + +L'affichage en ligne va également différer selon que la division s'est +arrêtée avec un reste final nul ou non ou selon qu'il s'agit d'une +division classique ou euclidienne. +\begin{SideBySideExample} + \opdiv[style=text]{3.14}{2}\par + \opdiv[style=text]{3.14}{3}\par + \opidiv[style=text]{314}{2}\par + \opidiv[style=text]{314}{3} +\end{SideBySideExample} +On notera l'emploi de \parameter{equalsymbol} ou +\parameter{approxsymbol} selon le cas ainsi que l'affichage avec une +troncature et non un arrondi. Nous verrons comment obtenir un arrondi +à la section~\ref{sec:Operations evoluees} + +L'affichage en ligne de \verb+\opdiv+ tient compte de +\parameter{maxdivstep}. Cela signifie que l'on peut obtenir des +résultats vraiment faux avec des valeurs trop faible de ce paramètre +et, contrairement à l'affichage posé, l'affichage en ligne ne +permettra pas de comprendre ce qu'il s'est passé. +\begin{SideBySideExample} + \opdiv[maxdivstep=2,style=text] + {1248}{3} +\end{SideBySideExample} +Si en plus, le dernier reste calculé est nul, on atteint un summum : +\begin{SideBySideExample} + \opdiv[maxdivstep=1,style=text] + {1208}{3} +\end{SideBySideExample} +puisqu'il n'y a même plus d'approximation ! + +Une division non euclidienne peut également s'arrêter sur la détection +de la survenue d'une période. Pour cela, il suffit de donner la valeur +\texttt{true} au paramètre \parameter{period}. +\begin{SideBySideExample} + \opdiv[period]{100}{3} +\end{SideBySideExample} + +Pour ne pas avoir à effectuer des comparaisons de chaque reste avec +tous les restes précédents, \package{xlop} calcule dès le départ la +longueur de la période ce qui permet de n'effectuer qu'une seule +comparaison à chaque étape et donc d'accélérer notablement les +calculs\footnote{Je remercie à cette occasion Olivier Viennet pour ses + précisions mathématiques qui ont permis d'implanter correctement ces + calculs.}. Malheureusement, ces calculs se font avec des nombres +directement accessibles à \TeX{} ce qui a pour conséquence de ne pas +pouvoir utiliser d'opérandes dont la valeur absolue excède +$\left\lfloor\frac{2^{31}-1}{10}\right\rfloor = 214748364$. + +Pour ne pas entraîner des calculs trop long, \package{xlop} ne +dépassera pas la valeur du paramètre \parameter{safedivstep} dans les +divisions avec détection de période. Sa valeur par défaut est égale +à~50. Cependant, \package{xlop} signalera le problème. Par exemple si +on demande un tel calcul avec le code : +\begin{Verbatim}[xrightmargin=0pt,frame=none] + \opdiv[period]{1}{289} +\end{Verbatim} +on obtiendra le message d'avertissement : +\begin{Verbatim}[xrightmargin=0pt,frame=none] + xlop warning. Period of division is too big (272 > safedivstep). + Division will stop before reach it. + See documentation for further information. +\end{Verbatim} +qui indique que la période de cette division est de~272 et qu'elle ne +sera donc pas atteinte à cause de la valeur de \texttt{safedivstep}. + +L'affichage en ligne d'une telle division présente quelque +particularités. +\begin{SideBySideExample} + \opdiv[period,style=text]{150}{7} +\end{SideBySideExample} +On obtient donc une égalité au lieu d'une approximation, la présence +d'un trait sous la période et des points de suspension à la suite de +la période. Tous ces éléments peuvent être configurés. Le symbole +d'égalité est donné par le paramètre \parameter{equalsymbol} (valeur +par défaut \verb+{$=$}+), la largeur du trait par le paramètre +\parameter{hrulewidth} (valeur par défaut \texttt{0.4pt}), sa position +verticale par le paramètre \parameter{vruleperiod} (valeur par défaut +\texttt{-0.2}) qui indique un décalage vertical en prenant +\verb+\oplineheight+ comme unité et les points de suspension sont +donnés par le paramètre \parameter{afterperiodsymbol} (valeur par +défaut \verb+$\ldots$+). +\begin{SideBySideExample} + \opdiv[period,style=text, + equalsymbol=$\approx$, + hrulewidth=0.2pt, + vruleperiod=0.7, + afterperiodsymbol=] + {150}{7} +\end{SideBySideExample} + +\subsection{Éléments supplémentaires} +\label{subsec:Elements supplementaires} +Les divisions posées peuvent comporter les soustractions successives +permettant le calcul des restes. Pour \package{xlop}, les nombres qui +sont soustraits sont des nombres intermédiaires donc les différentes +façons de représenter les soustractions utiliserons le paramètre +\parameter{displayintermediary} déjà vu pour la multiplication. La +valeur \texttt{none} (défaut) n'affichera aucune soustraction, la +valeur \texttt{all} affichera toutes les soustractions et la valeur +\texttt{nonzero} affichera les soustractions avec un nombre non nul. +\begin{CenterExample}[xrightmargin=0pt] + \opdiv[displayintermediary=none,voperation=top] + {251}{25}\quad + \opdiv[displayintermediary=nonzero,voperation=top] + {251}{25}\quad + \opdiv[displayintermediary=all,voperation=top] + {251}{25} +\end{CenterExample} + +Lorsqu'on pose une division, on peut dessiner un \og pont \fg{} +au-dessus de la partie du dividende qui sera prise en compte pour la +première étape du calcul. L'extension \package{xlop} permet d'afficher +ce symbole grâce au paramètre booléen \parameter{dividendbridge} +(valeur par défaut \texttt{false}). +\begin{SideBySideExample} + \opdiv[dividendbridge]{1254}{30} +\end{SideBySideExample} + +\subsection{Nombres non entiers et négatifs} +\label{subsec:Nombres non entiers et negatifs} +La présentation d'opérandes non entières est gérée par le paramètre +\parameter{shiftdecimalsep}. Sa valeur par défaut est \texttt{both} et +indique que le séparateur décimal sera décalé pour obtenir un diviseur +et un dividende entiers. La valeur \texttt{divisor} indique qu'il y +aura le décalage nécessaire pour obtenir un diviseur entier et la +valeur \texttt{none} indique qu'il n'y aura aucun décalage. +\begin{CenterExample}[xrightmargin=0pt] + \opdiv[shiftdecimalsep=both]{3.456}{25.6}\quad + \opdiv[shiftdecimalsep=divisor]{3.456}{25.6}\quad + \opdiv[shiftdecimalsep=none]{3.456}{25.6} +\end{CenterExample} + +Un symbole indiqué par le paramètre \parameter{strikedecimalsepsymbol} +est réservé pour montrer l'ancien emplacement de la virgule lorsqu'on +effectue un décalage. La valeur par défaut de ce paramètre est vide ce +qui fait que l'on ne voyait rien sur les exemples précédents. +\begin{CenterExample}[xrightmargin=0pt] + \opset{strikedecimalsepsymbol={\rlap{,}\rule[-1pt]{3pt}{0.4pt}}} + \opdiv[shiftdecimalsep=both]{3.456}{25.6}\quad + \opdiv[shiftdecimalsep=divisor]{3.456}{25.6}\quad + \opdiv[shiftdecimalsep=none]{3.456}{25.6} +\end{CenterExample} + +La présence d'un symbole non vide pour le séparateur décimal barré +peut laisser les zéros non significatifs au niveau des opérandes. +\begin{SideBySideExample} + \opdiv[shiftdecimalsep=divisor, + strikedecimalsepsymbol=% + \hspace{-3pt}\tiny$\times$] + {0.03456}{2.56} +\end{SideBySideExample} + +Comme nous l'avons déjà vu, la macro \macro{opidiv} donne un quotient +entier, cela même si les opérandes sont non entières. Il est un peu +bizarre de vouloir réaliser une division euclidienne sur des nombres +non entiers et la macro \macro{opidiv} sera assez stricte sur sa +présentation. Les paramètres \parameter{maxdivstep}, +\parameter{safedivstep} et \parameter{period} seront sans effet ainsi +que le paramètre \parameter{shiftdecimalsep}, les deux opérandes étant +rendues entières. +\begin{SideBySideExample} + \opidiv[strikedecimalsepsymbol=% + \hspace{-3pt}\tiny$\times$] + {34.57}{7} +\end{SideBySideExample} + +Lorsque les opérandes sont négatives, l'affichage en ligne de +\macro{opidiv} différera des données obtenues avec l'affichage +posée. Le reste sera nécessairement un nombre compris entre zéro +(inclus) et la valeur absolue du diviseur (exclu). +\begin{SideBySideExample} + \opdiv[style=text]{124}{7}\par + \opidiv[style=text]{124}{7}\par + \opidiv[style=text]{124}{-7}\par + \opidiv[style=text]{-124}{7}\par + \opidiv[style=text]{-124}{-7} +\end{SideBySideExample} + +Cette condition sur le reste reste valable même avec un diviseur non +entier. +\begin{SideBySideExample} + \opidiv[style=text]{1.24}{0.7}\par + \opidiv[style=text]{1.24}{-0.7}\par + \opidiv[style=text]{-1.24}{0.7}\par + \opidiv[style=text]{-1.24}{-0.7} +\end{SideBySideExample} + +\chapter{Autres commandes} +\label{chap:Autres commandes} +\section{Macros étoilées} +\label{sec:Macros etoilees} +Les cinq macros vues au chapitre précédent ont une version +étoilée. Ces macros étoilées réalisent le calcul mais ne procèdent à +aucun affichage, le résultat étant stocké dans une variable donnée en +dernier argument. + +Comme ces commandes n'affichent rien, les paramètres ne seront pas +acceptés pour les macros \macro{opadd*}, \macro{opsub*}, +\macro{opmul*} et \macro{opidiv*}. En revanche, les paramètres +\parameter{maxdivestep}, \parameter{safedivstep} et \parameter{period} +influencent les calculs et la macro \macro{opdiv*} acceptera donc un +argument optionnel pour pouvoir en tenir compte. +\begin{SideBySideExample} + \opmul*{2}{2}{a}% + \opmul*{a}{a}{a}\opmul*{a}{a}{a}% + \opadd[style=text]{a}{1} +\end{SideBySideExample} +Pour les macros \macro{opdiv} et \macro{opidiv}, il y aura deux +arguments supplémentaires pour pouvoir recevoir le quotient et le +reste final. +\begin{SideBySideExample} + \opdiv*[maxdivstep=1]{-88}{16}{q}{r}% + \opmul*{q}{16}{bq}% + \opmul[style=text]{16}{q}\par + \opadd[style=text]{bq}{r} +\end{SideBySideExample} + +\section{Entrées-sorties} +\label{sec:Entree-sorties} +La macro \macro{opcopy} recopie son premier argument dans son deuxième +argument. Le premier argument est donc un nombre écrit sous forme +décimale ou via une variable alors que le second sera considérée comme +un nom de variable. + +La macro \macro{opprint} affiche son argument. L'exemple qui suit +utilise le compteur \macro{time} qui indique le nombre de minutes +écoulés depuis minuit. +\begin{SideBySideExample} + \opidiv*{\the\time}{60}{h}{m}% + Il est \opprint{h}~heures et + \opprint{m}~minutes +\end{SideBySideExample} +On verra à la section~\ref{sec:Comparaisons} comment améliorer cet +affichage avec des tests. + +La macro \macro{opdisplay} affiche également un nombre mais en +écrivant chaque chiffre dans une boîte de largeur donnée par +\parameter{columnwidth} et de hauteur donnée par +\parameter{lineheight}. Le style est spécifié par le premier argument +et cette macro accepte un argument optionnel pour permettre de donner +un style particulier aux chiffres individuels. +\begin{SideBySideExample} + \opdisplay[resultstyle.1=\bfseries, + resultstyle.-2=\bfseries] + {resultstyle}{129.192} +\end{SideBySideExample} + +Les macros \macro{oplput} et \macro{oprput} permettent de placer un +objet à un emplacement déterminé. La syntaxe de ces deux commandes ne +suit pas celle des autres macros de \package{xlop} puisque +l'emplacement est indiqué sous forme de coordonnées entre +parenthèses. Les coordonnées utilisent \macro{opcolumnwidth} et +\macro{oplineheight} comme unités ce qui permet à l'utilisateur de +construire lui-même ses propres \og opérations \fg. +\begin{SideBySideExample} + \psset{xunit=\opcolumnwidth, + yunit=\oplineheight}% + \psgrid[subgriddiv=1,gridlabels=7pt, + griddots=5](0,1)(10,-2) + \oplput(2,0){Bonjour} + \oprput(8,-1){le monde} + $\bullet$ +\end{SideBySideExample} +Sur l'exemple ci-dessus, on peut voir que ces deux macros ne modifient +pas le point de référence. Elles prennent même la précaution d'inhiber +l'espace automatique qui les suit pour qu'il ne soit pas nécessaire de +mettre un \verb+%+ en fin de ligne. + +Les macros \macro{ophline} et \macro{opvline} complète les deux +précédentes pour donner à l'utilisateur les outils lui permettant de +construire ses propres opérations. La macro \macro{ophline} permet de +placer un trait horizontal dont la longueur est donné par le paramètre +qui suit les coordonnées. La macro \macro{opvline} fait de même avec +les traits verticaux. On rappelle que les paramètres +\parameter{hrulewidth} et \parameter{vrulewidth} indiquent les +épaisseurs respectives de ces types de traits. +\begin{CenterExample}[xrightmargin=0pt] + \par\vspace{2\oplineheight} + \oplput(1,2){O}\oplput(2,2){N}\oplput(3,2){E} + \oplput(0,1.5){$+$} + \oplput(1,1){O}\oplput(2,1){N}\oplput(3,1){E} + \ophline(0,0.8){4} + \oplput(1,0){T}\oplput(2,0){W}\oplput(3,0){O} +\end{CenterExample} + +\section{Chiffres d'un nombre} +\label{sec:Chiffres d'un nombre} +Les macros \macro{opwidth}, \macro{opintegerwidth} et +\macro{opdecimalwidth} indiquent respectivement le nombre de chiffres +du nombre dans sa totalité, de sa partie entière et de sa partie +décimale. Le premier argument est le nombre sur lequel s'effectue le +comptage et le second argument indique la variable où sera stocké le +résultat. +\begin{SideBySideExample} + \opcopy{123456.1234}{a}% + \opwidth{a}{na}% + \opintegerwidth{a}{ia}% + \opdecimalwidth{a}{da}% + \opprint{a} s'\'ecrit avec \opprint{na} + chiffres (\opprint{ia} en partie + enti\`ere et \opprint{da} en partie + d\'ecimale). +\end{SideBySideExample} + +La macro \macro{opunzero} permet de supprimer les zéros non +significatifs\index{zeros non significatifs@zéros non significatifs} +du nombre passé en argument. +\begin{SideBySideExample} + \opcopy{00150.00250}{a}% + Avant : \opprint{a}\par + \opunzero{a}% + Apr\`es : \opprint{a} +\end{SideBySideExample} + +Les macros \macro{integer} et \macro{opdecimal} donnent respectivement +la partie entière et la partie décimale d'un nombre. Le premier +argument est le nombre à traiter et le second est la variable qui +contiendra le résultat. +\begin{SideBySideExample} + \opcopy{-37.69911}{a}% + \opinteger{a}{ia}% + \opdecimal{a}{da}% + Partie enti\`ere : \opprint{ia}\par + Partie d\'ecimale : \opprint{da} +\end{SideBySideExample} + +Six macros servent à écrire ou lire un chiffre d'un nombre. On peut +lire ou écrire un chiffre selon son rang dans le nombre, dans sa +partie entière ou dans sa partie décimale. Les chiffres pour le nombre +dans sa totalité ou pour sa partie entière sont numérotés de droite à +gauche et, pour sa partie décimale de gauche à droite. Ainsi, avec le +nombre 1234,56789, le deuxième chiffre est 8, le deuxième chiffre de +sa partie entière est 3 et le deuxième chiffre de sa partie décimale +est 6. Il est alors facile de deviner le rôle respectif des six macros +: +\begin{itemize} +\item \parameter{opgetdigit} ; +\item \parameter{opsetdigit} ; +\item \parameter{opgetintegerdigit} ; +\item \parameter{opsetintegerdigit} ; +\item \parameter{opgetdecimaldigit} ; +\item \parameter{opsetdecimaldigit} ; +\end{itemize} +La syntaxe est la même pour ces six macros. Le premier argument est le +nombre sur lequel doit porter la lecture ou l'écriture, le deuxième +argument est l'index donnant la position du chiffre et le troisième +argument est le nom de la variable qui contiendra le chiffre lu ou +bien ce qui devra être écrit. Si l'index est en dehors du nombre, les +macros de lecture donneront \texttt{0} comme résultat et les macros +d'écriture étendront le nombre pour pouvoir atteindre cet index en +créant des zéros dans les nouvelles positions. + +\section{Comparaisons} +\label{sec:Comparaisons} +Lorsqu'on désire concevoir des macros évoluées, il est très souvent +utile de pouvoir réaliser des tests. Pour cela, \package{xlop} met à +disposition la macro \macro{opcmp} dont les deux arguments sont des +nombres et qui mettra à jour les tests \macro{ifopgt}, \macro{ifopge}, +\macro{ifople}, \macro{ifoplt}, \macro{ifopeq} et \macro{ifopneq} pour +respectivement indiquer que la première opérande est strictement +supérieure, supérieure, inférieure, strictement inférieure, égale ou +différente de la seconde opérande. + +Pour des raisons techniques, \package{xlop} donne des définitions +globales aux six tests précédents. Ceux-ci ne seront donc pas protégés +par les groupes. Comme ces tests sont utilisés par un grand nombre de +macros de \package{xlop}, une conséquence pratique est qu'il faut +\textbf{toujours} réaliser les tests \verb+\ifop...+ immédiatement +après le \macro{opcmp}, ou, du moins, avant toute autre utilisation de +macros de \package{xlop} sous peine de bogues éventuels difficiles à +comprendre ! + +On va reprendre la macro d'affichage de l'heure donnée à la +section~\ref{sec:Entree-sorties} mais en vérifiant si l'argument est +compris entre~0 (inclus) et~1440 (exclu) puis en réalisant les tests +nécessaires pour voir si \og heure \fg{} doit être ou non au pluriel +ainsi que \og minute \fg{}. + +\begin{CenterExample}[xrightmargin=0pt] + \newcommand\heure[1]{% + \opcmp{#1}{0}\ifopge + \opcmp{#1}{1440}\ifoplt + \opidiv*{#1}{60}{h}{m}% + \opprint{h} heure% + \opcmp{h}{1}\ifopgt + s% + \fi + \opcmp{m}{0}\ifopneq + \space\opprint{m} minute% + \opcmp{m}{1}\ifopgt + s% + \fi + \fi + \fi\fi + } + \heure{60} -- \heure{1080} -- \heure{1081} -- \heure{1082} +\end{CenterExample} + +\section{Opérations évoluées} +\label{sec:Operations evoluees} +Les macros qui nous restent à voir proviennent soit de commandes +utilisées de façon interne et qu'il aurait été dommage de ne pas +rendre publiques, soit de demandes d'utilisateurs. + +Les macros utilisées de façon interne sont \macro{opgcd} qui donne le +pgcd de deux nombres et \macro{opdivperiod} qui donne la longueur de +la période d'un quotient de deux nombres. Pour des raisons +d'efficacité, ces macros n'utilisent pas les nombres de \package{xlop} +mais des nombres directement accessibles à \TeX{}. Cela a pour +conséquence que les nombres passés en paramètres dans les deux +premiers arguments ne devront pas excéder \texttt{2147483647} pour +\macro{opgcd} et \texttt{214748364} pour \macro{opdivperiod}. Un +message d'avertissement rappellera à l'ordre en cas de dépassement. Le +résultat sera stocké dans la variable indiqué en troisième paramètre. + +Il y aura également quelques vérifications sur les deux premiers +paramètres. Un pgcd ne peut pas avoir d'argument nul et le calcul de +la longueur d'une période ne pourra pas se faire avec un quotient +nul. D'autre part, si un nombre non entier est passé en paramètre, +seule la partie entière sera prise en compte. +\begin{SideBySideExample} + \opcopy{5376}{a}% + \opcopy{2304}{b}% + \opgcd{a}{b}{gcd(ab)}% + \newcommand\pgcd{% + \mathop{\mathrm{pgcd}}}% + $\pgcd(\opprint{a},\opprint{b}) = + \opprint{gcd(ab)}$ +\end{SideBySideExample} +Si vous voulez vous amuser à trouver de grandes périodes de divisions, +sans entrer dans les détails mathématiques, les carrés de nombres +premiers sont de bons candidats. Par exemple, avec $257^2=66049$ on +trouve : +\begin{SideBySideExample} + \opdivperiod{1}{66049}{p}% + $\frac{1}{66049}$ a une p\'eriode + de longueur $\opprint{p}$. +\end{SideBySideExample} + +Les macros \macro{opcastingoutnines} et \macro{opcastingoutelevens} +vont permettre de composer des preuves par neuf et par onze. +L'extension \package{xlop} ne propose pas directement ces compositions +puisqu'elles nécessitent des traits en diagonal et donc le recours à +d'autres extensions. En réalité, la macro \macro{opcastingoutnines} va +faire la somme modulo~9 des chiffres du premier argument et stockera +le résultat dans le second argument tandis que la macro +\macro{opcastingoutelevens} fera la somme des chiffres de rangs +impairs, la somme des chiffres de rangs pairs puis la différence +modulo~11 de ces deux sommes. +\begin{SideBySideExample} + \newcommand\castingoutnines[3]{% + \opcastingoutnines{#1}{cna}% + \opcastingoutnines{#2}{cnb}% + \opmul*{cna}{cnb}{cna*cnb} + \opcastingoutnines{cna*cnb}{cna*cnb}% + \opcastingoutnines{#3}{cn(a*b)}% + \begin{pspicture}(-3.5ex,-3.5ex)% + (3.5ex,3.5ex) + \psline(-3.5ex,-3.5ex)(3.5ex,3.5ex) + \psline(-3.5ex,3.5ex)(3.5ex,-3.5ex) + \rput(-2.75ex,0){\opprint{cna}} + \rput(2.75ex,0){\opprint{cnb}} + \rput(0,2.75ex){\opprint{cna*cnb}} + \rput(0,-2.75ex){\opprint{cn(a*b)}} + \end{pspicture} + } + \castingoutnines{157}{317}{49669} +\end{SideBySideExample} +Incidemment, cet exemple montre que $157\times317\neq49669$ ! La +réponse correcte est \opmul[style=text]{157}{317}. + +Les deux macros suivantes sont très simples. Il s'agit de +\macro{opneg} qui calcul l'opposé de son premier argument et le +sauvegarde dans la variable indiquée par le second argument et de +\macro{opabs} qui réalise la même chose mais avec la valeur absolue. + +La macro \macro{oppower} permet de calculer des puissances entières de +nombres. Cette macro demande trois paramètres, le troisième paramètre +étant la variable recevant le résultat du premier paramètre à la +puissance le deuxième paramètre. Le deuxième paramètre doit être un +nombre entier. Lorsque le premier argument est nul, si le deuxième +paramètre est nul, le résultat sera~1, s'il est strictement positif, +le résultat sera nul et s'il est strictement négatif il y aura une +erreur et aucun résultat ne sera fourni. Il n'y a aucune limitation +sur le premier paramètre ce qui peut entraîner quelques problèmes. Par +exemple : +\begin{CenterExample}[xrightmargin=0pt] + \opcopy{0.8}{a}\opcopy{-17}{n}% + \oppower{a}{n}{r}% + $\opprint{a}^{\opprint{n}} = \opprint{r}$ +\end{CenterExample} +Avec $0{,}7$ au lieu de $0{,}8$, le problème aurait été encore pire : +\begin{CenterExample}[xrightmargin=0pt] + \opcopy{0.7}{a}\opcopy{-8}{n}% + \oppower{a}{n}{r}% + \opdecimalwidth{r}{dr} + $\opprint{a}^{\opprint{n}}$ a \opprint{dr} chiffres apr\`es la + virgule. +\end{CenterExample} +Tout cela est dû au fait que lorsque l'exposant est négatif, +\package{xlop} calcule \emph{d'abord} l'inverse du nombre pour +\emph{ensuite} calculer la puissance avec l'opposé de l'exposant. Si +on avait laissé $-17$ au lieu de $-8$ dans l'exemple précédent, les +capacités de \TeX{} auraient été dépassées. + +Les trois macros qui suivent permettent de contrôler la précision des +nombres manipulés. Elles permettent de construire un nombre en donnant +une valeur approchée par défaut, par excès ou un arrondi d'un nombre +donné en précisant le rang où devra se faire l'arrondi. Ces macros +sont respectivement \macro{opfloor}, \macro{opceil} et +\macro{opround}. Elles demandent trois paramètres qui seront dans +l'ordre le nombre de départ, le rang de l'arrondi et le nom de la +variable qui contiendra le résultat. + +Le rang est indiqué par une valeur entière donnant le nombre de +chiffres après la virgule qui doivent être présents. Si le rang est +négatif, l'arrondi se fera avant la virgule. Si le rang positif +indique plus de chiffres que la partie décimale n'en a, des zéros +seront ajoutés. Si le rang négatif indique plus de chiffres que la +partie entière n'en a, l'arrondi restera bloqué pour donner au moins +le premier chiffre du nombre. + +Voici un tableau récapitulatif pour mieux comprendre le fonctionnement +de ces trois macros. +\begin{center} + \opcopy{3838.3838}{a} + \begin{tabular}{|r|l|l|l|} + \hline + \multicolumn{4}{|c|}{\textbf{\texttt{\textbackslash + op\ldots{}\{3838.3838\}\{n\}\{r\}}}}\\\hline + \multicolumn{1}{|c|}{\textbf{\texttt{n}}} & + \multicolumn{1}{c|}{\textbf{\texttt{floor}}} & + \multicolumn{1}{c|}{\textbf{\texttt{ceil}}} & + \multicolumn{1}{c|}{\textbf{\texttt{round}}} \\\hline + \opcopy{6}{n}$\opprint{n}$ & + \opfloor{a}{n}{r}$\opprint{r}$ & + \opceil{a}{n}{r}$\opprint{r}$ & + \opround{a}{n}{r}$\opprint{r}$ \\ + \opcopy{4}{n}$\opprint{n}$ & + \opfloor{a}{n}{r}$\opprint{r}$ & + \opceil{a}{n}{r}$\opprint{r}$ & + \opround{a}{n}{r}$\opprint{r}$ \\ + \opcopy{3}{n}$\opprint{n}$ & + \opfloor{a}{n}{r}$\opprint{r}$ & + \opceil{a}{n}{r}$\opprint{r}$ & + \opround{a}{n}{r}$\opprint{r}$ \\ + \opcopy{0}{n}$\opprint{n}$ & + \opfloor{a}{n}{r}$\opprint{r}$ & + \opceil{a}{n}{r}$\opprint{r}$ & + \opround{a}{n}{r}$\opprint{r}$ \\ + \opcopy{-1}{n}$\opprint{n}$ & + \opfloor{a}{n}{r}$\opprint{r}$ & + \opceil{a}{n}{r}$\opprint{r}$ & + \opround{a}{n}{r}$\opprint{r}$ \\ + \opcopy{-2}{n}$\opprint{n}$ & + \opfloor{a}{n}{r}$\opprint{r}$ & + \opceil{a}{n}{r}$\opprint{r}$ & + \opround{a}{n}{r}$\opprint{r}$ \\ + \opcopy{-6}{n}$\opprint{n}$ & + \opfloor{a}{n}{r}$\opprint{r}$ & + \opceil{a}{n}{r}$\opprint{r}$ & + \opround{a}{n}{r}$\opprint{r}$ \\\hline + \end{tabular} + \opcopy{-3838.3838}{a} + \begin{tabular}{|r|l|l|l|} + \hline + \multicolumn{4}{|c|}{\textbf{\texttt{\textbackslash + op\ldots{}\{-3838.3838\}\{n\}\{r\}}}}\\\hline + \multicolumn{1}{|c|}{\textbf{\texttt{n}}} & + \multicolumn{1}{c|}{\textbf{\texttt{floor}}} & + \multicolumn{1}{c|}{\textbf{\texttt{ceil}}} & + \multicolumn{1}{c|}{\textbf{\texttt{round}}} \\\hline + \opcopy{6}{n}$\opprint{n}$ & + \opfloor{a}{n}{r}$\opprint{r}$ & + \opceil{a}{n}{r}$\opprint{r}$ & + \opround{a}{n}{r}$\opprint{r}$ \\ + \opcopy{4}{n}$\opprint{n}$ & + \opfloor{a}{n}{r}$\opprint{r}$ & + \opceil{a}{n}{r}$\opprint{r}$ & + \opround{a}{n}{r}$\opprint{r}$ \\ + \opcopy{3}{n}$\opprint{n}$ & + \opfloor{a}{n}{r}$\opprint{r}$ & + \opceil{a}{n}{r}$\opprint{r}$ & + \opround{a}{n}{r}$\opprint{r}$ \\ + \opcopy{0}{n}$\opprint{n}$ & + \opfloor{a}{n}{r}$\opprint{r}$ & + \opceil{a}{n}{r}$\opprint{r}$ & + \opround{a}{n}{r}$\opprint{r}$ \\ + \opcopy{-1}{n}$\opprint{n}$ & + \opfloor{a}{n}{r}$\opprint{r}$ & + \opceil{a}{n}{r}$\opprint{r}$ & + \opround{a}{n}{r}$\opprint{r}$ \\ + \opcopy{-2}{n}$\opprint{n}$ & + \opfloor{a}{n}{r}$\opprint{r}$ & + \opceil{a}{n}{r}$\opprint{r}$ & + \opround{a}{n}{r}$\opprint{r}$ \\ + \opcopy{-6}{n}$\opprint{n}$ & + \opfloor{a}{n}{r}$\opprint{r}$ & + \opceil{a}{n}{r}$\opprint{r}$ & + \opround{a}{n}{r}$\opprint{r}$ \\\hline + \end{tabular} +\end{center} + +La dernière macro qui nous reste à voir est \macro{opexpr} qui permet +de réaliser le calcul d'une expression complexe. Cette macro demande +deux paramètres : le premier est l'expression à calculer donnée sous +forme infixe (la forme habituelle pour un humain) et le second est le +nom de la variable qui contiendra le résultat. + +Initialement, la formule devait être donnée sous forme polonaise +inverse (la notation des calculatrices HP ou du langage PostScript par +exemple) mais un travail commun avec Christophe Jorssen a finalement +abouti à la possibilité de donner l'expression sous une forme plus +agréable pour l'utilisateur. + +Les formules acceptent les opérateurs arithmétiques habituels +\texttt{+}, \texttt{-}, \texttt{*} et \texttt{/} ainsi que l'opérateur +\texttt{:} pour la division euclidienne et \verb+^+ pour +l'exponentiation. L'opérateur \texttt{-} a les deux rôles d'opérateur +binaire de la soustraction et d'opérateur unaire pour l'opposé. +L'opérateur \texttt{+} a également les deux rôles d'opérateur binaire +de l'addition et d'opérateur unaire ne faisant \ldots{} rien ! Les +opérandes sont écrites sous forme décimale ou par l'intermédiaire de +nom de variable cependant, la macro \macro{opexpr} va introduire une +petite restriction sur les noms de variables puisque ceux-ci devront +être différents des noms de fonctions reconnus par cette macro. Les +fonctions accessibles sont : +\begin{itemize} +\item \texttt{abs(a)} ; +\item \texttt{ceil(a,i)} ; +\item \texttt{decimal(a)} ; +\item \texttt{floor(a,i)} ; +\item \texttt{gcd(a,b)} ; +\item \texttt{integer(a)} ; +\item \texttt{mod(a,b)} qui donne le résultat de \texttt{a} modulo + \texttt{b} ; +\item \texttt{rest(a,b)} qui donne le reste de la division de + \texttt{a} par \texttt{b} (la différence entre reste et modulo est + la différence qui existe entre division non euclidienne et division + euclidienne) ; +\item \texttt{round(a,i)}. +\end{itemize} +où les fonctions non décrites ci-dessus font appel aux macros +correspondantes (la fonction \texttt{xxx} faisant appel à la macro +\verb+\opxxx+). Pour les fonctions \texttt{ceil}, \texttt{floor} et +\texttt{round}, le nombre \texttt{i} indique le rang sur lequel doit +se faire l'arrondi. + +La macro \macro{opexpr} accepte un argument optionnel puisqu'elle peut +réaliser des divisions et que ces divisions doivent pouvoir être +contrôlées via les paramètres \parameter{maxdivstep}, +\parameter{safedivstep} et \parameter{period}. +Notre premier exemple est assez basique : +\begin{CenterExample}[xrightmargin=0pt] + \opexpr{3--gcd(15*17,25*27)*2}{r}% + $3--\gcd(15\times17,25\times27)\times2 = \opprint{r}$ +\end{CenterExample} + +Voici un autre exemple montrant que des données peuvent provenir d'une +macro : +\begin{CenterExample}[xrightmargin=0pt] + \newcommand\try{2}% + \opexpr{\try+1/ + (\try+1/ + (\try+1/ + (\try+1/ + (\try+1/ + (\try)))))}{r} + La fraction continue de base $u_n=2$ vaut \opprint{r} au rang~5. +\end{CenterExample} + +\appendix +\chapter{Aide-mémoire} +\label{chap:Aide-mémoire} +\section{Temps de compilation} +\label{sec:Temps de compilation} +Les temps de compilation ont été mesurés sur une machine à processeur +Pentium~II~600\,MHz ayant 256\,Mo de RAM et tournant sous linux +(Debian woody). Le principe a été de faire un fichier TeX{} minimum +dont le schéma général est donné par : +\begin{verbatim} + \input xlop + \count255=0 + \loop + \ifnum\count255<1000 + <opération à tester> + \advance\count255 by1 + \repeat + \bye +\end{verbatim} +Le temps de compilation avec \verb+<opération à tester>+ vide a été +soustrait des autres tests et seul le temps utilisateur a été pris en +compte. Les résultats sont donnés en millisecondes et sont évidemment +à prendre avec beaucoup de précautions. + +\index{compilation (temps de)|(}\index{temps de calcul|(}% +Le tableau suivant donne le temps de compilation des opérations en +millisecondes. Les opérandes utilisées l'ont été avec une écriture +sous forme de chiffres mais des essais avec des opérandes sous forme +de noms de variable ont montré que les différences étaient vraiment +minimes. + +La première ligne indique le nombre de chiffres des deux +opérandes. Ces nombres ont été construits de la façons suivantes : +\begin{itemize} +\item $\mathrm{A} = 1$ et $\mathrm{B} = 9$ pour un chiffre ; +\item $\mathrm{A} = 12$ et $\mathrm{B} = 98$ pour deux chiffres ; +\item $\mathrm{A} = 123$ et $\mathrm{B} = 987$ pour trois chiffres ; +\item $\mathrm{A} = 12345$ et $\mathrm{B} = 98765$ pour cinq chiffres ; +\item $\mathrm{A} = 1234567890$ et $\mathrm{B} = 9876543210$ pour dix + chiffres ; +\item $\mathrm{A} = 12345678901234567890$ et $\mathrm{B} = + 98765432109876543210$ pour vingt chiffres ; +\end{itemize} +Voici les résultats, quelques commentaires suivront : + +\bigskip\noindent\hbox to\linewidth{\hss + \begin{tabular}{|r|*{6}{l|}} + \cline{2-7} + \multicolumn{1}{l|}{} & + \multicolumn{1}{c|}{1} & + \multicolumn{1}{c|}{2} & + \multicolumn{1}{c|}{3} & + \multicolumn{1}{c|}{5} & + \multicolumn{1}{c|}{10} & + \multicolumn{1}{c|}{20} \\\hline + \verb+\opadd*{A}{B}{r}+ & + 1.1 & 1.4 & 1.6 & 2.1 & 3.3 & 5.8 \\\cline{2-7} + \verb+\opadd*{B}{A}{r}+ & + 1.1 & 1.4 & 1.6 & 2.1 & 3.3 & 5.8 \\\hline + \verb+\opsub*{A}{B}{r}+ & + 1.7 & 2.1 & 2.4 & 3.0 & 4.8 & 8.3 \\\cline{2-7} + \verb+\opsub*{B}{A}{r}+ & + 1.5 & 1.7 & 2.0 & 2.6 & 4.0 & 7.0 \\\hline + \verb+\opmul*{A}{B}{r}+ & + 4.6 & 6.3 & 8.2 & 12.8 & 29.9 & 87.0 \\\cline{2-7} + \verb+\opmul*{B}{A}{r}+ & + 5.0 & 6.6 & 8.5 & 13.2 & 30.3 & 87.8 \\\hline + \verb+\opdiv*{A}{B}{q}{r}+ & + 46.4 & 53.8 & 53.8 & 64.3 & 85.8 & 124.7 \\\cline{2-7} + \verb+\opdiv*{B}{A}{q}{r}+ & + 12.4 & 48.9 & 55.7 & 58.6 & 72.8 & 111.0 \\\hline + \verb+\opdiv*[maxdivstep=5]{A}{B}{q}{r}+ & + 26.8 & 30.0 & 32.6 & 37.6 & 49.5 & 73.5 \\\cline{2-7} + \verb+\opdiv*[maxdivstep=5]{B}{A}{q}{r}+ & + 12.4 & 29.1 & 32.6 & 35.2 & 43.3 & 67.9 \\\hline + \verb+\opidiv*{A}{B}{q}{r}+ & + 10.8 & 12.2 & 13.5 & 16.0 & 22.3 & 35.5 \\\cline{2-7} + \verb+\opidiv*{B}{A}{q}{r}+ & + 11.6 & 13.0 & 14.2 & 16.6 & 23.0 & 36.7 \\\hline + \verb+\opidiv*{A}{2}{q}{r}+ & + 10.7 & 12.0 & 15.3 & 22.3 & 42.9 & 83.0 \\\hline + \end{tabular} + \hss +} +\par\bigskip +Il est normal que l'inversion des opérandes n'ait aucune influence +pour l'addition. Il peut alors sembler anormal qu'elle en ait une pour +la soustraction mais en fait, avoir une seconde opérande supérieure à +la première va entraîner quelques instructions supplémentaires (double +inversion, gestion plus longue du signe du résultat). + +Il est normal que le temps de la division soit supérieur à celui de la +multiplication. Il peut alors sembler anormal que la division ait +l'air de \og rattraper \fg{} son retard. En fait, une multiplication +voit sa complexité fortement augmenter avec la taille des opérandes +mais la division normale est bloquée par le paramètre +\parameter{maxdivstep}. On le voit bien sur l'exemple où on limite ce +maximum à 5~étapes. + +Quelques résultats semblent bizarres. Ainsi, +\verb+\opdiv*{9}{1}{q}{r}+ est anormalement rapide : cela est dû +au fait d'avoir un quotient à un seul chiffre. Plus bizarre encore, +\verb+\opdiv*{123}{987}{q}{r}+ est plutôt rapide. Ici, +l'explication est plus subtile : cela est dû à la présence de nombreux +zéros au quotient. + +Avec des opérandes de taille comparable, la division euclidienne est +très rapide par rapport à la division non euclidienne. Cela est dû au +fait que le quotient n'aura que peu de chiffres (un seul avec tous les +nombres \texttt{A} et \texttt{B}). La dernière ligne du tableau est +plus représentative des temps de compilation que l'on peut obtenir +avec cette opération. + +Toutes ces remarques sont faites pour bien insister sur la difficulté +à évaluer un temps de compilation a priori : il dépend de trop de +paramètres. Cela dit, le tableau permet d'avoir quand même une idée de +ce à quoi il faut s'attendre. +\index{compilation (temps de)|)}\index{temps de calcul|)} + +\section{Liste des macros} +\label{sec:Liste des macros} +\noindent\index{macros!table des|(}% +\begin{longtable}{|l|p{6.3cm}|} + \hline + \multicolumn{1}{|c|}{\textbf{Macro}} & + \multicolumn{1}{c|}{\textbf{Description}} \\\hline\hline + \endfirsthead + \hline + \multicolumn{1}{|c|}{\textbf{Macro}} & + \multicolumn{1}{c|}{\textbf{Description}} \\\hline\hline + \endhead + \hline + \multicolumn{2}{|c|}{$\ldots$ à suivre $\ldots$}\\ + \hline + \endfoot + \hline + \endlastfoot + \verb+\opabs{n}{N}+ & + \verb+N+ reçoit la valeur absolue de \verb+n+. \\\hline + \verb+\opadd[P]{n1}{n2}+ & + Affiche le résultat de l'opération \verb-n1+n2-. \\\hline + \verb+\opadd*{n1}{n2}{N}+ & + Calcule \verb-n1+n2- et place le résultat dans + \verb+N+. \\\hline + \verb+\opcastingoutelevens{n}{N}+ & + Calcule la différence (modulo 11) de la somme des chiffres de rang + impair et de la somme des chiffres de rang pair de \verb+n+ et + place le résultat dans \verb+N+. \\\hline + \verb+\opcastingoutnines{n}{N}+. & + Calcule la somme modulo 9 des chiffres de \verb+n+ et place le + résultat dans \verb+N+. \\\hline + \verb+\opceil{n}{T}{N}+ & + Place dans \verb+N+ la valeur approchée par excès de + \verb+n+ au rang \verb+T+. \\\hline + \verb+\opcmp{n1}{n2}+ & + Compare les nombres \verb+n1+ et \verb+n2+ et réalise la + mise à jour correspondante des tests \verb+\ifopeq+, + \verb+\ifopneq+, \verb+\ifopgt+, \verb+\ifopge+, + \verb+\ifople+ et \verb+\ifoplt+. \\\hline + \verb+\opcopy{n}{N}+ & + Copie le nombre \verb+n+ dans \verb+N+. \\\hline + \verb+\opdecimal{n}{N}+ & + Copie la partie décimale (nombre entier positif) de \verb+n+ + dans \verb+N+. \\\hline + \verb+\opdecimalwidth{n}{N}+ & + Le nombre \verb+N+ reçoit la largeur de la partie décimale du + nombre \verb+n+. \\\hline + \verb+\opdisplay[P]{S}{n}+ & + Affiche le nombre \verb+n+ avec le style \verb+S+ en + plaçant chaque chiffre dans une boîte de largeur + \verb+\opcolumnwidth+ et de hauteur + \verb+\oplineheight+. \\\hline + \verb+\opdiv[P]{n1}{n2}+ & + Affiche le résultat de l'opération n1/n2. \\\hline + \verb+\opdiv*[P]{n1}{n2}{N1}{N2}+ & + Calcule \verb+n1/n2+, place le quotient dans \verb+N1+ et + le reste dans \verb+N2+. \\\hline + \verb+\opdivperiod{T1}{T2}{N}+ & + Calcule la longueur de la période de la division de \verb+T1+ + par \verb+T2+ et place le résultat dans \verb+N+. \\\hline + \verb+\opexpr[P]{F}{N}+ & + \'Évalue la formule \texttt{F} est place le résultat final dans le + nombre \texttt{N}. \\\hline + \verb+\opfloor{n}{T}{N}+ & + Place dans \verb+N+ la valeur approchée par défaut de + \verb+n+ au rang \verb+T+. \\\hline + \verb+\opgcd{T1}{T2}{N}+ & + Calcule le pgcd de \verb+T1+ et \verb+T2+ et place le + résultat dans \verb+N+. \\\hline + \verb+\opgetdecimaldigit{n}{T}{N}+ & + Construit le nombre \verb+N+ avec le seul chiffre situé en + \verb+T+ième position de la partie décimale du nombre + \verb+n+. \\\hline + \verb+\opgetdigit{n}{T}{N}+ & + Construit le nombre \verb+N+ avec le seul chiffre situé en + \verb+T+ième position du nombre \verb+n+. \\\hline + \verb+\opgetintegerdigit{n}{T}{N}+ & + Construit le nombre \verb+N+ avec le seul chiffre situé en + \verb+T+ième position de la partie entière du nombre + \verb+n+. \\\hline + \verb+\ophline(T1,T2){T3}+ & + Trace un trait horizontal de longueur \verb+T3+, d'épaisseur + \verb+hrulewidth+ et débutant en \verb+(T1,T2)+ par + rapport au point de référence. \\\hline + \verb+\opidiv[P]{n1}{n2}+ & + Affiche le résultat de l'opération \verb+n1/n2+ (division + euclidienne, c'est-à-dire avec un quotient entier). \\\hline + \verb+\opidiv*{n1}{n2}{N1}{N2}+ & + Calcule \verb+n1/n2+ (division euclidienne), place le quotient + (entier) dans \verb+N1+ et le reste (compris entre 0 inclus et + \verb+|n2|+ exclu) dans \verb+N2+. \\\hline + \verb+\opinteger{n}{N}+ & + Copie la partie entière (nombre entier positif) de \verb+n+ + dans \verb+N+. \\\hline + \verb+\opintegerwidth{n}{N}+ & + Le nombre \verb+N+ reçoit la longueur de la partie entière du + nombre \verb+n+. \\\hline + \verb+\oplput(T1,T2){<objet>}+ & + Place \verb+<objet>+ à droite du point situé en + \verb+(T1,T2)+ par rapport au point de référence. \\\hline + \verb+\opmul[P]{n1}{n2}+ & + Affiche le résultat de l'opération \verb+n1*n2+. \\\hline + \verb+\opmul*{n1}{n2}{N}+ & + Calcule \verb+n1*n2+ et place le résultat dans + \verb+N+. \\\hline + \verb+\opneg{n}{N}+ & + Le nombre \verb+N+ reçoit l'opposé de \verb+n+. \\\hline + \verb+\oppower{n}{T}{N}+ & + Calcule \verb+n+ à la puissance \verb+T+ et place le + résultat dans \verb+N+. \\\hline + \verb+\opprint{n}+ & + Affiche le nombre \verb+n+ de façon directe. \\\hline + \verb+\opround{n}{T}{N}+ & + Place dans \verb+N+ la valeur arrondie de \verb+n+ au rang + \verb+T+. \\\hline + \verb+\oprput(T1,T2){<objet>}+ & + Place \verb+<objet>+ à gauche du point situé en + \verb+(T1,T2)+ par rapport au point de référence. \\\hline + \verb+\opset{L}+ & + Effectue une affectation globale des paramètres de \package{xlop} + désignés dans la liste \verb+L+. \\\hline + \verb+\opsetdecimaldigit{n}{T}{N}+ & + Modifie le \verb+T+ième chiffre de la partie décimale de + \verb+N+ pour qu'il soit égal à \verb+n+. \\\hline + \verb+\opsetdigit{n}{T}{N}+ & + Modifie le \verb+T+ième chiffre de \verb+N+ pour qu'il + soit égal à \verb+n+. \\\hline + \verb+\opsetintegerdigit{n}{T}{N}+ & + Modifie le \verb+T+ième chiffre de la partie entière de + \verb+N+ pour qu'il soit égal à \verb+n+. \\\hline + \verb+\opsub[P]{n1}{n2}+ & + Affiche le résultat de l'opération n1-n2. \\\hline + \verb+\opsub*{n1}{n2}{N}+ & + Calcule n1-n2 et place le résultat dans N. \\\hline + \verb+\opunzero{N}+ & + Supprime les zéros non significatifs du nombre \verb+N+. \\\hline + \verb+\opvline(T1,T2){T3}+ & + Trace un trait vertical de longueur \verb+T3+, d'épaisseur + \verb+hrulewidth+ et débutant en \verb+(T1,T2)+ par + rapport au point de référence. \\\hline + \verb+\opwidth{n}{N}+ & + Le nombre \verb+N+ reçoit le nombre de chiffres du nombre + \verb+n+. \\\hline +\end{longtable}\index{macros!table des|)} + +Dans ce tableau, les paramètres : +\begin{itemize} +\item \texttt{n} et \texttt{ni} (où \texttt{i} représente un indice) + indiquent que le paramètre doit être un nombre donné sous forme + décimale ou sous forme d'un nom de variable ; +\item \texttt{N} et \texttt{Ni} (où \texttt{i} représente un indice) + indiquent que le paramètre doit être un nombre donné sous forme d'un + nom de variable ; +\item \texttt{[P]} indique que la macro accepte un paramètre optionnel + permettant de modifier les paramètres de \package{xlop} ; +\item \texttt{T} et \texttt{Ti} (où \texttt{i} représente un indice) + indiquent que le paramètre doit être un nombre donné sous forme + décimale ou sous forme d'un nom de variable mais ne devant pas + excéder la taille des nombres directement acceptables par \TeX{} (en + l'occurrence $-2147483648 \le \mathtt{T} \le 2147483647$). +\end{itemize} + +\section{Liste des paramètres} +\label{sec:Liste des parametres} +\index{parametres@paramètres!table des|(}% +\begingroup +\advance\hoffset by-1.75cm \advance\linewidth by1.75cm +\begin{longtable}{|l|l|p{7cm}|} + \hline + \multicolumn{1}{|c|}{\textbf{Paramètre}} & + \multicolumn{1}{c|}{\textbf{Défaut}} & + \multicolumn{1}{c|}{\textbf{Signification}} \\\hline\hline + \endfirsthead + \hline + \multicolumn{1}{|c|}{\textbf{Paramètre}} & + \multicolumn{1}{c|}{\textbf{Défaut}} & + \multicolumn{1}{c|}{\textbf{Signification}} \\\hline\hline + \endhead + \hline + \multicolumn{3}{|c|}{$\ldots$ à suivre $\ldots$}\\ + \hline + \endfoot + \hline + \endlastfoot + \verb+afterperiodsymbol+ & + \verb+$\ldots$+ & + Symbole utilisé à la suite de la période d'une division. \\\hline + \verb+approxsymbol+ & + \verb+$\approx$+ & + Symbole utilisé comme relation d'égalité approximative dans les + opérations en ligne. \\\hline + \verb+equalsymbol+ & + \verb+{$=$}+ & + Symbole utilisé comme relation d'égalité dans les opérations en + ligne. \\\hline + \verb+addsymbol+ & + \verb-$+$- & + Symbole utilisé comme opérateur d'addition. \\\hline + \verb+subsymbol+ & + \verb+$-$+ & + Symbole utilisé comme opérateur de soustraction. \\\hline + \verb+mulsymbol+ & + \verb+$\times$+ & + Symbole utilisé comme opérateur de multiplication. \\\hline + \verb+divsymbol+ & + \verb+$\div$+ & + Symbole utilisé comme opérateur de division pour les opérations en + ligne. \\\hline + \verb+decimalsepsymbol+ & + \verb+.+ & + Symbole utilisé comme séparateur décimal. \\\hline + \verb+strikedecimalsepsymbol+ & + & + Symbole utilisé pour un séparateur décimal déplacé au niveau du + dividende et du diviseur dans les divisions posées. \\\hline + \verb+shiftintermediarysymbol+ & + \verb+$\cdot$+ & + Symbole utilisé pour montrer les décalages des nombres + intermédiaires dans les multiplications posées. \\\hline + \verb+displayshiftintermediary+ & + \verb+shift+ & + Indique que le caractère de décalage dans les multiplications sera + affiché uniquement pour le décalage supplémentaire (valeur + \verb+shift+), pour tous les décalages (valeur \verb+all+) + ou jamais (valeur \verb+none+). \\\hline + \verb+voperation+ & + \verb+bottom+ & + Type d'alignement vertical d'une opération posée. La + valeur \verb+bottom+ indique que le bas de l'opération sera + au niveau de la ligne de base. La valeur \verb+top+ indique + que la première ligne de l'opération sera sur la ligne de base. La + valeur \verb+center+ indique que l'opération sera centrée + verticalement sur la ligne de base. \\\hline + \verb+voperator+ & + \verb+center+ & + Positionnement vertical de l'opérateur dans les + opérations posées. La valeur \verb+top+ place l'opérateur au + niveau de la première opérande. La valeur \verb+bottom+ place + l'opérateur au niveau de la seconde opérande. La valeur + \verb+center+ place l'opérateur entre les deux + opérandes. \\\hline + \verb+hfactor+ & + \verb+decimal+ & + Type d'alignement des opérandes dans les + multiplications posées. La valeur \verb+decimal+ indique un + alignement sur la virgule. La valeur \verb+right+ indique une + composition au fer à droite. \\\hline + \verb+vruleperiod+ & + \verb+-0.2+ & + Position verticale du trait indiquant la période du quotient + dans les divisions en ligne. \\\hline + \verb+dividendbridge+ & + \verb+false+ & + Indique si le \og pont \fg{} au-dessus du dividende est présent ou + non. \\\hline + \verb+shiftdecimalsep+ & + \verb+both+ & + Indique la façon dont se fait le décalage de virgule au niveau des + opérandes d'une division posée. La valeur \verb+both+ indique + que le décalage doit rendre le diviseur et le dividende + entiers. La valeur \verb+divisor+ indique que le décalage + doit rendre le diviseur entier. La valeur \verb+none+ indique + qu'il n'y aura aucun décalage. \\\hline + \verb+maxdivstep+ & + \verb+10+ & + Nombre d'étapes maximum d'une division. \\\hline + \verb+safedivstep+ & + \verb+50+ & + Nombre d'étapes maximum d'une division lors d'un arrêt sur + période. \\\hline + \verb+period+ & + \verb+false+ & + Indique si la division doit s'arrêter sur une détection de période + ou non. \\\hline + \verb+deletezero+ & + \verb+true+ & + Indique si on affiche (\verb+false+) ou on supprime + (\verb+true+) les zéros non significatifs. \\\hline + \verb+carryadd+ & + \verb+true+ & + Indique si les retenues doivent être affichées pour les additions + posées. \\\hline + \verb+carrysub+ & + \verb+false+ & + Indique si les retenues doivent être affichées pour les + soustractions posées. \\\hline + \verb+offsetcarry+ & + \verb+-0.35+ & + Décalage horizontal pour les retenues dans les + soustractions posées. \\\hline + \verb+style+ & + \verb+display+ & + Indique si l'opération doit être en ligne (\verb+text+) ou + posée (\verb+display+). \\\hline + \verb+displayintermediary+ & + \verb+nonzero+ & + Indique si les résultats intermédiaires doivent être affichés + (\verb+all+) ou seulement les non nuls (\verb+nonzero+) ou + aucun (valeur \verb+none+) dans les multiplications et les + divisions. \\\hline + \verb+lastcarry+ & + \verb+false+ & + Indique si la retenue au niveau d'une absence de chiffre devra + être affichée ou non. \\\hline + \verb+parenthesisnegative+ & + \verb+none+ & + Comportement à adopter pour l'affichage des nombres + négatifs dans les opérations en lignes. La valeur \verb+none+ + les affiche sans parenthèse, \verb+all+ les mettra + systématiquement les nombres négatifs entre parenthèses et + \verb+last+ les mettra entre parenthèses + sauf pour la première valeur d'une expression. \\\hline + \verb+columnwidth+ & + \verb+2ex+ & + Largeur des boîtes contenant un chiffre. \\\hline + \verb+lineheight+ & + \verb+\baselineskip+ & + Hauteur des boîtes contenant un chiffre. \\\hline + \verb+decimalsepwidth+ & + \verb+0pt+ & + Largeur de la boîte contenant le séparateur décimal. \\\hline + \verb+decimalsepoffset+ & + \verb+0pt+ & + Décalage horizontal du séparateur décimal. \\\hline + \verb+hrulewidth+ & + \verb+0.4pt+ & + \'Épaisseur des lignes horizontales. \\\hline + \verb+vrulewidth+ & + \verb+0.4pt+ & + \'Épaisseur des lignes verticales. \\\hline + \verb+behaviorsub+ & + \verb+silent+ & + Comportement de \package{xlop} face à une + soustraction \og impossible \fg{}, c'est-à-dire une soustraction + ayant ses deux opérandes positives avec une seconde opérande + strictement supérieure à la première. La valeur \verb+silent+ + effectuera l'opération en permutant les opérandes de façon + silencieuse. La valeur \verb+warning+ fera de même mais en + émettant un message d'avertissement. Enfin, la valeur + \verb+error+ affichera un message d'erreur et l'opération ne + sera pas effectuée. \\\hline + \verb+country+ & + \verb+french+ & + Indique le comportement des opérations posées en fonction du + pays. L'extension prévoit pour l'instant \verb+french+, + \verb+american+ et \verb+russian+ mais les différentes + façons de présenter les opérations ne sont pas implantées dans la + version 0.2. \\\hline + \verb+operandstyle+ & + & + Style utilisé pour les opérandes. \\\hline + \verb+resultstyle+ & + & + Style utilisé pour les résultats. \\\hline + \verb+remainderstyle+ & + & + Style utilisé pour les restes. \\\hline + \verb+intermediarystyle+ & + & + Style utilisé pour les résultats intermédiaires (nombres + intermédiaires dans une multiplication et nombres à soustraire + dans une division où apparaissent les soustractions + successives). \\\hline + \verb+carrystyle+ & + \verb+\scriptsize+ & + Style utilisé pour les retenues. La valeur par défaut lorsqu'on ne + compile pas sous \LaTeX{} est \verb+\sevenrm+. \\\hline +\end{longtable}\index{parametres@paramètres!table des|)} +\newpage\endgroup + +\chapter{Trucs et astuces} +\label{chap:Trucs et astuces} +\section{Comparaison avec \package{calc} et \package{fp}} +On pourrait croire que \package{xlop} puisse remplacer avantageusement +des extensions telles que +\package{calc}\index{extension!calc}\index{calc} et +\package{fp}\index{extension!fp}\index{fp}. En réalité, c'est un peu +plus compliqué que cela. Bien sûr, \package{xlop} permet des calculs +complexes et sur des nombres comportant un nombre arbitraire de +chiffres mais, contrairement à \package{calc}, il ne permet pas de +gérer directement les unités. La comparaison avec \package{fp} est un +peu plus réaliste mais il ne faut pas perdre de vue que \package{xlop} +peut devenir gourmand en mémoire et en temps de calcul. + +Si vous voulez vraiment réaliser des calculs sur des +longueurs\index{longueur}, vous pouvez toujours utiliser le fait +qu'une affectation d'un registre de longueur à un compteur donnera un +nombre correspondant à cette longueur avec l'unité \texttt{sp}. +\begin{CenterExample}[xrightmargin=0pt] + \newcommand\getsize[2]{% + \dimen0=#1\relax + \count255=\dimen0 + \opcopy{\the\count255}{#2}} + \getsize{1pt}{r}$1\,\mathrm{pt} = \opprint{r}\,\mathrm{sp}$\quad + \getsize{1pc}{r}$1\,\mathrm{pc} = \opprint{r}\,\mathrm{sp}$\quad + \getsize{1in}{r}$1\,\mathrm{in} = \opprint{r}\,\mathrm{sp}$\quad + \getsize{1bp}{r}$1\,\mathrm{bp} = \opprint{r}\,\mathrm{sp}$\quad + \getsize{1cm}{r}$1\,\mathrm{cm} = \opprint{r}\,\mathrm{sp}$\quad + \getsize{1mm}{r}$1\,\mathrm{mm} = \opprint{r}\,\mathrm{sp}$\quad + \getsize{1dd}{r}$1\,\mathrm{dd} = \opprint{r}\,\mathrm{sp}$\quad + \getsize{1cc}{r}$1\,\mathrm{cc} = \opprint{r}\,\mathrm{sp}$\quad + \getsize{1sp}{r}$1\,\mathrm{sp} = \opprint{r}\,\mathrm{sp}$\quad +\end{CenterExample} +N'oubliez cependant pas que le but principal de \package{xlop} est +d'\emph{afficher} automatiquement les opérations. + +Muni de la macro \macro{getsize}, il est possible de réaliser des +calculs sur des longueurs. +\newcommand\getsize[2]{% + \dimen0=#1\relax + \count255=\dimen0 + \opcopy{\the\count255}{#2} +}\par\vspace{-\baselineskip}\noindent +\vbox to0cm{\parindent=0pt\vbox to2.5cm{\vss + \getsize{1cm}{u}% + \getsize{\textwidth}{w}% + \getsize{\textheight}{h}% + \opexpr{w*h/u^2}{S}% + \opround{S}{2}{S}% + \begin{minipage}{4.3cm} + La surface d'empagement est de + \opprint{S}\,$\mathrm{cm}^2$ + \end{minipage}}} +\begin{Verbatim}[xleftmargin=5cm,xrightmargin=0pt] + \getsize{1cm}{u}% + \getsize{\textwidth}{w}% + \getsize{\textheight}{h}% + \opexpr{w*h/u^2}{S}% + \opround{S}{2}{S}% + La surface d'empagement est de + \opprint{S}\,$\mathrm{cm}^2$ +\end{Verbatim} + +\section{Création d'opérations complexes} +\label{sec:Creation d'operations complexes} +L'utilisation des macros de \package{xlop} associées au mécanisme de +boucle de \TeX{} permet de créer des opérations à volonté. Nous ne +donnerons que deux exemples. Le premier est la décomposition d'un +nombre en facteurs premiers, le second est un calcul général de +fraction continue.\index{nombre!premier}% +\index{decomposition@décomposition en nombres premiers} +\begin{Verbatim}[xrightmargin=0pt] + \newcount\primeindex + \newcount\tryindex + \newif\ifprime + \newif\ifagain + \newcommand\getprime[1]{% + \opcopy{2}{P0}% + \opcopy{3}{P1}% + \opcopy{5}{try} + \primeindex=2 + \loop + \ifnum\primeindex<#1\relax + \testprimality + \ifprime + \opcopy{try}{P\the\primeindex}% + \advance\primeindex by1 + \fi + \opadd*{try}{2}{try}% + \ifnum\primeindex<#1\relax + \testprimality + \ifprime + \opcopy{try}{P\the\primeindex}% + \advance\primeindex by1 + \fi + \opadd*{try}{4}{try}% + \fi + \repeat + } + \newcommand\testprimality{% + \begingroup + \againtrue + \global\primetrue + \tryindex=0 + \loop + \opidiv*{try}{P\the\tryindex}{q}{r}% + \opcmp{r}{0}% + \ifopeq \global\primefalse \againfalse \fi + \opcmp{q}{P\the\tryindex}% + \ifoplt \againfalse \fi + \advance\tryindex by1 + \ifagain + \repeat + \endgroup + } +\end{Verbatim} +\newcount\primeindex +\newcount\tryindex +\newif\ifprime +\newif\ifagain +\newcommand\getprime[1]{% + \opcopy{2}{P0}% + \opcopy{3}{P1}% + \opcopy{5}{try} + \primeindex=2 + \loop + \ifnum\primeindex<#1\relax + \testprimality + \ifprime + \opcopy{try}{P\the\primeindex}% + \advance\primeindex by1 + \fi + \opadd*{try}{2}{try}% + \ifnum\primeindex<#1\relax + \testprimality + \ifprime + \opcopy{try}{P\the\primeindex}% + \advance\primeindex by1 + \fi + \opadd*{try}{4}{try}% + \fi + \repeat +} +\newcommand\testprimality{% + \begingroup + \againtrue + \global\primetrue + \tryindex=0 + \loop + \opidiv*{try}{P\the\tryindex}{q}{r}% + \opcmp{r}{0}% + \ifopeq \global\primefalse \againfalse \fi + \opcmp{q}{P\the\tryindex}% + \ifoplt \againfalse \fi + \advance\tryindex by1 + \ifagain + \repeat + \endgroup +} + +Avec ce code, on dispose d'un moyen de créer une liste de nombres +premiers (en l'occurrence les 20~premiers). +\begin{SideBySideExample} + \getprime{20}% + \opprint{P0}, \opprint{P1}, \ldots, + \opprint{P9}, \ldots \opprint{P19}. +\end{SideBySideExample} + +On notera toutefois que ce code est très mauvais, il est excessivement +lent et n'apporte rien par rapport à une approche directe avec des +nombres manipulés par les opérations natives de \TeX{}. Ce n'est +qu'un exemple pédagogique. On notera également l'astuce permettant +d'emboîter deux boucles avec la macro \verb+\testprimality+ +entièrement mise dans un groupe : s'il est nécessaire de rendre les +affectations \verb+\primetrue+ et \verb+\primefalse+ globales, les +opérations de \package{xlop} rendent leurs résultats globaux +directement.\index{affectation globale}% + +Une fois que vous avez votre \og table \fg{} de nombres premiers, vous +pouvez vous en servir pour décomposer un nombre en facteurs +premiers. +\begin{CenterExample}[xrightmargin=0pt] + \newcommand\primedecomp[2][nil]{% + \begingroup + \opset{#1}% + \opcopy{#2}{NbtoDecompose}% + \opabs{NbtoDecompose}{NbtoDecompose}% + \opinteger{NbtoDecompose}{NbtoDecompose}% + \opcmp{NbtoDecompose}{0}% + \ifopeq + Je refuse de d\'ecomposer z\'ero. + \else + \setbox1=\hbox{\opdisplay{operandstyle.1}% + {NbtoDecompose}}% + {\setbox2=\box2{}}% + \count255=1 + \primeindex=0 + \loop + \opcmp{NbtoDecompose}{1}\ifopneq + \opidiv*{NbtoDecompose}{P\the\primeindex}{q}{r}% + \opcmp{0}{r}\ifopeq + \ifvoid2 + \setbox2=\hbox{% + \opdisplay{intermediarystyle.\the\count255}% + {P\the\primeindex}}% + \else + \setbox2=\vtop{% + \hbox{\box2} + \hbox{% + \opdisplay{intermediarystyle.\the\count255}% + {P\the\primeindex}}} + \fi + \opcopy{q}{NbtoDecompose}% + \advance\count255 by1 + \setbox1=\vtop{% + \hbox{\box1} + \hbox{% + \opdisplay{operandstyle.\the\count255}% + {NbtoDecompose}} + }% + \else + \advance\primeindex by1 + \fi + \repeat + \hbox{\box1 + \kern0.5\opcolumnwidth + \opvline(0,0.75){\the\count255.25} + \kern0.5\opcolumnwidth + \box2}% + \fi + \endgroup + } + + \getprime{20}% + \primedecomp[operandstyle.2=\red, + intermediarystyle.2=\red]{252} +\end{CenterExample} +Dans ce code, on notera l'emploi d'un groupe entourant l'ensemble de +la macro pour protéger les modifications de paramètres de +\package{xlop}.\index{parametre@paramètre!modifications locales} +\`A ce propos, on notera également qu'un paramètre vide n'est pas +accepté. C'est tout à fait volontaire, l'auteur de l'extension pensant +qu'un utilisateur tapant des crochets sans rien mettre à l'intérieur +est sans doute en train de commettre une erreur. Pour palier à cette +impossibilité de transmettre un paramètre vide +\index{parametre@paramètre!vide}% +il existe le paramètre particulier \parameter{nil} qui a exactement ce +rôle. + +On notera enfin l'astuce \verb+{\setbox2=\box2}+ qui permet +d'obtenir un registre de boîte vide et les manipulations finales +permettant de représenter la barre verticale de façon lisible. + +Le second exemple permet de calculer une fraction continue du type : +\def\dfrac#1#2{\frac{\displaystyle #1}{\displaystyle #2}} +\[a_0+\dfrac{1}{a_1+\dfrac{1}{a_2+\dfrac{1}{a_3+\cdots}}}\] +en donnant la suite $a_0,a_1,a_2,a_3,\ldots$ à la macro. L'exemple +donne les fractions correspondant au nombre d'or et aux racines +carrées de~2 et~3. +\makeatletter +\begin{CenterExample}[xrightmargin=0pt] + \begingroup + \catcode`\:=12 + \long\gdef\continuedfraction#1#2{% + \let\@mirror\relax + \@for\op@Nb:=#1\do + {% + \ifx\@mirror\relax + \edef\@mirror{\op@Nb}% + \else + \edef\@mirror{\op@Nb,\@mirror}% + \fi + }% + \let\Op@result\relax + \@for\op@Nb:=\@mirror\do + {% + \ifx\Op@result\relax + \opcopy{\op@Nb}{result}% + \else + \opexpr{\op@Nb+1/result}{result}% + \fi + }% + \opcopy{result}{#2}% + } + \endgroup + \continuedfraction{1,1,1,1,1,1,1,1,1,1}{r}\opprint{r}\quad + \continuedfraction{1,2,2,2,2,2,2,2,2,2}{r}\opprint{r}\quad + \continuedfraction{1,1,2,1,2,1,2,1,2,1}{r}\opprint{r} +\end{CenterExample} +\makeatother +Une fois n'est pas coutume, nous avons fait appel à des commandes +\LaTeX{} pour effectuer une boucle. Ce manuel étant composé en +français, le caractère \og \texttt{\string:} \fg{} est actif ce qui +empêche la macro \verb+\@for+ de fonctionner correctement d'où le +groupe où ce caractère reçoit un code de catégorie adéquat. + +\section{Accès direct aux nombres} +\label{sec:Acces direct aux nombres} +Lorsqu'on récupère un nombre dans une variable, on peut le traiter de +multiples façons à l'aide des macros de \package{xlop}. Toutefois, +dans certaines situations, on peut souhaiter construire ses propres +macros ou utiliser des macros externes en passant un tel nombre en +paramètre. + +Passer directement \verb+\opprint{var}+ est inopérant car cette macro +est suffisamment complexe pour induire des effets de bord dans ce +genre de situations. Il devient alors nécessaire d'accéder directement +à ce nombre. Lorsqu'un nombre est mémorisé dans une variable +\verb+var+, \package{xlop} crée une macro +\texttt{$\backslash$Op@var}\index{Opvar@\texttt{\boi {Op\at var}}} +qui contient +ce nombre. On notera le \og O \fg{} majuscule et le \og p \fg{} +minuscule. L'arrobas est là pour rendre cette définition privée +c'est-à-dire qu'il faut faire un effort pour y accéder avec +l'utilisation des macros \macro{makeatletter} et \macro{makeatother} +de \LaTeX{} ou bien en indiquant un code de catégorie égal à~11 +(lettre) pour ce caractère lorsqu'on travaille sous \TeX{}. +\begin{SideBySideExample} + \opcopy{1234}{a}\opcopy{56}{b}% + \opmul*{a}{b}{r}% + \makeatletter + $\nombre{\Op@a} \times + \nombre{\Op@b} = \nombre{\Op@r}$ + \makeatother +\end{SideBySideExample} + +\chapter{Versions futures} +\label{chap:Versions futures} +L'extension \package{xlop} en est à sa version~0.2 qui est +essentiellement une version corrigée de la version~0.1 (première +version publique). La prochaine version sera la~0.3 dont la version +\og stable \fg{} sera alors la version~0.4. + +L'ensemble des spécificités de la version 0.3 n'est pas totalement +arrêté mais il y a déjà plusieurs points prévus : +\begin{itemize} +\item gestion internationale des opérations posées ; +\item opérations en base 2 à 36 ; +\item ajout de fonctions de haut niveau avec les racines + (\macro{oproot} pour les racines quelconques et \macro{opsqrt} pour + la racine carrée), exponentielle, logarithme, fonctions + trigonométriques (directes, inverses, hyperboliques) ; +\item ajout d'une macro permettant de réaliser une écriture formatée, + c'est-à-dire une écriture d'un nombre où les longueurs des parties + entière et décimale seront indiquées (si ces longueurs ne sont pas + celles du nombre, il y aura un débordement ou un remplissage) ; + cette macro existait dans la version~0.1 et permettait + essentiellement d'afficher des nombres avec un alignement sur la + virgule, au fer à droite ou au fer à gauche ; +\item ajout d'une macro permettant les additions à plus de deux + opérandes ; +\item ajout d'un paramètre permettant l'écriture scientifique ou + ingénieur ; +\item possibilité d'écrire un nombre sur plusieurs lignes et/ou en + utilisant un séparateur des milliers ; +\item retenues dans les multiplications ; +\item rendre publics les restes successives d'une division ; +\item les valeurs négatives de \parameter{maxdivstep} et + \parameter{safedivstep} réaliseront un comptage sur les chiffres + décimaux du quotient ; +\item manuel en anglais. +\end{itemize} + +Pour le premier point, seules la division anglo-saxonne, la +multiplication dite russe et la multiplication dite babylonienne sont +en cours d'étude, l'auteur ne connaissant pas les habitudes des autres +pays en la matière. Si vous connaissez d'autres façons de poser les +opérations à part celles présentées dans ce manuel, la division +anglo-saxonne, la multiplication russe (double colonne avec des +divisions par deux sur une colonne et des multiplications par deux sur +l'autre) et la multiplication babylonienne (ou vénitienne qui consiste +à faire une grande grille de multiplication à un chiffre et à effectuer +les sommes finales en diagonale), l'auteur vous sera éternellement +reconnaissant de le contacter à l'adresse : +\begin{verbatim} + Jean-Come.Charpentier@wanadoo.fr +\end{verbatim} +en plaçant le mot \og \texttt{xlop} \fg{} dans le sujet du message. + +Il serait souhaitable d'avoir un manuel du hacker qui expliquerait en +détail le code source. Cet outil pourrait être tout à fait bénéfique +pour que chacun puisse apporter plus facilement des améliorations au +code. Malheureusement, le code actuel fait plus de~\nombre{3900} +lignes et le travail nécessaire risque d'être trop important. +Éventuellement, il pourra y avoir un manuel du hacker expliquant les +spécifications générales du code sans entrer dans trop de détails +techniques. + +%\printindex +\chapter{Index} +\label{chap:index} +\begin{multicols}{2} +\makeatletter +\parindent \z@\relax +\parskip \z@ \@plus.3\p@\relax +\let\item\@idxitem +\makeatother +\renewenvironment{theindex}{}{}% +\input\jobname.ind +\end{multicols} +\end{document} diff --git a/Master/texmf-dist/doc/generic/xlop/history.txt b/Master/texmf-dist/doc/generic/xlop/history.txt new file mode 100644 index 00000000000..97ef8d73097 --- /dev/null +++ b/Master/texmf-dist/doc/generic/xlop/history.txt @@ -0,0 +1,55 @@ +10 janvier 2004 version 0.01-beta01 +--------------- + Division posée. + +28 janvier 2004 version 0.01-beta02 +--------------- + Quatre opérations posées et en ligne. + +5 février 2004 version 0.01-beta03 +-------------- + Ajout de la division euclidienne. + +3 mars 2004 version 0.01-beta04 +----------- + Ajout de plein de détails de présentations. + Changement complet de certains algorithmes et du codage interne des + nombres développés. + Manuel de l'utilisateur. + Première version envoyée aux beta-testeurs. Un grand merci à : + Pascal Chantriaux + Marc Chaudemanche + Olivier Deutsch + Paul Gaborit + Martine Gautier + Yvon Henel + Christophe Jorssen + Ahmed Kadi + Josselin Noirel + Olivier Viennet + Damien Wyard + +26 mai 2004 version 0.1 +----------- + Refonte complète du code + Ajout de certains détails de présentation. + syntaxe "à la keyval" des paramètres ; + correction de bogues de la version 0.01-beta04 ; + manipulations de chiffres ; + \opexpr ; + changement de codage des noms de nombre. + Première version publique. + +25 juin 2004 version 0.2 +------------ + Correction de bogues + Style pour le séparateur décimal + +6 avril 2005 version 0.21 +------------ + Correction d'un bogue sur la division + +4 janvier 2006 version 0.22 +------------ + Correction d'un bogue sur l'affichage de la multiplication posée + diff --git a/Master/texmf-dist/doc/generic/xlop/xlop.tex b/Master/texmf-dist/doc/generic/xlop/xlop.tex new file mode 100644 index 00000000000..dea98da45d0 --- /dev/null +++ b/Master/texmf-dist/doc/generic/xlop/xlop.tex @@ -0,0 +1,3948 @@ +\def\fileversion{0.22} +\def\filedate{2006/01/04} +%% +%% xlop.tex: +%% eXtra Large OPeration macros for Generic TeX. +%% See `user.pdf' for documentation; +%% `hacker.pdf' for explanation. +%% +%% Copyright 2005,2006, by Jean-C\^ome Charpentier +%% Jean-Come.Charpentier@wanadoo.fr +%% +%% This program 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 2003/12/01 or later. + +\csname xlopLoaded\endcsname +\let\xlopLoaded\endinput +\edef\opAtCode{\the\catcode`\@} +\catcode`\@=11\relax +\newcount\count@z +\newcount\count@i +\newcount\count@ii +\newcount\count@iii +\newcount\count@iv +\newcount\count@v +\newtoks\op@currentstyle +\expandafter\ifx\csname @latexerr\endcsname\relax +\long\def\@ifundefined#1#2#3{% + \expandafter\ifx\csname #1\endcsname\relax + #2% + \else + #3% + \fi} +\def\@gobble#1{} +\def\@namedef#1{\expandafter\def\csname #1\endcsname} +\def\@nameuse#1{\csname #1\endcsname} +\def\typeout#1{\immediate\write\@unused{#1}} +\alloc@7\write\chardef\sixt@@n\@unused +\def\@spaces{\space\space\space\space} +\def\@ifnextchar#1#2#3{% + \let\@tempe#1\def\@tempa{#2}\def\@tempb{#3}\futurelet\@tempc\@ifnch} +\def\@ifnch{% + \ifx\@tempc\@sptoken + \let\@tempd\@xifnch + \else + \ifx\@tempc\@tempe + \let\@tempd\@tempa + \else + \let\@tempd\@tempb + \fi + \fi + \@tempd +} +\begingroup +\def\:{\global\let\@sptoken= } \: +\def\:{\@xifnch} \expandafter\gdef\: {\futurelet\@tempc\@ifnch} +\endgroup +\fi %LaTeX-like +\def\@nameedef#1{\expandafter\edef\csname #1\endcsname} +\def\@namexdef#1{\expandafter\xdef\csname #1\endcsname} +\typeout{`xlop' v\fileversion\space\space <\filedate> (jcc)} +\newif\ifop@error +\def\op@error{% + \begingroup + \global\op@errortrue + \newlinechar`\^^J + \op@@error +} +\def\op@@error#1#2{% + \xdef\op@errortext{#1}% + \xdef\op@errorhelp{#2}% + \endgroup +} +\def\op@errorwrite{% + \global\op@errorfalse + \begingroup + \newlinechar`\^^J + \expandafter\errhelp\expandafter{\op@errorhelp}% + \typeout{% + xlop error. \space See documentation for further information.^^J + \@spaces\@spaces\@spaces\@spaces + Type \space H <return> \space for immediate help.}% + \errmessage{\op@errortext}% + \endgroup +} +\def\op@warning{% + \begingroup + \newlinechar`\^^J + \op@@warning +} +\def\op@@warning#1{% + \typeout{xlop warning. + #1^^J\@spaces See documentation for further information.^^J}% + \endgroup +} +\let\@nil\relax +\def\opset#1{% + \Pop@set#1,\@nil + \ifop@error\op@errorwrite\fi + \ignorespaces +} +\def\Pop@set#1,{% + \Pop@@set#1==\@nil + \@ifnextchar\@nil{\@gobble}{\Pop@set}% +} +\def\Pop@@set#1=#2=#3\@nil{% + \@ifundefined{pOP@#1}% + {\Pop@@@set#1.={#2}} + {\@nameuse{pOP@#1}{#2}}% +} +\def\Pop@@@set#1.#2=#3{% + \@ifundefined{pOP@#1}% + {\op@error{Parameter `#1' not defined.}% + {\space\space Perhaps you have mispelling parameter!^^J + \space Are you sure about `#1'?^^J}}% + {\@nameuse{pOP@#1}[#2]{#3}}% +} +\def\op@string@lpar{(} +\def\op@string@rpar{)} +\def\op@string@comma{,} +\def\op@string@abs{abs} +\def\op@string@add{add} +\def\op@string@ceil{ceil} +\def\op@string@div{div} +\def\op@string@floor{floor} +\def\op@string@gcd{gcd} +\def\op@string@idiv{idiv} +\def\op@string@integer{integer} +\def\op@string@mod{mod} +\def\op@string@mul{mul} +\def\op@string@neg{neg} +\def\op@string@power{power} +\def\op@string@rest{rest} +\def\op@string@round{round} +\def\op@string@sub{sub} + +\def\op@string@all{all} +\def\op@string@american{american} +\def\op@string@both{both} +\def\op@string@bottom{bottom} +\def\op@string@center{center} +\def\op@string@decimal{decimal} +\def\op@string@delete{delete} +\def\op@string@display{display} +\def\op@string@divisor{divisor} +\def\op@string@error{error} +\def\op@string@false{false} +\def\op@string@french{french} +\def\op@string@last{last} +\def\op@string@left{left} +\def\op@string@none{none} +\def\op@string@nonzero{nonzero} +\def\op@string@right{right} +\def\op@string@russian{russian} +\def\op@string@shift{shift} +\def\op@string@silent{silent} +\def\op@string@strike{strike} +\def\op@string@text{text} +\def\op@string@top{top} +\def\op@string@true{true} +\def\op@string@warning{warning} + +\def\pOP@afterperiodsymbol#1{\def\op@afterperiodsymbol{#1}} +\def\pOP@approxsymbol#1{\def\op@approxsymbol{#1}} +\def\pOP@equalsymbol#1{\def\op@equalsymbol{#1}} +\def\pOP@addsymbol#1{\def\op@addsymbol{#1}} +\def\pOP@subsymbol#1{\def\op@subsymbol{#1}} +\def\pOP@mulsymbol#1{\def\op@mulsymbol{#1}} +\def\pOP@divsymbol#1{\def\op@divsymbol{#1}} +\def\pOP@decimalsepsymbol#1{\def\op@decimalsepsymbol{{#1}}} +\def\pOP@strikedecimalsepsymbol#1{\def\op@strikedecimalsepsymbol{#1}} +\def\pOP@shiftintermediarysymbol#1{\def\op@shiftintermediarysymbol{#1}} +\def\pOP@displayshiftintermediary#1{\edef\@tempa{#1}% + \ifx\@tempa\op@string@shift + \let\op@displayshiftintermediary\op@string@shift + \else\ifx\@tempa\op@string@all + \let\op@displayshiftintermediary\op@string@all + \else\ifx\@tempa\op@string@none + \let\op@displayshiftintermediary\op@string@none + \else + \op@error{Parameter displayshiftintermediary accept only `shift', + `all', and `none'.^^J \space Here, the value is `#1'}% + {Value must be `shift', `all', or `none'}% + \fi\fi\fi +} +\def\pOP@voperation#1{\edef\@tempa{#1}% + \ifx\@tempa\op@string@bottom + \let\op@voperation\op@string@bottom + \else\ifx\@tempa\op@string@center + \let\op@voperation\op@string@center + \else\ifx\@tempa\op@string@top + \let\op@voperation\op@string@top + \else + \op@error{Parameter voperation accept only `top', `center', + and `bottom'.^^J \space Here, the value is `#1'}% + {Value must be `top', `center', or `bottom'}% + \fi\fi\fi +} +\def\pOP@voperator#1{\edef\@tempa{#1}% + \ifx\@tempa\op@string@top + \let\op@voperator\op@string@top + \else\ifx\@tempa\op@string@bottom + \let\op@voperator\op@string@bottom + \else\ifx\@tempa\op@string@center + \let\op@voperator\op@string@center + \else + \op@error{Parameter voperator accept only `top', `center', + and `bottom'.^^J \space Here, the value is `#1'}% + {Value must be `top', `center', or `bottom'}% + \fi\fi\fi +} +\def\pOP@hfactor#1{\edef\@tempa{#1}% + \ifx\@tempa\op@string@right + \let\op@hfactor\op@string@right + \else\ifx\@tempa\op@string@decimal + \let\op@hfactor\op@string@decimal + \else + \op@error{Parameter hfactor accept only `right' + and `decimal'.^^J \space Here, the value is `#1'}% + {Value must be `right' or `decimal'}% + \fi\fi +} +\def\pOP@vruleperiod#1{\def\op@vruleperiod{#1}} +\newif\ifop@dividendbridge +\def\pOP@dividendbridge#1{\edef\@tempa{#1}% + \edef\@tempa{#1}% + \ifx\@tempa\op@string@false + \op@dividendbridgefalse + \else\ifx\@tempa\op@string@true + \op@dividendbridgetrue + \else\ifx\@tempa\empty + \op@dividendbridgetrue + \else + \op@error{Parameter dividendbridge accept only `true' and `false'.^^J + \space Here, the value is `#1'}% + {Value must be `true', or `false', or an empty value}% + \fi\fi\fi +} +\def\pOP@shiftdecimalsep#1{\edef\@tempa{#1}% + \ifx\@tempa\op@string@none + \let\op@shiftdecimalsep\op@string@none + \else\ifx\@tempa\op@string@divisor + \let\op@shiftdecimalsep\op@string@divisor + \else\ifx\@tempa\op@string@both + \let\op@shiftdecimalsep\op@string@both + \else + \op@error{Parameter shiftdecimalsep accept only `none', `divisor', + and `both'.^^J \space Here, the value is `#1'}% + {Value must be `none', `divisor', or `both'}% + \fi\fi\fi +} +\def\pOP@maxdivstep#1{\edef\op@maxdivstep{#1}} +\def\pOP@safedivstep#1{\edef\op@safedivstep{#1}} +\newif\ifop@period +\def\pOP@period#1{\edef\@tempa{#1}% + \ifx\@tempa\op@string@false + \op@periodfalse + \else\ifx\@tempa\op@string@true + \op@periodtrue + \else\ifx\@tempa\empty + \op@periodtrue + \else + \op@error{Parameter period accept only `true' and `false'.^^J + \space Here, the value is `#1'}% + {Value must be `true', or `false', or an empty value}% + \fi\fi\fi +} +\newif\ifop@deletezero +\def\pOP@deletezero#1{\edef\@tempa{#1}% + \ifx\@tempa\op@string@false + \op@deletezerofalse + \else\ifx\@tempa\op@string@true + \op@deletezerotrue + \else\ifx\@tempa\empty + \op@deletezerotrue + \else + \op@error{Parameter deletezero accept only `true' and `false'.^^J + \space Here, the value is `#1'}% + {Value must be `true', or `false', or an empty value}% + \fi\fi\fi +} +\newif\ifop@carryadd +\def\pOP@carryadd#1{\edef\@tempa{#1}% + \ifx\@tempa\op@string@false + \op@carryaddfalse + \else\ifx\@tempa\op@string@true + \op@carryaddtrue + \else\ifx\@tempa\empty + \op@carryaddtrue + \else + \op@error{Parameter carryadd accept only `true' and `false'.^^J + \space Here, the value is `#1'}% + {Value must be `true', or `false', or an empty value}% + \fi\fi\fi +} +\newif\ifop@carrysub +\def\pOP@carrysub#1{\edef\@tempa{#1}% + \ifx\@tempa\op@string@false + \op@carrysubfalse + \else\ifx\@tempa\op@string@true + \op@carrysubtrue + \else\ifx\@tempa\empty + \op@carrysubtrue + \else + \op@error{Parameter carrysub accept only `true' and `false'.^^J + \space Here, the value is `#1'}% + {Value must be `true', or `false', or an empty value}% + \fi\fi\fi +} +\def\pOP@offsetcarry#1{\edef\op@offsetcarry{#1}} +\def\pOP@style#1{\edef\@tempa{#1}% + \ifx\@tempa\op@string@display + \let\op@style\op@string@display + \else\ifx\@tempa\op@string@text + \let\op@style\op@string@text + \else + \op@error{Parameter style accept only `display' and `text'.^^J + \space Here, the value is `#1'}% + {Value must be `display' or `text'}% + \fi\fi +} +\def\pOP@displayintermediary#1{\edef\@tempa{#1}% + \ifx\@tempa\op@string@all + \let\op@displayintermediary\op@string@all + \else\ifx\@tempa\op@string@nonzero + \let\op@displayintermediary\op@string@nonzero + \else\ifx\@tempa\op@string@none + \let\op@displayintermediary\op@string@none + \else + \op@error{Parameter style accept only `all', `none', and `nonzero'.^^J + \space Here, the value is `#1'}% + {Value must be `all', `none', or `nonzero'}% + \fi\fi\fi +} +\newif\ifop@lastcarry +\def\pOP@lastcarry#1{\edef\@tempa{#1}% + \ifx\@tempa\op@string@false + \op@lastcarryfalse + \else\ifx\@tempa\op@string@true + \op@lastcarrytrue + \else\ifx\@tempa\empty + \op@lastcarrytrue + \else + \op@error{Parameter lastcarry accept only `true' and `false'.^^J + \space Here, the value is `#1'}% + {Value must be `true', or `false', or an empty value}% + \fi\fi\fi +} +\def\pOP@parenthesisnegative#1{\edef\@tempa{#1}% + \ifx\@tempa\op@string@all + \let\op@parenthesisnegative\op@string@all + \else\ifx\@tempa\op@string@last + \let\op@parenthesisnegative\op@string@last + \else\ifx\@tempa\op@string@none + \let\op@parenthesisnegative\op@string@none + \else + \op@error{Parameter parenthesisnegative accept only `all', `last' + and `none'.^^J + \space Here, the value is `#1'}% + {Value must be `all', `last', or `none'}% + \fi\fi\fi +} +\newdimen\opcolumnwidth +\def\pOP@columnwidth#1{\opcolumnwidth=#1\relax} +\newdimen\oplineheight +\newbox\op@strutbox +\def\pOP@lineheight#1{\oplineheight=#1\relax + \setbox\op@strutbox=\hbox{% + \vrule height.708333\oplineheight + depth .291667\oplineheight + width\z@}% +} +\def\op@strut{\relax\ifmmode + \copy\op@strutbox + \else + \unhcopy\op@strutbox + \fi +} +\newdimen\op@decimalsepwidth +\def\pOP@decimalsepwidth#1{\op@decimalsepwidth=#1} +\newdimen\op@decimalsepoffset +\def\pOP@decimalsepoffset#1{\op@decimalsepoffset=#1} +\newdimen\op@hrulewidth +\def\pOP@hrulewidth#1{\op@hrulewidth=#1\relax} +\newdimen\op@vrulewidth +\def\pOP@vrulewidth#1{\op@vrulewidth=#1\relax} +\def\pOP@behaviorsub#1{\edef\@tempa{#1}% + \ifx\@tempa\op@string@warning + \let\op@behaviorsub\op@string@warning + \else\ifx\@tempa\op@string@error + \let\op@behaviorsub\op@string@error + \else\ifx\@tempa\op@string@silent + \let\op@behaviorsub\op@string@silent + \else + \op@error{Parameter behaviorsub accept only `warning', `error' + and `silent'.^^J + \space Here, the value is `#1'}% + {Value must be `warning', `error', or `silent'}% + \fi\fi\fi +} +\def\pOP@country#1{\edef\@tempa{#1}% + \ifx\@tempa\op@string@french + \let\op@country\op@string@french + \else\ifx\@tempa\op@string@american + \let\op@country\op@string@american + \else\ifx\@tempa\op@string@russian + \let\op@country\op@string@russian + \else + \op@error{Parameter contry accept only some values.^^J + \space Value `#1' isn't a valid country for xlop}% + {For now, value must be `french', `russian', or `american'}% + \fi\fi\fi +} +\def\pOP@operandstyle{% + \@ifnextchar[{\pOP@@operandstyle}{\pOP@@operandstyle[0.]}% +} +\def\pOP@@operandstyle[#1.]#2{% + \@namedef{op@operandstyle.#1}{#2}% +} +\def\pOP@carrystyle{% + \@ifnextchar[{\pOP@@carrystyle}{\pOP@@carrystyle[0.]}% +} +\def\pOP@@carrystyle[#1.]#2{% + \@namedef{op@carrystyle.#1}{#2}% +} +\def\pOP@resultstyle{% + \@ifnextchar[{\pOP@@resultstyle}{\pOP@@resultstyle[0.]}% +} +\def\pOP@@resultstyle[#1.]#2{% + \@namedef{op@resultstyle.#1}{#2}% +} +\def\pOP@intermediarystyle{% + \@ifnextchar[{\pOP@@intermediarystyle}{\pOP@@intermediarystyle[0.]}% +} +\def\pOP@@intermediarystyle[#1.]#2{% + \@namedef{op@intermediarystyle.#1}{#2}% +} +\def\pOP@remainderstyle{% + \@ifnextchar[{\pOP@@remainderstyle}{\pOP@@remainderstyle[0.]}% +} +\def\pOP@@remainderstyle[#1.]#2{% + \@namedef{op@remainderstyle.#1}{#2}% +} +\def\pOP@nil#1{} + +\opset{afterperiodsymbol=$\ldots$,approxsymbol=$\approx$, + equalsymbol={$=$},addsymbol=$+$,subsymbol=$-$, + mulsymbol=$\times$,divsymbol=$\div$, + decimalsepsymbol=.,strikedecimalsepsymbol=, + shiftintermediarysymbol=$\cdot$,displayshiftintermediary=shift, + voperation=bottom,voperator=center, + hfactor=right,vruleperiod=-0.2,dividendbridge=false, + shiftdecimalsep=both,maxdivstep=10,safedivstep=50,period=false, + deletezero=true,carryadd=true,carrysub=false,offsetcarry=-0.35, + style=display,displayintermediary=none,lastcarry=false, + parenthesisnegative=none,columnwidth=2ex,lineheight=\baselineskip, + decimalsepwidth=0pt,decimalsepoffset=0pt, + hrulewidth=0.4pt,vrulewidth=0.4pt, + behaviorsub=silent,country=french, + operandstyle=,resultstyle=,remainderstyle=, + intermediarystyle=} +\expandafter\ifx\csname @latexerr\endcsname\relax + \opset{carrystyle=\sevenrm} +\else + \opset{carrystyle=\scriptsize} +\fi + +\count@z=`\0 \edef\op@numbegin{\the\count@z} +\count@z=`\9 \edef\op@numend{\the\count@z} +\count@z=`\+ \edef\op@plus{\the\count@z} +\count@z=`\- \edef\op@minus{\the\count@z} +\count@z=`\* \edef\op@multiply{\the\count@z} +\count@z=`\/ \edef\op@divide{\the\count@z} +\count@z=`\: \edef\op@idivide{\the\count@z} +\count@z=`\^ \edef\op@pow{\the\count@z} +\count@z=`\. \edef\op@dot{\the\count@z} +\count@z=`\, \edef\op@comma{\the\count@z} +\count@z=`\( \edef\op@lparenthesis{\the\count@z} +\count@z=`\) \edef\op@rparenthesis{\the\count@z} +\count@z=`\ \edef\op@space{\the\count@z} +\newcount\op@parenthesis +\newcount\op@token +\newcount\op@stack +\newcount\op@stackb +\newif\ifop@in@number +\newif\ifop@in@decimal +\newif\ifop@in@name +\newif\ifop@in@sign +\newif\ifop@isdigit +\newif\ifop@isplus +\newif\ifop@isminus +\newif\ifop@isdot +\newif\ifop@iscomma +\newif\ifop@isdecimalsep +\newif\ifop@ismultiply +\newif\ifop@isdivide +\newif\ifop@isidivide +\newif\ifop@ispower +\newif\ifop@islparenthesis +\newif\ifop@isrparenthesis +\newif\ifop@isspace +\newif\ifop@isother + +\newif\ifopgt +\newif\ifopge +\newif\ifopeq +\newif\ifopneq +\newif\ifople +\newif\ifoplt +\newif\ifop@again +\newif\ifop@carry +\def\op@testchar#1{% + \op@isdigitfalse + \op@isplusfalse + \op@isminusfalse + \op@isdecimalsepfalse + \count@z=`#1\relax + \ifnum\count@z=\op@plus\relax + \op@isplustrue + \else\ifnum\count@z=\op@minus\relax + \op@isminustrue + \else\ifnum\count@z=\op@dot\relax + \op@isdecimalseptrue + \else\ifnum\count@z=\op@comma\relax + \op@isdecimalseptrue + \else\ifnum\count@z<\op@numbegin\relax + \else\ifnum\count@z>\op@numend\relax + \else + \op@isdigittrue + \fi\fi\fi\fi\fi\fi +} +\def\op@split#1#2{% + \begingroup + \edef\op@arg{#1}% + \expandafter\op@readnumber\op@arg\@nil + \ifop@error + \op@error{Number name `#1' is undefined}% + {See documentation about number name}% + \let\next\relax + \let\op@arg\relax + \else + \edef\op@name{#2}% + \op@length + \count@i=\@nameuse{OP@\op@name @w}\relax + \edef\op@arg{\op@arg.}% + \let\next\op@@split + \fi + \expandafter\next\op@arg\@nil + \endgroup +} +\def\op@@split#1#2\@nil{% + \ifnum\count@i>0 + \edef\op@argi{#1}% + \edef\op@argii{#2}% + \let\next\op@@split + \expandafter\op@testchar\op@argi + \ifop@isdigit + \@namexdef{OP@\op@name @\the\count@i}{\op@argi}% + \advance\count@i by -1 + \fi + \else + \let\next\relax + \let\op@argii\relax + \fi + \expandafter\next\op@argii\@nil +} +\def\op@readnumber#1#2\@nil{% + \op@testchar{#1}% + \ifop@isdigit \else + \ifop@isplus \else + \ifop@isminus \else + \ifop@isdecimalsep \else + \@ifundefined{Op@#1#2}% + {\global\op@errortrue}% + {\edef\op@arg{\@nameuse{Op@#1#2}}}% + \fi\fi\fi\fi +} +\def\op@length{% + \begingroup + \expandafter\op@@length\op@arg\@nil + \ifnum\count@i=0 + \count@i=1 + \xdef\op@arg{0\op@arg}% + \fi + \@namexdef{OP@\op@name @i}{\the\count@i}% + \@namexdef{OP@\op@name @d}{\the\count@ii}% + \advance\count@i by \count@ii + \@namexdef{OP@\op@name @w}{\the\count@i}% + \endgroup +} +\def\op@@length#1#2\@nil{% + \edef\op@argi{#1}% + \edef\op@argii{#2}% + \expandafter\op@testchar\op@argi + \ifop@isdigit + \@namexdef{OP@\op@name @s}{0}% + \count@i=1 + \count@ii=0 + \ifx\empty\op@argii + \let\next\relax + \let\op@argii\relax + \else + \let\next\op@length@after@digit + \fi + \else \ifop@isplus + \@namexdef{OP@\op@name @s}{0}% + \let\next\op@length@after@sign + \else \ifop@isminus + \@namexdef{OP@\op@name @s}{1}% + \let\next\op@length@after@sign + \else \ifop@isdecimalsep + \@namexdef{OP@\op@name @s}{0}% + \count@i=0 + \count@ii=0 + \let\next\op@length@after@decimalsep + \else + \op@error{\op@argi\op@argii\space isn't a valid number}% + {See documentation for syntax of valid number}% + \let\next\relax + \let\op@argii\relax + \fi\fi\fi\fi + \ifx\empty\op@argii + \op@error{\op@argi\space isn't a valid number}% + {See documentation for syntax of valid number}% + \let\next\relax + \let\op@argii\relax + \fi + \expandafter\next\op@argii\@nil +} +\def\op@length@after@digit#1#2\@nil{% + \edef\op@argi{#1}% + \edef\op@argii{#2}% + \expandafter\op@testchar\op@argi + \ifop@isdigit + \advance\count@i by 1 + \let\next\op@length@after@digit + \else \ifop@isdecimalsep + \let\next\op@length@after@decimalsep + \else + \op@error{#1#2 not allowed here. \space I forget it}% + {See documentation for valid number. Characters before + are OK}% + \let\next\relax + \let\op@argii\relax + \fi\fi + \ifx\empty\op@argii + \let\next\relax + \fi + \expandafter\next\op@argii\@nil +} +\def\op@length@after@sign#1#2\@nil{% + \edef\op@argi{#1}% + \edef\op@argii{#2}% + \expandafter\op@testchar\op@argi + \ifop@isplus + \let\next\op@length@after@sign + \else \ifop@isminus + \ifnum\@nameuse{OP@\op@name @s}=0 + \@namexdef{OP@\op@name @s}{1}% + \else + \@namexdef{OP@\op@name @s}{0}% + \fi + \let\next\op@length@after@sign + \else \ifop@isdecimalsep + \ifx\empty\op@argii + \op@error{#1\space isn't a valid number}% + {See documentation for syntax of valid number}% + \let\next\relax + \else + \count@i=0 + \count@ii=0 + \let\next\op@length@after@decimalsep + \fi + \else \ifop@isdigit + \count@i=1 + \count@ii=0 + \ifx\empty\op@argii + \let\next\relax + \else + \let\next\op@length@after@digit + \fi + \fi\fi\fi\fi + \expandafter\next\op@argii\@nil +} +\def\op@length@after@decimalsep#1#2\@nil{% + \edef\op@argi{#1}% + \edef\op@argii{#2}% + \expandafter\op@testchar\op@argi + \ifop@isdigit + \advance\count@ii by 1 + \let\next\op@length@after@decimalsep + \else + \op@error{#1#2 not allowed here. \space I forget it}% + {See documentation for syntax of valid number. Characters + before is OK}% + \let\next\relax + \let\op@argii\relax + \fi + \ifx\empty\op@argii + \let\next\relax + \let\op@argii\relax + \fi + \expandafter\next\op@argii\@nil +} +\def\op@unsplit#1#2{% + \begingroup + \edef\op@name{#1}% + \ifnum\@nameuse{OP@\op@name @s}=1 + \def\op@macroname{-}% + \else + \def\op@macroname{}% + \fi + \count@z=\@nameuse{OP@\op@name @i}\relax + \count@i=\@nameuse{OP@\op@name @w}\relax + \loop + \ifnum\count@z>0 + \edef\op@macroname{\op@macroname + \@nameuse{OP@\op@name @\the\count@i}}% + \advance\count@z by-1 + \advance\count@i by-1 + \repeat + \ifnum\count@i>0 + \edef\op@macroname{\op@macroname\op@decimalsepsymbol}% + \loop + \ifnum\count@i>0 + \edef\op@macroname{\op@macroname + \@nameuse{OP@\op@name @\the\count@i}}% + \advance\count@i by-1 + \repeat + \fi + \@namexdef{Op@#2}{\op@macroname}% + \endgroup +} +\def\oplput(#1,#2)#3{\leavevmode + \vbox to\z@{\vss\hbox{\raise #2\oplineheight \hbox to\z@{% + \kern #1\opcolumnwidth #3\hss}}}% + \ignorespaces +} +\def\oprput(#1,#2)#3{\leavevmode + \vbox to \z@{\vss\hbox{\raise #2\oplineheight \hbox to\z@{% + \hss#3\kern -#1\opcolumnwidth}}}% + \ignorespaces +} +\def\ophline(#1,#2)#3{\leavevmode + \vbox to\z@{\vss\hbox{\raise #2\oplineheight \hbox to\z@{% + \kern #1\opcolumnwidth + \vrule width#3\opcolumnwidth + depth0.5\op@hrulewidth height0.5\op@hrulewidth \hss}}}% + \ignorespaces +} +\def\opvline(#1,#2)#3{\leavevmode + \vbox to\z@{\vss\hbox{\raise #2\oplineheight \hbox to\z@{% + \kern #1\opcolumnwidth \kern-0.5\op@vrulewidth + \vrule width\op@vrulewidth depth#3\oplineheight height\z@ \hss}}}% + \ignorespaces +} +\def\op@makebox#1#2#3#4{% + \begingroup + \edef\op@name{#4}% + \dimen0=\opcolumnwidth + \count@z=#1% + \advance\count@z by-\@nameuse{OP@\op@name @i}\relax + \multiply\dimen0 by\count@z + \global\setbox0=\hbox{% + \op@strut\vrule width\dimen0 height\z@ depth\z@}% + \count@z=\@nameuse{OP@\op@name @i}\relax + \count@i=\@nameuse{OP@\op@name @w}\relax + \loop + \ifnum\count@z>0 + \op@setstyle{#3.\the\count@z}% + \global\setbox0=\hbox{\box0 + \hbox to\opcolumnwidth{\hss\the\op@currentstyle + {\@nameuse{OP@\op@name @\the\count@i}}\hss}}% + \advance\count@z by-1 + \advance\count@i by-1 + \repeat + \ifnum\count@i>0 + \op@setstyle{#3.d}% + \global\setbox0=\hbox{\box0 + \hbox to\op@decimalsepwidth{\hss + \vrule width\op@decimalsepoffset height\z@ depth\z@ + \the\op@currentstyle\op@decimalsepsymbol \hss}}% + \count@z=-1 + \loop + \ifnum\count@i>0 + \op@setstyle{#3.\the\count@z}% + \global\setbox0=\hbox{\box0 + \hbox to\opcolumnwidth{\hss\the\op@currentstyle + {\@nameuse{OP@\op@name @\the\count@i}}\hss}}% + \advance\count@z by-1 + \advance\count@i by-1 + \repeat + \fi + \dimen0=\opcolumnwidth + \count@z=#2\relax + \advance\count@z by-\@nameuse{OP@\op@name @d}\relax + \multiply\dimen0 by\count@z + \global\setbox0=\hbox{\box0 + \vrule width\dimen0 height\z@ depth\z@}% + \endgroup +} +\def\op@setstyle#1{% + \edef\op@arg{#1}% + \expandafter\op@@setstyle\op@arg..\@nil +} +\def\op@@setstyle#1.#2.#3\@nil{% + \edef\op@styleroot{#1}% + \edef\op@styleindex{#2}% + \op@setstylesubindex#3.\@nil + \ifx\empty\op@stylesubindex + \@ifundefined{op@\op@styleroot.\op@styleindex}% + {\op@currentstyle={\@nameuse{op@\op@styleroot.0}}}% + {\op@currentstyle={\@nameuse{op@\op@styleroot.\op@styleindex}}}% + \else + \@ifundefined{op@\op@styleroot.\op@styleindex.\op@stylesubindex}% + {\@ifundefined{op@\op@styleroot.\op@styleindex}% + {\op@currentstyle={\@nameuse{op@\op@styleroot.0}}}% + {\op@currentstyle={\@nameuse{op@\op@styleroot.\op@styleindex}}}% + } + {\op@currentstyle= + {\@nameuse{op@\op@styleroot.\op@styleindex.\op@stylesubindex}}}% + \fi +} +\def\op@setstylesubindex#1.#2\@nil{\def\op@stylesubindex{#1}} +\def\opdisplay{\@ifnextchar[{\op@displaypar}{\op@displaypar[nil]}} +\def\op@displaypar[#1]#2#3{% + \begingroup + \opset{#1}% + \op@split{#3}{r}% + \ifop@error + \op@errorwrite + \else + \op@display{#2}{r}% + \fi + \endgroup +} +\def\op@display#1#2{% + \op@makebox{\@nameuse{OP@#2@i}}{\@nameuse{OP@#2@d}}{#1}{#2}% + \leavevmode\box0 +} +\def\opprint#1{% + \op@split{#1}{r}% + \ifop@error + \op@errorwrite + \else + \op@unsplit{r}{@r}% + \Op@@r + \fi +} +\def\op@format#1#2#3{% + \begingroup + \count@iii=#1\relax + \count@iv=#2\relax + \count@z=\count@iv + \advance\count@z by-\@nameuse{OP@#3@d}\relax + \ifnum\count@z>0 + \count@i=\@nameuse{OP@#3@w}\relax + \advance\count@z by\count@i\relax + \loop + \@namexdef{OP@#3@\the\count@z}{\@nameuse{OP@#3@\the\count@i}}% + \advance\count@i by-1 + \advance\count@z by-1\relax + \ifnum\count@i>0 + \repeat + \loop + \@namexdef{OP@#3@\the\count@z}{0}% + \advance\count@z by-1\relax + \ifnum\count@z>0 + \repeat + \@namexdef{OP@#3@d}{\the\count@iv}% + \count@i=\@nameuse{OP@#3@i}% + \advance\count@i by\count@iv\relax + \@namexdef{OP@#3@w}{\the\count@i}% + \fi + \count@z=\count@iii + \advance\count@z by-\@nameuse{OP@#3@i}\relax + \ifnum\count@z>0 + \count@i=\@nameuse{OP@#3@w}\relax + \loop + \advance\count@i by1 + \@namexdef{OP@#3@\the\count@i}{0}% + \advance\count@z by-1\relax + \ifnum\count@z>0 + \repeat + \@namexdef{OP@#3@i}{\the\count@iii}% + \fi + \count@i=\@nameuse{OP@#3@i}\relax + \advance\count@i by\@nameuse{OP@#3@d}\relax + \@namexdef{OP@#3@w}{\the\count@i}% + \endgroup +} +\def\opunzero#1{% + \op@split{#1}{uzr}% + \ifop@error + \op@errorwrite + \else + \op@unzero{uzr}% + \op@unsplit{uzr}{#1}% + \fi +} +\def\op@unzero#1{% + \begingroup + \count@z=\@nameuse{OP@#1@i}\relax + \count@i=\@nameuse{OP@#1@w}\relax + \count@ii=\@nameuse{OP@#1@i}\relax + \loop + \ifnum\count@z>1\relax + \ifnum\@nameuse{OP@#1@\the\count@i}=0\relax + \advance\count@ii by-1 + \else + \count@z=0 + \fi + \advance\count@z by-1 + \advance\count@i by-1 + \repeat + \@namexdef{OP@#1@i}{\the\count@ii}% + \count@z=\@nameuse{OP@#1@d}\relax + \count@i=1\relax + \count@ii=0\relax + \loop + \ifnum\count@z>0\relax + \ifnum\@nameuse{OP@#1@\the\count@i}=0\relax + \advance\count@ii by1 + \advance\count@z by-1 + \advance\count@i by1 + \else + \count@z=0 + \fi + \repeat + \ifnum\count@ii>0\relax + \count@z=1\relax + \count@i=\@nameuse{OP@#1@w}\relax + \count2=\count@ii + \advance\count@ii by1 + \loop + \@namexdef{OP@#1@\the\count@z}{\@nameuse{OP@#1@\the\count@ii}}% + \ifnum\count@ii<\count@i + \advance\count@z by1 + \advance\count@ii by1 + \repeat + \count@ii=\@nameuse{OP@#1@d}% + \advance\count@ii by-\count2 + \@namexdef{OP@#1@d}{\the\count@ii}% + \fi + \ifnum\@nameuse{OP@#1@i}=1\relax + \ifnum\@nameuse{OP@#1@d}=0\relax + \ifnum\@nameuse{OP@#1@1}=0 + \@namexdef{OP@#1@s}{0}% + \fi + \fi + \fi + \count@i=\@nameuse{OP@#1@i}\relax + \advance\count@i by\@nameuse{OP@#1@d}\relax + \@namexdef{OP@#1@w}{\the\count@i}% + \endgroup +} +\def\opcopy#1#2{% + \op@split{#1}{a}% + \ifop@error + \op@errorwrite + \else + \op@unsplit{a}{#2}% + \fi +} +\def\op@copy#1#2{% + \begingroup + \@namexdef{OP@#2@w}{\@nameuse{OP@#1@w}}% + \@namexdef{OP@#2@i}{\@nameuse{OP@#1@i}}% + \@namexdef{OP@#2@d}{\@nameuse{OP@#1@d}}% + \@namexdef{OP@#2@s}{\@nameuse{OP@#1@s}}% + \count@z=\@nameuse{OP@#2@w}\relax + \loop + \ifnum\count@z>0 + \@namexdef{OP@#2@\the\count@z}{\@nameuse{OP@#1@\the\count@z}}% + \advance\count@z by-1 + \repeat + \endgroup +} +\def\opcmp#1#2{% + \op@split{#1}{ca}% + \op@split{#2}{cb}% + \ifop@error + \op@errorwrite + \else + \op@cmp{ca}{cb}% + \fi +} +\def\op@cmp#1#2{% + \begingroup + \global\opgtfalse + \global\opgefalse + \global\opeqfalse + \global\opneqfalse + \global\oplefalse + \global\opltfalse + \op@copy{#1}{ca}% + \op@unzero{ca}% + \op@copy{#2}{cb}% + \op@unzero{cb}% + \ifnum\OP@ca@s>\OP@cb@s\relax + \global\oplttrue + \global\opletrue + \global\opneqtrue + \else \ifnum\OP@ca@s<\OP@cb@s\relax + \global\opgttrue + \global\opgetrue + \global\opneqtrue + \else + \ifnum\OP@ca@i>\OP@cb@i\relax + \global\opgetrue + \global\opgttrue + \global\opneqtrue + \else \ifnum\OP@ca@i<\OP@cb@i\relax + \global\opletrue + \global\oplttrue + \global\opneqtrue + \else + \op@againtrue + \count@i=\OP@ca@w\relax + \count@ii=\OP@cb@w\relax + \loop + \ifop@again + \ifnum\@nameuse{OP@ca@\the\count@i}> + \@nameuse{OP@cb@\the\count@ii}\relax + \op@againfalse + \global\opgttrue + \global\opgetrue + \global\opneqtrue + \else \ifnum\@nameuse{OP@ca@\the\count@i}< + \@nameuse{OP@cb@\the\count@ii}\relax + \op@againfalse + \global\oplttrue + \global\opletrue + \global\opneqtrue + \else \ifnum\count@i=1\relax + \op@againfalse + \ifnum\count@ii=1\relax + \global\opeqtrue + \global\opgetrue + \global\opletrue + \else + \global\oplttrue + \global\opletrue + \global\opneqtrue + \fi + \else \ifnum\count@ii=1\relax + \op@againfalse + \global\opgttrue + \global\opgetrue + \global\opneqtrue + \fi\fi\fi\fi + \advance\count@i by-1 + \advance\count@ii by-1 + \repeat + \fi\fi + \ifnum\OP@ca@s=1\relax + \ifopneq + \ifopgt + \global\opgtfalse + \global\opgefalse + \global\oplttrue + \global\opletrue + \else + \global\opgttrue + \global\opgetrue + \global\opltfalse + \global\oplefalse + \fi + \fi + \fi + \fi\fi + \endgroup +} +\def\op@max#1#2{% + \ifnum#1>#2 + #1% + \else + #2% + \fi +} +\def\op@textoperation#1#2#3#4#5{% + \mathsurround=\z@\relax + \ifop@deletezero + \op@unzero{#1}% + \op@unzero{#3}% + \op@unzero{#5}% + \fi + \op@unsplit{#1}{@a}% + \op@unsplit{#3}{@b}% + \op@unsplit{#5}{@r}% + \ifnum\@nameuse{OP@#1@s}=1\relax + \ifx\op@parenthesisnegative\op@string@all + $(\Op@@a)$% + \else + $\Op@@a$% + \fi + \else + $\Op@@a$% + \fi + $\>$\nobreak#2$\>$\penalty\binoppenalty + \ifnum\@nameuse{OP@#3@s}=1\relax + \ifx\op@parenthesisnegative\op@string@all + $(\Op@@b)$% + \else \ifx\op@parenthesisnegative\op@string@last + $(\Op@@b)$% + \else + $\Op@@b$% + \fi\fi + \else + $\Op@@b$% + \fi + $\;$\nobreak#4$\;$\penalty\relpenalty + \ifnum\@nameuse{OP@#5@s}=1\relax + \ifx\op@parenthesisnegative\op@string@all + $(\Op@@r)$% + \else + $\Op@@r$% + \fi + \else + $\Op@@r$% + \fi +} +\def\opadd{\@ifnextchar*{\op@addstar}{\op@addnostar}} +\def\op@addstar*#1#2#3{% + \begingroup + \op@split{#1}{a}% + \op@split{#2}{b}% + \ifop@error + \op@errorwrite + \else + \ifop@deletezero + \op@unzero{a}% + \op@unzero{b}% + \fi + \ifnum\OP@a@s=0 + \ifnum\OP@b@s=0 + \xdef\op@realsymbol{\op@addsymbol}% + \op@add{a}{b}{r}% + \else + \def\OP@b@s{0}% + \op@cmp{a}{b}% + \ifopgt + \xdef\op@realsymbol{\op@subsymbol}% + \op@sub{a}{b}{r}% + \else + \xdef\op@realsymbol{\op@subsymbol}% + \op@copy{a}{r}% + \op@copy{b}{a}% + \op@copy{r}{b}% + \op@sub{a}{b}{r}% + \xdef\OP@r@s{1}% + \fi + \fi + \else + \ifnum\OP@b@s=0 + \def\OP@a@s{0}% + \op@cmp{a}{b}% + \ifopgt + \xdef\op@realsymbol{\op@subsymbol}% + \op@sub{a}{b}{r}% + \xdef\OP@r@s{1}% + \else + \xdef\op@realsymbol{\op@subsymbol}% + \op@copy{a}{r}% + \op@copy{b}{a}% + \op@copy{r}{b}% + \op@sub{a}{b}{r}% + \fi + \else + \xdef\op@realsymbol{\op@addsymbol}% + \op@add{a}{b}{r}% + \xdef\OP@r@s{1}% + \fi + \fi + \ifop@error\else + \ifop@deletezero + \op@unzero{r}% + \fi + \op@unsplit{r}{#3}% + \fi + \fi + \endgroup +} +\def\op@addnostar{\@ifnextchar[{\op@addarg}{\op@addarg[nil]}} +\def\op@addarg[#1]#2#3{% + \begingroup + \opset{#1}% + \ifx\op@style\op@string@display + \ifx\op@country\op@string@french + \op@adddisplayone{#2}{#3}% + \else \ifx\op@country\op@string@american + \op@adddisplayone{#2}{#3}% + \else \ifx\op@country\op@string@russian + \op@adddisplayone{#2}{#3}% + \else + \op@error{Country \op@country\space isn't recognize} + {For now, only `french', `american' and + `russian' are valid} + \fi\fi\fi + \else + \op@addstar*{#2}{#3}{@r}% + \op@split{#2}{a}% + \op@split{#3}{b}% + \op@split{@r}{r}% + \ifop@deletezero + \op@unzero{a}% + \op@unzero{b}% + \fi + \op@textoperation{a}{\op@addsymbol}{b}{\op@equalsymbol}{r}% + \fi + \endgroup +} +\def\op@adddisplayone#1#2{% + \op@addstar*{#1}{#2}{@r}% + \op@addsubdisplayone +} +\def\op@add#1#2#3{% + \begingroup + \global\op@carryfalse + \count@i=\op@max{\@nameuse{OP@#1@i}}{\@nameuse{OP@#2@i}}% + \count@ii=\op@max{\@nameuse{OP@#1@d}}{\@nameuse{OP@#2@d}}% + \op@format{\the\count@i}{\the\count@ii}{#1}% + \op@format{\the\count@i}{\the\count@ii}{#2}% + \@namexdef{OP@#3@i}{\the\count@i}% + \@namexdef{OP@#3@d}{\the\count@ii}% + \@namexdef{OP@#3@s}{0}% + \xdef\OP@carry@s{0}% + \xdef\OP@carry@d{0}% + \advance\count@i by\count@ii + \@namexdef{OP@#3@w}{\the\count@i}% + \xdef\OP@carry@i{\the\count@i}% + \xdef\OP@carry@w{\the\count@i}% + \count@ii=1 + \def\op@carry{0}% + \@namexdef{OP@carry@1}{ }% + \loop + \count@z=\@nameuse{OP@#1@\the\count@ii}% + \advance\count@z by\@nameuse{OP@#2@\the\count@ii}% + \advance\count@z by\op@carry\relax + \ifnum\count@z>9 + \advance\count@z by-10 + \def\op@carry{1}% + \global\op@carrytrue + \else + \def\op@carry{0}% + \fi + \@namexdef{OP@#3@\the\count@ii}{\the\count@z}% + \ifnum\count@ii<\count@i + \advance\count@ii by1\relax + \ifnum\op@carry=0 + \@namexdef{OP@carry@\the\count@ii}{ }% + \else + \@namexdef{OP@carry@\the\count@ii}{1}% + \global\op@carrytrue + \fi + \repeat + \ifnum\op@carry=1 + \advance\count@i by1 + \@namexdef{OP@#3@w}{\the\count@i}% + \@namexdef{OP@#3@\the\count@i}{1}% + \ifop@lastcarry + \@namexdef{OP@carry@w}{\the\count@i}% + \@namexdef{OP@carry@i}{\the\count@i}% + \@namexdef{OP@carry@\the\count@i}{1}% + \global\op@carrytrue + \fi + \count@i=\@nameuse{OP@#3@i}\relax + \advance\count@i by1 + \@namexdef{OP@#3@i}{\the\count@i}% + \fi + \endgroup +} +\def\opsub{\@ifnextchar*{\op@substar}{\op@subnostar}} +\def\op@substar*#1#2#3{% + \begingroup + \op@split{#1}{a}% + \op@split{#2}{b}% + \ifop@error + \op@errorwrite + \else + \ifnum\OP@a@s=0 + \ifnum\OP@b@s=0 + \op@cmp{a}{b}% + \ifopgt + \xdef\op@realsymbol{\op@subsymbol}% + \op@sub{a}{b}{r}% + \else + \ifx\op@behaviorsub\op@string@warning + \op@warning{Substraction with first operand less than + second one} + \else\ifx\op@behaviorsub\op@string@error + \op@error{Substraction with first operand less than + second one}% + {I can't do a-b with a and b positive and a<b}% + \global\op@errortrue + \fi\fi + \ifop@error\else + \xdef\op@realsymbol{\op@subsymbol}% + \op@copy{a}{r}% + \op@copy{b}{a}% + \op@copy{r}{b}% + \op@sub{a}{b}{r}% + \xdef\OP@r@s{1}% + \fi + \fi + \else + \xdef\op@realsymbol{\op@addsymbol}% + \op@add{a}{b}{r}% + \fi + \else + \ifnum\OP@b@s=0 + \xdef\op@realsymbol{\op@addsymbol}% + \op@add{a}{b}{r}% + \xdef\OP@r@s{1}% + \else + \op@cmp{a}{b}% + \ifoplt + \xdef\op@realsymbol{\op@subsymbol}% + \op@sub{a}{b}{r}% + \xdef\OP@r@s{1}% + \else + \xdef\op@realsymbol{\op@subsymbol}% + \op@copy{a}{r}% + \op@copy{b}{a}% + \op@copy{r}{b}% + \op@sub{a}{b}{r}% + \fi + \fi + \fi + \ifop@error\else + \ifop@deletezero + \op@unzero{r}% + \fi + \op@unsplit{r}{#3}% + \fi + \fi + \endgroup +} +\def\op@subnostar{\@ifnextchar[{\op@subarg}{\op@subarg[nil]}} +\def\op@subarg[#1]#2#3{% + \begingroup + \opset{#1}% + \ifx\op@style\op@string@display + \ifx\op@country\op@string@french + \op@subdisplayone{#2}{#3}% + \else \ifx\op@country\op@string@american + \op@subdisplayone{#2}{#3}% + \else \ifx\op@country\op@string@russian + \op@subdisplayone{#2}{#3}% + \else + \op@error{Country \op@country\space isn't recognize} + {For now, only `french', `american' and + `russian' are valid} + \fi\fi\fi + \else + \op@substar*{#2}{#3}{@r}% + \op@split{#2}{a}% + \op@split{#3}{b}% + \op@split{@r}{r}% + \ifop@deletezero + \op@unzero{a}% + \op@unzero{b}% + \fi + \op@textoperation{a}{\op@subsymbol}{b}{\op@equalsymbol}{r}% + \fi + \endgroup +} +\def\op@subdisplayone#1#2{% + \op@substar*{#1}{#2}{@r}% + \op@addsubdisplayone +} +\def\op@sub#1#2#3{% + \begingroup + \global\op@carryfalse + \count@i=\op@max{\@nameuse{OP@#1@i}}{\@nameuse{OP@#2@i}}\relax + \count@ii=\op@max{\@nameuse{OP@#1@d}}{\@nameuse{OP@#2@d}}\relax + \count@iii=\@nameuse{OP@#2@w}\relax + \advance\count@iii by1 + \op@format{\the\count@i}{\the\count@ii}{#1}% + \op@format{\the\count@i}{\the\count@ii}{#2}% + \@namexdef{OP@#3@i}{\the\count@i}% + \@namexdef{OP@#3@d}{\the\count@ii}% + \@namexdef{OP@#3@s}{0}% + \xdef\OP@carry@s{0}% + \xdef\OP@carry@d{0}% + \advance\count@i by\count@ii + \@namexdef{OP@#3@w}{\the\count@i}% + \xdef\OP@carry@i{\the\count@i}% + \xdef\OP@carry@w{\the\count@i}% + \count@ii=1 + \def\op@carry{0}% + \@namexdef{OP@carry@1}{ }% + \loop + \count@z=\@nameuse{OP@#1@\the\count@ii}% + \advance\count@z by-\@nameuse{OP@#2@\the\count@ii}% + \advance\count@z by-\op@carry\relax + \ifnum\count@z<0 + \advance\count@z by10 + \def\op@carry{1}% + \else + \def\op@carry{0}% + \fi + \@namexdef{OP@#3@\the\count@ii}{\the\count@z}% + \ifnum\count@ii<\count@i + \advance\count@ii by1\relax + \@namexdef{OP@carry@\the\count@ii}{ }% + \ifnum\op@carry=0 \else + \ifop@lastcarry + \@namexdef{OP@carry@\the\count@ii}{1}% + \global\op@carrytrue + \else + \ifnum\count@ii<\count@iii\relax + \@namexdef{OP@carry@\the\count@ii}{1}% + \global\op@carrytrue + \fi + \fi + \fi + \repeat + \endgroup +} +\def\op@addsubdisplayone{% + \begingroup + \ifop@error\else + \ifop@deletezero + \op@unzero{a}% + \op@unzero{b}% + \fi + \ifx\op@realsymbol\op@subsymbol + \ifnum\OP@a@d<\OP@b@d\relax + \op@format{\OP@a@i}{\OP@b@d}{a}% + \fi + \fi + \count@i=\op@max{\OP@a@i}{\OP@b@i}% + \count@i=\op@max{\the\count@i}{\OP@r@i}% + \advance\count@i by1 + \count@ii=\op@max{\OP@a@d}{\OP@b@d}% + \count@ii=\op@max{\the\count@ii}{\OP@r@d}% + \count@z=\count@i + \advance\count@z by\count@ii + \setbox1=\hbox to\count@z\opcolumnwidth{% + \ifx\op@voperator\op@string@top + \oplput(0,2){\op@realsymbol}% + \else\ifx\op@voperator\op@string@bottom + \oplput(0,1){\op@realsymbol}% + \else + \oplput(0,1.5){\op@realsymbol}% + \fi\fi + \ophline(0,0.75){\the\count@z}% + \ifnum\OP@r@d>0\relax + \oplput(\the\count@z,0.75){% + \vrule width\op@decimalsepwidth + depth0.5\op@hrulewidth height0.5\op@hrulewidth} + \fi + \ifx\op@realsymbol\op@subsymbol + \ifop@carrysub + \ifop@carry + \op@makebox{\the\count@z}{0}{carrystyle}{carry}% + \oplput(\op@offsetcarry,2){\kern\opcolumnwidth\copy0}% + \oplput(\op@offsetcarry,1){\box0}% + \fi + \fi + \fi + \vbox{% + \ifx\op@realsymbol\op@addsymbol + \ifop@carryadd + \ifop@carry + \op@makebox{\the\count@z}{0}{carrystyle}{carry}% + \hbox{\box0}% + \fi + \fi + \fi + \op@makebox{\the\count@i}{\the\count@ii}{operandstyle.1}{a}% + \hbox{\box0}% + \op@makebox{\the\count@i}{\the\count@ii}{operandstyle.2}{b}% + \hbox{\box0}% + \op@makebox{\the\count@i}{\the\count@ii}{resultstyle}{r}% + \hbox{\box0}% + }% + }% + \leavevmode + \ifx\op@voperation\op@string@center + \lower1\oplineheight\box1 + \else\ifx\op@voperation\op@string@top + \lower2\oplineheight\box1 + \else + \box1 + \fi\fi + \fi + \endgroup +} +\def\opmul{\@ifnextchar*{\op@mulstar}{\op@mulnostar}} +\def\op@mulstar*#1#2#3{% + \begingroup + \op@split{#1}{a}% + \op@split{#2}{b}% + \ifop@error + \op@errorwrite + \else + \ifop@deletezero + \op@unzero{a}% + \op@unzero{b}% + \fi + \op@mul{a}{b}{r}% + \ifop@deletezero + \op@unzero{r}% + \fi + \xdef\op@realsymbol{\op@mulsymbol}% + \ifnum\OP@a@s=\OP@b@s\else + \xdef\OP@r@s{1}% + \fi + \ifop@error\else + \op@unsplit{r}{#3}% + \fi + \fi + \endgroup +} +\def\op@mulnostar{\@ifnextchar[{\op@mularg}{\op@mularg[nil]}} +\def\op@mularg[#1]#2#3{% + \begingroup + \opset{#1}% + \ifx\op@style\op@string@display + \ifx\op@country\op@string@french + \op@muldisplayone{#2}{#3}% + \else \ifx\op@country\op@string@american + \op@muldisplayone{#2}{#3}% + \else \ifx\op@country\op@string@russian + \op@muldisplayone{#2}{#3}% + \else + \op@error{Country \op@country\space isn't recognize} + {For now, only `french', `american' and + `russian' are valid} + \fi\fi\fi + \else + \op@mulstar*{#2}{#3}{@r}% + \op@split{#2}{a}% + \op@split{#3}{b}% + \op@split{@r}{r}% + \ifop@deletezero + \op@unzero{a}% + \op@unzero{b}% + \op@unzero{r}% + \fi + \op@textoperation{a}{\op@mulsymbol}{b}{\op@equalsymbol}{r}% + \fi + \endgroup +} +\def\op@muldisplayone#1#2{% + \begingroup + \ifop@error\else + \op@split{#1}{a}% + \op@split{#2}{b}% + \ifop@deletezero + \op@unzero{a}% + \op@unzero{b}% + \fi + \op@mul{a}{b}{r}% + \ifnum\OP@b@i=1 + \expandafter\if\csname OP@b@\OP@b@w\endcsname0 + \ifnum\OP@r@i>1 + \expandafter\if\csname OP@r@\OP@r@w\endcsname0 + \count@i=\OP@r@w + \advance\count@i\m@ne + \edef\OP@r@w{\the\count@i}% + \count@i=\OP@r@i + \advance\count@i\m@ne + \edef\OP@r@i{\the\count@i}% + \fi\fi\fi\fi + \setbox1=\hbox to\OP@r@w\opcolumnwidth{% + \vbox{% + \ifx\op@hfactor\op@string@right + \count@i=\OP@r@w + \advance\count@i by-\OP@a@d + \op@makebox{\the\count@i}{\OP@a@d}{operandstyle.1}{a}% + \hbox{\box0}% + \count@i=\OP@r@w + \advance\count@i by-\OP@b@d + \op@makebox{\the\count@i}{\OP@b@d}{operandstyle.2}{b}% + \hbox{\box0}% + \else + \count@i=\OP@r@w + \count@ii=\op@max{\OP@a@d}{\OP@b@d}% + \advance\count@i by-\count@ii + \op@makebox{\the\count@i}{\the\count@ii}{operandstyle.1}{a}% + \hbox{\box0}% + \op@makebox{\the\count@i}{\the\count@ii}{operandstyle.2}{b}% + \hbox{\box0}% + \fi + \op@againtrue + \ifx\op@displayintermediary\op@string@none + \ifnum\OP@b@w=1 + \op@againfalse + \fi + \fi + \global\count@z=0\relax + \ifop@again + \count@ii=0\relax + \setbox2=\hbox{}% + \loop + \ifnum\count@ii<\OP@b@w + \advance\count@ii by1 + \count@iii=\@nameuse{OP@b@\the\count@ii}% + \count@iv=\OP@r@w + \advance\count@iv by-\count@ii + \advance\count@iv by1 + \op@makebox{\the\count@iv}{0}% + {intermediarystyle.\the\count@ii}{T\the\count@iii}% + \ifx\op@displayintermediary\op@string@all + \hbox{\box0\copy2}% + \global\advance\count@z by1 + \else + \ifnum\the\count@iii=0 + \ifx\op@displayshiftintermediary\op@string@shift + \setbox2=\hbox{\box2\hbox to\opcolumnwidth{% + \hss\op@shiftintermediarysymbol\hss}}% + \fi + \else + \hbox{\box0\copy2}% + \global\advance\count@z by1 + \ifx\op@displayshiftintermediary\op@string@shift + \setbox2=\hbox{}% + \fi + \fi + \fi + \ifx\op@displayshiftintermediary\op@string@all + \setbox2=\hbox{\box2\hbox to\opcolumnwidth{% + \hss\op@shiftintermediarysymbol\hss}}% + \fi + \repeat + \fi + \op@makebox{\OP@r@i}{\OP@r@d}{resultstyle}{r}% + \hbox{\box0}% + }% + \count@i=\OP@r@w + \ophline(-\the\count@i,0.75){\the\count@i}% + \ifnum\OP@r@d>0\relax + \oprput(-\the\count@i,0.75){% + \vrule width\op@decimalsepwidth + depth0.5\op@hrulewidth height0.5\op@hrulewidth} + \fi + \ifx\op@hfactor\op@string@right + \count@i=\op@max{\OP@a@w}{\OP@b@w}% + \else + \count@i=\op@max{\OP@a@d}{\OP@b@d}% + \advance\count@i by\op@max{\OP@a@i}{\OP@b@i}% + \fi + \advance\count@i by1\relax + \ophline(-\the\count@i,\the\count@z.75){\the\count@i}% + \ifx\op@voperator\op@string@top + \advance\count@z by2 + \oplput(-\the\count@i,\the\count@z){\op@mulsymbol}% + \advance\count@z by-2 + \else\ifx\op@voperator\op@string@bottom + \advance\count@z by1 + \oplput(-\the\count@i,\the\count@z){\op@mulsymbol}% + \advance\count@z by-1 + \else + \advance\count@z by1 + \oplput(-\the\count@i,\the\count@z.5){\op@mulsymbol}% + \advance\count@z by-1 + \fi\fi + }% + \leavevmode + \ifx\op@voperation\op@string@center + \advance\count@z by3 + \dimen0=\oplineheight + \multiply\dimen0 by\count@z + \dimen0=0.5\dimen0 + \lower\dimen0\box1 + \else\ifx\op@voperation\op@string@top + \advance\count@z by2 + \dimen0=\oplineheight + \multiply\dimen0 by\count@z + \lower\dimen0\box1 + \else + \box1 + \fi\fi + \fi + \endgroup +} +\def\op@mul#1#2#3{% + \begingroup + \op@multable{#1}% + \count@z=\@nameuse{OP@#2@w}\relax + \op@copy{zero}{mr}% + \loop + \count@iii=\@nameuse{OP@#2@\the\count@z}% + \advance\count@z by-1 + \op@copy{T\the\count@iii}{rr}% + \op@lshift{\the\count@z}{rr}% + \op@add{rr}{mr}{mr}% + \ifnum\count@z>0 + \repeat + \count@z=\@nameuse{OP@#1@d}% + \advance\count@z by\@nameuse{OP@#2@d}% + \xdef\OP@mr@d{\the\count@z}% + \count@i=\OP@mr@w + \advance\count@i by-\count@z + \ifnum\count@i>0\relax + \xdef\OP@mr@i{\the\count@i}% + \else + \xdef\OP@mr@i{1}% + \count@z=\@nameuse{OP@mr@d}% + \advance\count@z by1 + \count@i=\@nameuse{OP@mr@w}% + \@namexdef{OP@mr@w}{\the\count@z}% + \loop + \ifnum\count@i<\count@z + \advance\count@i by1 + \@namexdef{OP@mr@\the\count@i}{0}% + \repeat + \fi + \op@copy{mr}{#3}% + \endgroup +} +\def\op@multable#1{% + \op@copy{#1}{T1}% + \@namexdef{OP@T1@i}{\@nameuse{OP@T1@w}}% + \@namexdef{OP@T1@d}{0}% + \@namexdef{OP@T1@s}{0}% + \op@add{T1}{T1}{T2}% + \op@add{T1}{T2}{T3}% + \op@add{T1}{T3}{T4}% + \op@add{T1}{T4}{T5}% + \op@add{T1}{T5}{T6}% + \op@add{T1}{T6}{T7}% + \op@add{T1}{T7}{T8}% + \op@add{T1}{T8}{T9}% + \op@unzero{T1}% + \op@format{\@nameuse{OP@T1@i}}{\@nameuse{OP@T1@d}}{T0}% +} +\def\op@lshift#1#2{% + \begingroup + \count@i=#1\relax + \count@z=\@nameuse{OP@#2@w}\relax + \advance\count@i by\count@z + \@namexdef{OP@#2@w}{\the\count@i}% + \@namexdef{OP@#2@i}{\the\count@i}% + \loop + \ifnum\count@z>0 + \@namexdef{OP@#2@\the\count@i}{\@nameuse{OP@#2@\the\count@z}}% + \advance\count@z by-1 + \advance\count@i by-1 + \repeat + \loop + \ifnum\count@i>0 + \@namexdef{OP@#2@\the\count@i}{0}% + \advance\count@i by-1 + \repeat + \endgroup +} +\def\op@rshift#1#2{% + \begingroup + \count@i=#1\relax + \count@z=\@nameuse{OP@#2@w}\relax + \advance\count@z by-\count@i + \ifnum\count@z>0 + \@namexdef{OP@#2@w}{\the\count@z}% + \@namexdef{OP@#2@i}{\the\count@z}% + \@namexdef{OP@#2@d}{0}% + \@namexdef{OP@#2@s}{0}% + \advance\count@i by1\relax + \count@ii=1 + \loop + \@namexdef{OP@#2@\the\count@ii}{\@nameuse{OP@#2@\the\count@i}}% + \advance\count@i by1 + \ifnum\count@ii<\count@z + \advance\count@ii by1 + \repeat + \else + \op@copy{zero}{#2}% + \fi + \endgroup +} +\def\opdiv{\@ifnextchar*{\op@divstar}{\op@divnostar}} +\def\op@divstar*{\@ifnextchar[{\op@divstararg}{\op@divstararg[nil]}} +\def\op@divstararg[#1]#2#3#4#5{% + \begingroup + \opset{#1} + \op@split{#2}{a}% + \op@split{#3}{b}% + \ifop@error + \op@errorwrite + \else + \op@unzero{a}% + \op@unzero{b}% + \edef\op@shift{\op@max{\OP@a@d}{\OP@b@d}}% + \op@mulpowerten{a}{\op@shift}% + \op@mulpowerten{b}{\op@shift}% + \xdef\OP@a@s{0}% + \xdef\OP@b@s{0}% + \ifop@period + \op@div{1}{a}{b}{q}{r}% + \else + \op@div{0}{a}{b}{q}{r}% + \fi + \op@split{#2}{a}% + \op@split{#3}{b}% + \op@unzero{a}% + \op@unzero{b}% + \ifnum\OP@a@s=0\relax + \ifnum\OP@b@s=0\relax + \else + \xdef\OP@q@s{1}% + \fi + \else + \xdef\OP@r@s{1}% + \ifnum\OP@b@s=0\relax + \xdef\OP@q@s{1}% + \fi + \fi + \ifop@error\else + \op@unsplit{q}{#4}% + \op@unsplit{r}{#5}% + \fi + \fi + \endgroup +} +\def\op@divnostar{\@ifnextchar[{\op@divarg}{\op@divarg[nil]}} +\def\op@divarg[#1]#2#3{% + \begingroup + \opset{#1}% + \op@split{#2}{a}% + \op@split{#3}{b}% + \ifop@error + \op@errorwrite + \else + \ifx\op@style\op@string@display + \op@unzero{a}% + \op@unzero{b}% + \ifx\op@shiftdecimalsep\op@string@none + \xdef\OP@a@i{\OP@a@w}% + \xdef\OP@a@d{0}% + \xdef\OP@b@i{\OP@b@w}% + \xdef\OP@b@d{0}% + \else\ifx\op@shiftdecimalsep\op@string@divisor + \xdef\OP@a@i{\OP@a@w}% + \xdef\OP@a@d{0}% + \xdef\OP@b@i{\OP@b@w}% + \xdef\OP@b@d{0}% + \op@unzero{a}% + \op@unzero{b}% + \else + \edef\op@shift{\op@max{\OP@a@d}{\OP@b@d}}% + \op@mulpowerten{a}{\op@shift}% + \op@mulpowerten{b}{\op@shift}% + \fi\fi + \fi + \ifop@period + \op@div{1}{a}{b}{q}{r}% + \else + \op@div{0}{a}{b}{q}{r}% + \fi + \ifx\op@style\op@string@display + \op@split{#2}{a}% + \op@split{#3}{b}% + \op@copy{q}{qq}% + \op@unzero{a}% + \op@unzero{b}% + \ifx\op@shiftdecimalsep\op@string@none + \def\op@shift{0}% + \count@v=\OP@a@d + \advance\count@v by-\OP@b@d\relax + \ifnum\count@v>0 + \op@divpowerten{qq}{\the\count@v}% + \else + \count@v=-\count@v + \op@mulpowerten{qq}{\the\count@v}% + \fi + \else\ifx\op@shiftdecimalsep\op@string@divisor + \edef\op@shift{\OP@a@d}% + \count@v=\OP@a@d + \advance\count@v by-\OP@b@d\relax + \ifnum\count@v>0 + \op@divpowerten{qq}{\the\count@v}% + \else + \count@v=-\count@v + \op@mulpowerten{qq}{\the\count@v}% + \fi + \edef\op@shift{\OP@b@d}% + \op@split{#2}{a}% + \ifx\op@strikedecimalsepsymbol\empty + \op@unzero{a}% + \else + \count@z=\OP@a@w + \fi + \op@mulpowerten{a}{\OP@b@d}% + \ifx\op@strikedecimalsepsymbol\empty\else + \advance\count@z by-\OP@a@d + \op@format{\the\count@z}{\OP@a@d}{a}% + \fi + \xdef\OP@b@i{\OP@b@w}% + \xdef\OP@b@d{0}% + \ifx\op@strikedecimalsepsymbol\empty + \op@unzero{b}% + \fi + \else + \edef\op@shift{\op@max{\OP@a@d}{\OP@b@d}}% + \ifx\op@strikedecimalsepsymbol\empty + \op@unzero{a}% + \op@unzero{b}% + \else + \count@z=\OP@a@w + \count@i=\OP@b@w + \fi + \op@mulpowerten{a}{\op@shift}% + \op@mulpowerten{b}{\op@shift}% + \ifx\op@strikedecimalsepsymbol\empty\else + \advance\count@z by-\OP@a@d + \op@format{\the\count@z}{\OP@a@d}{a}% + \advance\count@i by-\OP@b@d + \op@format{\the\count@i}{\OP@b@d}{b}% + \fi + \fi\fi + \ifx\op@country\op@string@french + \op@divdisplayone + \else \ifx\op@country\op@string@american + \op@divdisplayone + \else \ifx\op@country\op@string@russian + \op@divdisplayone + \else + \op@error{Country \op@country\space isn't recognize} + {For now, only `french', `american' and + `russian' are valid}% + \fi\fi\fi + \else + \ifnum\OP@a@s=\OP@b@s\else + \xdef\OP@q@s{1}% + \fi + \mathsurround=\z@\relax + \ifop@deletezero + \op@unzero{a}% + \op@unzero{b}% + \op@unzero{q}% + \fi + \op@unsplit{a}{@a}% + \op@unsplit{b}{@b}% + \op@unsplit{q}{@q}% + \ifnum\OP@a@s=1\relax + \ifx\op@parenthesisnegative\op@string@all + $(\Op@@a)$% + \else + $\Op@@a$% + \fi + \else + $\Op@@a$% + \fi + $\>$\nobreak\op@divsymbol$\>$\penalty\binoppenalty + \ifnum\OP@b@s=1\relax + \ifx\op@parenthesisnegative\op@string@all + $(\Op@@b)$% + \else \ifx\op@parenthesisnegative\op@string@last + $(\Op@@b)$% + \else + $\Op@@b$% + \fi\fi + \else + $\Op@@b$% + \fi + \op@cmp{zero}{r}% + \ifopeq + $\;$\nobreak\op@equalsymbol$\;$\penalty\relpenalty + \setbox0=\hbox{\Op@@q}% + \else + \ifop@period + $\;$\nobreak\op@equalsymbol$\;$\penalty\relpenalty + \setbox0=\hbox{% + \Op@@q + \setbox1=\hbox{0}% + \begingroup + \opcolumnwidth=\wd1 + \ophline(-\op@lengthperiod,\op@vruleperiod){\op@lengthperiod}% + \endgroup + \op@afterperiodsymbol + }% + \else + $\;$\nobreak\op@approxsymbol$\;$\penalty\relpenalty + \setbox0=\hbox{\Op@@q}% + \fi + \fi + \ifnum\OP@q@s=1\relax + \ifx\op@parenthesisnegative\op@string@all + $(\box0)$% + \else + $\box0$% + \fi + \else + $\box0$% + \fi + \fi + \fi + \endgroup +} +\def\opidiv{\@ifnextchar*{\op@idivstar}{\op@idivnostar}} +\def\op@idivstar*#1#2#3#4{% + \begingroup + \op@split{#1}{a}% + \op@split{#2}{b}% + \ifop@error + \op@errorwrite + \else + \op@unzero{a}% + \op@unzero{b}% + \edef\op@shift{\op@max{\OP@a@d}{\OP@b@d}}% + \op@mulpowerten{a}{\op@shift}% + \op@mulpowerten{b}{\op@shift}% + \xdef\OP@a@s{0}% + \xdef\OP@b@s{0}% + \op@periodfalse + \op@div{2}{a}{b}{q}{r}% + \op@split{#1}{a}% + \op@split{#2}{b}% + \op@unzero{a}% + \op@unzero{b}% + \ifnum\OP@a@s=0\relax + \ifnum\OP@b@s=0\relax + \else + \xdef\OP@q@s{1}% + \fi + \else + \op@add{one}{q}{q}% + \ifnum\OP@b@s=0\relax + \xdef\OP@q@s{1}% + \fi + \fi + \ifop@error\else + \op@unsplit{q}{#3}% + \op@unsplit{r}{#4}% + \fi + \fi + \endgroup +} +\def\op@idivnostar{\@ifnextchar[{\op@idivarg}{\op@idivarg[nil]}} +\def\op@idivarg[#1]#2#3{% + \begingroup + \opset{#1}% + \op@periodfalse + \let\op@shiftdecimalsep\op@string@both + \op@split{#2}{a}% + \op@split{#3}{b}% + \ifop@error + \op@errorwrite + \else + \ifx\op@style\op@string@display + \op@unzero{a}% + \op@unzero{b}% + \edef\op@shift{\op@max{\OP@a@d}{\OP@b@d}}% + \op@mulpowerten{a}{\op@shift}% + \op@mulpowerten{b}{\op@shift}% + \fi + \xdef\OP@a@s{0}% + \xdef\OP@b@s{0}% + \op@div{2}{a}{b}{q}{r}% + \op@split{#2}{a}% + \op@split{#3}{b}% + \op@unzero{a}% + \op@unzero{b}% + \ifx\op@style\op@string@display + \op@copy{q}{qq}% + \edef\op@shift{\op@max{\OP@a@d}{\OP@b@d}}% + \ifx\op@strikedecimalsepsymbol\empty\else + \count@z=\OP@a@w + \count@i=\OP@b@w + \fi + \op@mulpowerten{a}{\op@shift}% + \op@mulpowerten{b}{\op@shift}% + \ifx\op@strikedecimalsepsymbol\empty\else + \advance\count@z by-\OP@a@d + \op@format{\the\count@z}{\OP@a@d}{a}% + \advance\count@i by-\OP@b@d + \op@format{\the\count@i}{\OP@b@d}{b}% + \fi + \ifx\op@country\op@string@french + \op@divdisplayone + \else \ifx\op@country\op@string@american + \op@divdisplayone + \else \ifx\op@country\op@string@russian + \op@divdisplayone + \else + \op@error{Country \op@country\space isn't recognize} + {For now, only `french', `american' and + `russian' are valid}% + \fi\fi\fi + \else + \ifnum\OP@a@s=0\relax + \ifnum\OP@b@s=0\relax + \else + \xdef\OP@q@s{1}% + \fi + \else + \op@add{q}{one}{q}% + \op@sub{b}{r}{r} + \ifnum\OP@b@s=0\relax + \xdef\OP@q@s{1}% + \else + \fi + \fi + \mathsurround=\z@\relax + \ifop@deletezero + \op@unzero{a}% + \op@unzero{b}% + \op@unzero{q}% + \fi + \op@unsplit{a}{@a}% + \op@unsplit{b}{@b}% + \op@unsplit{q}{@q}% + \op@unsplit{r}{@r}% + \ifnum\OP@a@s=1\relax + \ifx\op@parenthesisnegative\op@string@all + $(\Op@@a)$% + \else + $\Op@@a$% + \fi + \else + $\Op@@a$% + \fi + $\;$\nobreak\op@equalsymbol$\;$\penalty\relpenalty + \ifnum\OP@b@s=1\relax + \ifx\op@parenthesisnegative\op@string@all + $(\Op@@b)$% + \else \ifx\op@parenthesisnegative\op@string@last + $\Op@@b$% + \else + $\Op@@b$% + \fi\fi + \else + $\Op@@b$% + \fi + $\>$\nobreak\op@mulsymbol$\>$\penalty\binoppenalty + \ifnum\OP@q@s=1\relax + \ifx\op@parenthesisnegative\op@string@all + $(\Op@@q)$% + \else \ifx\op@parenthesisnegative\op@string@last + $(\Op@@q)$% + \else + $\Op@@q$% + \fi\fi + \else + $\Op@@q$% + \fi + \op@cmp{zero}{r}% + \ifopeq\else + $\>$\nobreak\op@addsymbol$\>$\penalty\binoppenalty + \ifnum\OP@q@s=1\relax + \ifx\op@parenthesisnegative\op@string@all + $(\Op@@r)$% + \else \ifx\op@parenthesisnegative\op@string@last + $(\Op@@r)$% + \else + $\Op@@r$% + \fi\fi + \else + $\Op@@r$% + \fi + \fi + \fi + \fi + \endgroup +} +\def\op@divdisplayone{% + \begingroup + \count@z=\z@\relax + \count@i=\OP@a@w + \loop + \ifnum\@nameuse{OP@a@\the\count@i}=0 + \advance\count@i by-1 + \advance\count@z by1 + \repeat + \count@i=\op@firstlength + \advance\count@i by\count@z + \xdef\op@firstlength{\the\count@i}% + \setbox2=\vbox{% + \count@i=\op@firstlength + \advance\count@i by1 + \hbox{% + \ifx\op@displayintermediary\op@string@none\else + \kern\opcolumnwidth + \advance\count@i by1 + \fi + \ifop@dividendbridge + \vrule width0pt depth0pt height\oplineheight + \opvline(0,1){0.4}% + \ophline(0,1){\op@firstlength}% + \opvline(\op@firstlength,1){0.4}% + \fi + \op@display{operandstyle.1}{a}% + \ifnum\op@shift=0\relax\else + \count@v=\op@shift + \advance\count@v by\OP@a@d + \oplput(-\the\count@v,0){\op@strikedecimalsepsymbol}% + \fi + }% + \count@z=\OP@q@w + \count@ii=1\relax + \ifx\op@displayintermediary\op@string@none + \advance\count@i by-1\relax + \else + \count@iv=\@nameuse{OP@q@\the\count@z}\relax + \count@iii=\count@i + \advance\count@iii by-\@nameuse{OP@T\the\count@iv @w}% + \hbox{% + \ifx\op@voperator\op@string@center + \oplput(0,0.5){\op@subsymbol}% + \else\ifx\op@voperator\op@string@top + \oplput(0,1){\op@subsymbol}% + \else + \oplput(0,0){\op@subsymbol}% + \fi\fi + \ophline(1,-0.25){\op@firstlength}% + \advance\count@ii by1 + \kern\count@iii\opcolumnwidth + \op@display{intermediarystyle.1}% + {T\the\count@iv}% + }% + \fi + {\global\setbox4=\hbox{}\setbox4=\box4}% + \loop + \advance\count@z by-1 + \advance\count@i by1\relax + \ifnum\count@z>0\relax + \count@iv=\@nameuse{OP@q@\the\count@z}\relax + \ifnum\count@iv=0 + \ifx\op@displayintermediary\op@string@all + \count@v=\count@i + \advance\count@v by-\@nameuse{OP@R\the\count@ii @w}% + \hbox{% + \kern\count@v\opcolumnwidth + \op@display{remainderstyle.\the\count@ii}% + {R\the\count@ii}% + }% + \count@iii=\count@i + \advance\count@iii by-\@nameuse{OP@T\the\count@iv @w}% + \hbox{% + \kern\count@v\opcolumnwidth + \ifx\op@voperator\op@string@center + \oplput(-1,0.5){\op@subsymbol}% + \else\ifx\op@voperator\op@string@top + \oplput(-1,1){\op@subsymbol}% + \else + \oplput(-1,0){\op@subsymbol}% + \fi\fi + \ophline(0,-0.25){\@nameuse{OP@R\the\count@ii @w}}% + \kern-\count@v\opcolumnwidth + \kern\count@iii\opcolumnwidth + \op@display{intermediarystyle.\the\count@ii}% + {T\the\count@iv}% + }% + \else + \ifnum\@nameuse{OP@R\the\count@ii @w}=2 + \ifnum\@nameuse{OP@R\the\count@ii @2}=0 + \op@makebox{1}{0}{remainderstyle.\the\count@ii.1}{zero}% + \setbox4=\hbox to\opcolumnwidth{\hss\box0\hss}% + \fi + \fi + \fi + \advance\count@ii by1\relax + \else + \count@v=\count@i + \advance\count@v by-\@nameuse{OP@R\the\count@ii @w}% + \ifvoid4\relax\else + \advance\count@v by-1 + \fi + \hbox{% + \kern\count@v\opcolumnwidth\copy4 + \op@display{remainderstyle.\the\count@ii}% + {R\the\count@ii}% + }% + \advance\count@ii by1\relax + \ifx\op@displayintermediary\op@string@none + \else + \count@iii=\count@i + \advance\count@iii by-\@nameuse{OP@T\the\count@iv @w}% + \hbox{% + \kern\count@v\opcolumnwidth + \ifx\op@voperator\op@string@center + \oplput(-1,0.5){\op@subsymbol}% + \else\ifx\op@voperator\op@string@top + \oplput(-1,1){\op@subsymbol}% + \else + \oplput(-1,0){\op@subsymbol}% + \fi\fi + \advance\count@ii by-1 + \ifvoid4\relax + \ophline(0,-0.25){\@nameuse{OP@R\the\count@ii @w}}% + \else + \ophline(0,-0.25){\@nameuse{OP@T\the\count@iv @w}}% + \ophline(\@nameuse{OP@T\the\count@iv @w},-0.25){1}% + {\setbox4=\box4}% + \fi + \advance\count@ii by1 + \kern-\count@v\opcolumnwidth + \kern\count@iii\opcolumnwidth + \op@display{intermediarystyle.\the\count@ii}% + {T\the\count@iv}% + }% + \fi + \fi + \repeat + \advance\count@i by-1 + \count@iii=\count@i + \advance\count@iii by-\@nameuse{OP@R\the\count@ii @w}% + \hbox{% + \kern\count@iii\opcolumnwidth + \op@display{remainderstyle.\the\count@ii}% + {R\the\count@ii}% + }% + }% + \setbox3=\vbox{% + \count@v=\op@max{\OP@qq@w}{\OP@b@w} + \hbox{\ophline(-0.5,-0.25){\the\count@v.5}% + \op@display{operandstyle.2}{b}% + \ifnum\op@shift=0\relax\else + \count@v=\op@shift + \advance\count@v by\OP@b@d + \oplput(-\the\count@v,0){\op@strikedecimalsepsymbol}% + \fi} + \hbox{\op@display{resultstyle}{qq}} + }% + \dimen0=\ht2 + \ifdim\dimen0>\ht3 + \ht3=\ht2 + \else + \ht2=\ht3 + \fi + \ifx\op@voperation\op@string@top + \dimen0=\ht2 + \advance\dimen0 by-0.5\oplineheight + \ht2=0.75\oplineheight + \ht3=0.75\oplineheight + \dp2=\dimen0 + \dp2=\dimen0 + \fi + \setbox1=\hbox{% + \box2 + \kern0.5\opcolumnwidth + \kern-0.5\op@hrulewidth + \ifx\voperation\op@string@top + \vrule width\op@hrulewidth + \else + \vrule width\op@hrulewidth + \fi + \kern0.5\opcolumnwidth + \kern-0.5\op@hrulewidth + \box3 + }% + \ifx\op@voperation\op@string@center + \setbox1=\hbox{$\vcenter{\box1}$}% + \fi + \leavevmode\box1 + \endgroup +} +\def\op@div#1#2#3#4#5{% + \begingroup + \def\op@divmode{#1}% + \op@copy{#2}{da}% + \op@copy{#3}{db}% + \count@iv=0 + \count@iii=\op@max{\OP@da@d}{\OP@db@d}\relax + \op@powten{da}{\the\count@iii}% + \op@powten{db}{\the\count@iii}% + \ifnum\op@divmode=1 + \op@cmp{da}{maxinteger}% + \ifopgt + \op@warning{I can't deal period with such great dividend + (max = 2147483647).^^J + Use of maxdivstep instead period.}% + \def\op@divmode{0}% + \else \op@cmp{db}{maxdivperiod}% + \ifopgt + \op@warning{I can't deal period with such great divisor + (max = 214748363).^^J + Use of maxdivstep instead period.}% + \def\op@divmode{0}% + \else + \op@unsplit{da}{@a}% + \op@unsplit{db}{@b}% + \op@divperiod{\Op@@a}{\Op@@b}{op@lengthperiod}% + \ifnum\op@lengthperiod>\op@safedivstep + \op@warning{Period of division is too big + (\op@lengthperiod\space > safedivstep).^^J + \space\space\space Division will stop + before reach it.}% + \fi + \fi\fi + \fi + \op@multable{db}% + \op@cmp{da}{db}% + \ifople + \op@copy{da}{R}% + \count@i=\OP@da@w + \else + \xdef\OP@R@d{0}% + \xdef\OP@R@s{0}% + \count@i=\@nameuse{OP@db@w}% + \op@leftdividend{\the\count@i}% + \op@cmp{R}{db}% + \ifoplt + \ifnum\OP@da@w>\count@i + \advance\count@i by1 + \op@leftdividend{\the\count@i}% + \fi + \fi + \fi + \xdef\op@firstlength{\the\count@i}% + \count@i=-\count@i + \advance\count@i by\OP@da@w + \op@copy{R}{R0}% + \op@copy{zero}{dq}% + \count@ii=0 + \op@againtrue + \loop + \ifop@again + \op@tableextract{R}% + \op@multen{dq}% + \@namexdef{OP@dq@1}{\op@k}% + \op@sub{R}{T\op@k}{dr}% + \op@unzero{T\op@k}% + \op@multen{dr}% + \ifnum\count@i>0 + \@namexdef{OP@dr@1}{\@nameuse{OP@da@\the\count@i}}% + \fi + \advance\count@i by-1\relax + \op@unzero{dr}% + \ifnum\OP@dr@w=1 + \xdef\OP@dr@w{2}% + \xdef\OP@dr@i{2}% + \@namexdef{OP@dr@2}{0}% + \fi + \advance\count@ii by1\relax + \op@copy{dr}{R\the\count@ii}% + \op@copy{dr}{R}% + \ifcase\op@divmode\relax + \ifnum\count@ii<\op@maxdivstep\relax\else + \op@againfalse + \fi + \ifnum\count@i<0\relax% + \op@cmp{zero}{R}% + \ifopeq + \op@againfalse + \fi + \fi + \or + \ifnum\count@ii<\op@safedivstep\relax\else + \op@againfalse + \fi + \ifnum\count@i<-\op@lengthperiod\relax + \count@iv=\count@ii + \advance\count@iv by-\op@lengthperiod + \op@cmp{R\the\count@iv}{R\the\count@ii}% + \ifopeq + \op@againfalse + \fi + \fi + \or + \ifnum\count@i=-1 + \op@againfalse + \fi + \fi + \repeat + \op@copy{zero}{T0}% + \advance\count@i by1\relax + \ifnum\count@i<0 + \xdef\OP@dq@d{-\the\count@i}% + \count@z=\OP@dq@w + \advance\count@z by\count@i + \xdef\OP@dq@i{\the\count@z}% + \fi + \op@unzero{dq}% + \op@copy{dq}{#4}% + \op@unzero{dr}% + \op@copy{dr}{R}% + \op@rshift{1}{dr}% + \op@copy{dr}{R\the\count@ii}% + \count@i=\count@iii + \advance\count@i by1 + \advance\count@i by\OP@dq@d\relax + \count@ii=\count@i + \advance\count@ii by\OP@R@w + \op@format{\the\count@ii}{0}{R}% + \count@z=\OP@R@w + \advance\count@z by-\count@i + \xdef\OP@R@i{\the\count@z}% + \xdef\OP@R@d{\the\count@i}% + \op@unzero{R}% + \op@copy{R}{#5}% + \endgroup +} +\def\op@powten#1#2{% + \begingroup + \count@z=#2\relax + \advance\count@z by-\@nameuse{OP@#1@d}% + \@namexdef{OP@#1@d}{0}% + \count@i=\@nameuse{OP@#1@w}% + \advance\count@i by\count@z + \@namexdef{OP@#1@w}{\the\count@i}% + \@namexdef{OP@#1@i}{\the\count@i}% + \count@ii=\count@i + \advance\count@ii by-\count@z + \loop + \ifnum\count@ii>0 + \@namexdef{OP@#1@\the\count@i}{\@nameuse{OP@#1@\the\count@ii}}% + \advance\count@i by-1 + \advance\count@ii by-1 + \repeat + \loop + \ifnum\count@i>0 + \@namexdef{OP@#1@\the\count@i}{0}% + \advance\count@i by-1 + \repeat + \endgroup +} +\def\opdivperiod#1#2#3{% + \op@split{#1}{a}% + \op@split{#2}{b}% + \ifop@error\else + \op@unzero{a}% + \edef\OP@a@i{\OP@a@w}% + \def\OP@a@d{0}% + \def\OP@a@s{0}% + \op@unzero{b}% + \edef\OP@b@i{\OP@b@w}% + \def\OP@b@d{0}% + \def\OP@b@s{0}% + \op@cmp{a}{zero}% + \ifopeq + \op@unsplit{one}{#3}% + \else + \op@cmp{b}{zero}% + \ifopeq + \op@error{divisor must be nonzero}% + {You have to learn some math}% + \else + \op@cmp{a}{maxdivperiod}% + \ifopgt + \op@error{Arguments of \string\opdivperiod\space + must be less than 214748363}% + {Sorry}% + \else + \op@cmp{b}{maxdivperiod}% + \ifopgt + \op@error{Arguments of \string\opdivperiod\space + must be less than 214748363}% + {Sorry}% + \else + \op@unsplit{a}{@a}% + \op@unsplit{b}{@b}% + \op@divperiod{\Op@@a}{\Op@@b}{Op@@r}% + \opcopy{@r}{#3}% + \fi + \fi + \fi + \fi + \fi + \ifop@error\op@errorwrite\fi +} +\def\op@divperiod#1#2#3{% + \begingroup + \count@i=#1\relax + \count@ii=#2\relax + \ifnum\count@ii=0\relax + \@namexdef{#3}{1}% + \else + \op@gcd{\the\count@i}{\the\count@ii}{op@tmp}% + \count@iii=\op@tmp + \divide\count@ii by\count@iii + \op@twofiveQ{\the\count@ii}{op@tmp}% + \op@order{\op@tmp}{op@tmp}% + \@namexdef{#3}{\op@tmp}% + \fi + \endgroup +} +\def\opgcd#1#2#3{% + \op@split{#1}{a}% + \op@split{#2}{b}% + \ifop@error\else + \def\OP@a@s{0}% + \def\OP@b@s{0}% + \op@cmp{a}{zero}% + \ifopeq + \op@error{Arguments of \string\opgcd\space must be nonzero}% + {You have to learn some math}% + \else + \op@cmp{b}{zero}% + \ifopeq + \op@error{Arguments of \string\opgcd\space must be nonzero}% + {You have to learn some math}% + \else\ifnum\OP@a@d>0 + \op@error{Arguments of \string\opgcd\space must be integer}% + {You have to learn some math}% + \else\ifnum\OP@b@d>0 + \op@error{Arguments of \string\opgcd\space must be integer}% + {You have to learn some math}% + \else + \op@cmp{a}{maxinteger}% + \ifopgt + \op@error{Arguments of \string\opgcd\space must be less than + 2147483647}% + {Sorry}% + \else + \op@cmp{b}{maxinteger}% + \ifopgt + \op@error{Arguments of \string\opgcd\space must be less than + 2147483647}% + {Sorry}% + \else + \op@unsplit{a}{@a}% + \op@unsplit{b}{@b}% + \op@gcd{\Op@@a}{\Op@@b}{Op@@r}% + \opcopy{@r}{#3}% + \fi\fi\fi\fi\fi\fi + \fi + \ifop@error\op@errorwrite\fi +} +\def\op@gcd#1#2#3{% + \begingroup + \count@i=#1\relax + \count@ii=#2\relax + \loop + \count@iii=\count@i + \divide\count@iii by\count@ii + \multiply\count@iii by\count@ii + \advance\count@i by-\count@iii + \count@iii=\count@i\relax + \count@i=\count@ii\relax + \count@ii=\count@iii + \ifnum\count@ii>0 + \repeat + \@namexdef{#3}{\the\count@i}% + \endgroup +} +\def\op@twofiveQ#1#2{% + \begingroup + \count@i=#1\relax + \loop + \count@ii=\count@i + \divide\count@ii by2 + \multiply\count@ii by2 + \ifnum\count@ii=\count@i + \divide\count@i by2 + \repeat + \loop + \count@ii=\count@i + \divide\count@ii by5 + \multiply\count@ii by5 + \ifnum\count@ii=\count@i + \divide\count@i by5 + \repeat + \@namexdef{#2}{\the\count@i}% + \endgroup +} +\def\op@order#1#2{% + \begingroup + \count@i=1\relax + \count@ii=0 + \loop + \multiply\count@i by10 + \count@iii=\count@i + \divide\count@iii by#1\relax + \multiply\count@iii by#1\relax + \advance\count@i by-\count@iii + \advance\count@ii by1 + \ifnum\count@i>1 + \repeat + \@namexdef{#2}{\the\count@ii} + \endgroup +} +\def\op@leftdividend#1{% + \begingroup + \count@z=#1\relax + \count@i=\OP@da@w + \xdef\OP@R@w{\the\count@z}% + \xdef\OP@R@i{\the\count@z}% + \loop + \@namexdef{OP@R@\the\count@z}{\@nameuse{OP@da@\the\count@i}}% + \advance\count@i by-1 + \advance\count@z by-1 + \ifnum\count@z>0 + \repeat + \endgroup +} +\def\op@multen#1{% + \begingroup + \count@z=\@nameuse{OP@#1@w}\relax + \count@i=\count@z + \advance\count@i by1 + \@namexdef{OP@#1@w}{\the\count@i}% + \@namexdef{OP@#1@i}{\the\count@i}% + \loop + \ifnum\count@z>0 + \@namexdef{OP@#1@\the\count@i}{\@nameuse{OP@#1@\the\count@z}}% + \advance\count@z by-1 + \advance\count@i by-1 + \repeat + \@namexdef{OP@#1@1}{0}% + \endgroup +} +\def\op@mulpowerten#1#2{% + \begingroup + \ifnum\@nameuse{OP@#1@d}<#2\relax + \count@z=#2\relax + \advance\count@z by-\@nameuse{OP@#1@d}\relax + \count@ii=\@nameuse{OP@#1@w}% + \count@i=\@nameuse{OP@#1@w}% + \advance\count@i by\count@z + \@namexdef{OP@#1@w}{\the\count@i}% + \@namexdef{OP@#1@i}{\the\count@i}% + \@namexdef{OP@#1@d}{0}% + \loop + \ifnum\count@ii>0 + \@namexdef{OP@#1@\the\count@i}{\@nameuse{OP@#1@\the\count@ii}}% + \advance\count@i by-1 + \advance\count@ii by-1 + \repeat + \loop + \ifnum\count@z>0 + \@namexdef{OP@#1@\the\count@z}{0}% + \advance\count@z by-1\relax + \repeat + \else + \count@z=\@nameuse{OP@#1@d}\relax + \advance\count@z by-#2\relax + \@namexdef{OP@#1@d}{\the\count@z}% + \count@z=\@nameuse{OP@#1@i}\relax + \advance\count@z by#2\relax + \@namexdef{OP@#1@i}{\the\count@z}% + \fi + \op@unzero{#1}% + \endgroup +} +\def\op@divpowerten#1#2{% + \begingroup + \ifnum\@nameuse{OP@#1@i}>#2\relax + \count@z=\@nameuse{OP@#1@d}\relax + \advance\count@z by#2\relax + \@namexdef{OP@#1@d}{\the\count@z}% + \count@z=\@nameuse{OP@#1@i}\relax + \advance\count@z by-#2\relax + \@namexdef{OP@#1@i}{\the\count@z}% + \else + \count@z=\@nameuse{OP@#1@d}\relax + \advance\count@z by#2\relax + \@namexdef{OP@#1@d}{\the\count@z}% + \@namexdef{OP@#1@i}{1}% + \advance\count@z by1\relax + \count@i=\@nameuse{OP@#1@w}% + \@namexdef{OP@#1@w}{\the\count@z}% + \advance\count@z by1 + \loop + \ifnum\count@i<\count@z + \advance\count@i by1 + \@namexdef{OP@#1@\the\count@i}{0}% + \repeat + \fi + \op@unzero{#1}% + \endgroup +} +\def\op@tableextract#1{% + \op@cmp{#1}{T5}% + \ifopge \op@cmp{#1}{T7}% + \ifopge \op@cmp{#1}{T8}% + \ifopge \op@cmp{#1}{T9}% + \ifopge \gdef\op@k{9}% + \else \gdef\op@k{8}% + \fi + \else \gdef\op@k{7}% + \fi + \else \op@cmp{#1}{T6}% + \ifopge \gdef\op@k{6}% + \else \gdef\op@k{5}% + \fi + \fi + \else \op@cmp{#1}{T2}% + \ifopge \op@cmp{#1}{T3}% + \ifopge \op@cmp{#1}{T4}% + \ifopge \gdef\op@k{4}% + \else \gdef\op@k{3}% + \fi + \else \gdef\op@k{2}% + \fi + \else \op@cmp{#1}{T1}% + \ifopge \gdef\op@k{1}% + \else \gdef\op@k{0}% + \fi + \fi + \fi +} +\def\opwidth#1#2{% + \op@split{#1}{a}% + \ifop@error + \op@errorwrite + \else + \@namexdef{Op@#2}{\OP@a@w}% + \fi +} +\def\opintegerwidth#1#2{% + \op@split{#1}{a}% + \ifop@error + \op@errorwrite + \else + \@namexdef{Op@#2}{\OP@a@i}% + \fi +} +\def\opdecimalwidth#1#2{% + \op@split{#1}{a}% + \ifop@error + \op@errorwrite + \else + \@namexdef{Op@#2}{\OP@a@d}% + \fi +} +\def\opinteger#1#2{% + \op@split{#1}{a}% + \ifop@error + \op@errorwrite + \else + \op@integer{a}{b}% + \op@unsplit{b}{#2}% + \fi +} +\def\op@integer#1#2{% + \begingroup + \op@unzero{#1}% + \count@z=\@nameuse{OP@#1@d}\relax + \ifnum\count@z>0\relax + \count@i=0 + \loop + \ifnum\count@z<\@nameuse{OP@#1@w}% + \advance\count@z by1\relax + \advance\count@i by1\relax + \@namexdef{OP@#2@\the\count@i}{\@nameuse{OP@#1@\the\count@z}}% + \repeat + \@namexdef{OP@#2@w}{\the\count@i}% + \@namexdef{OP@#2@i}{\the\count@i}% + \@namexdef{OP@#2@d}{0}% + \else + \op@copy{#1}{#2}% + \fi + \@namexdef{OP@#2@s}{0}% + \endgroup +} +\def\opdecimal#1#2{% + \op@split{#1}{a}% + \ifop@error + \op@errorwrite + \else + \op@decimal{a}{b}% + \op@unsplit{b}{#2}% + \fi +} +\def\op@decimal#1#2{% + \op@unzero{#1}% + \ifop@error + \op@errorwrite + \else + \ifnum\@nameuse{OP@#1@d}=0\relax + \op@copy{zero}{#2}% + \else + \op@copy{#1}{#2}% + \@namexdef{OP@#2@i}{\@nameuse{OP@#1@d}}% + \@namexdef{OP@#2@w}{\@nameuse{OP@#1@d}}% + \@namexdef{OP@#2@d}{0}% + \@namexdef{OP@#2@s}{0}% + \fi + \fi +} +\def\opgetdigit#1#2#3{% + \op@split{#1}{a}% + \ifop@error + \op@errorwrite + \else + \ifnum\@nameuse{OP@a@w}>#2\relax + \@namexdef{Op@#3}{\@nameuse{OP@a@#2}}% + \else + \@namexdef{Op@#3}{0}% + \fi + \fi +} +\def\opsetdigit#1#2#3{% + \begingroup + \op@split{#1}{a}% + \op@split{#3}{b}% + \ifop@error + \op@errorwrite + \else + \op@unsplit{b}{@b}% + \@namexdef{OP@a@#2}{\Op@@b}% + \ifnum\OP@a@w<#2\relax + \count@z=\OP@a@w\relax + \advance\count@z by1\relax + \loop + \ifnum\count@z<#2\relax + \@namexdef{OP@a@\the\count@z}{0}% + \advance\count@z by1 + \repeat + \xdef\OP@a@w{#2}% + \count@z=#2\relax + \advance\count@z by-\OP@a@d + \xdef\OP@a@i{\the\count@z}% + \fi + \op@unsplit{a}{#1}% + \fi + \endgroup +} +\def\opgetintegerdigit#1#2#3{% + \begingroup + \op@split{#1}{a}% + \ifop@error + \op@errorwrite + \else + \count@z=\OP@a@d + \advance\count@z by#2\relax + \ifnum\OP@a@w>\count@z\relax + \@namexdef{Op@#3}{\@nameuse{OP@a@\the\count@z}}% + \else + \@namexdef{Op@#3}{0}% + \fi + \fi + \endgroup +} +\def\opsetintegerdigit#1#2#3{% + \begingroup + \op@split{#1}{a}% + \op@split{#3}{b}% + \ifop@error + \op@errorwrite + \else + \op@unsplit{b}{@b}% + \count@z=\OP@a@d + \advance\count@z by#2\relax + \@namexdef{OP@a@\the\count@z}{\Op@@b}% + \ifnum\OP@a@w>\count@z\relax\else + \count@i=\OP@a@w + \xdef\OP@a@w{\the\count@z}% + \advance\count@i by1 + \loop + \ifnum\count@i<\count@z + \@namexdef{OP@a@\the\count@i}{0}% + \advance\count@i by1 + \repeat + \advance\count@z by-\OP@a@d + \xdef\OP@a@i{\the\count@z}% + \fi + \op@unsplit{a}{#1}% + \fi + \endgroup +} +\def\opgetdecimaldigit#1#2#3{% + \begingroup + \op@split{#1}{a}% + \ifop@error + \op@errorwrite + \else + \ifnum\OP@a@d<#2\relax + \@namexdef{Op@#3}{0}% + \else + \count@z=\OP@a@d + \advance\count@z by-#2\relax + \advance\count@z by1 + \@namexdef{Op@#3}{\@nameuse{OP@a@\the\count@z}}% + \fi + \fi + \endgroup +} +\def\opsetdecimaldigit#1#2#3{% + \begingroup + \op@split{#1}{a}% + \op@split{#3}{b}% + \ifop@error + \op@errorwrite + \else + \op@unsplit{b}{@b}% + \ifnum\OP@a@d<\Op@@b\relax + \count@z=\Op@@b + \advance\count@z by-\OP@a@d + \advance\count@z by1\relax + \count@i=\OP@a@w + \advance\count@i by\count@z\relax + \count@z=\OP@a@w + \xdef\OP@a@w{\the\count@i}% + \xdef\OP@a@d{\Op@@b}% + \loop + \ifnum\count@z>0 + \@namexdef{OP@a@\the\count@i}{\@nameuse{OP@a@\the\count@z}}% + \advance\count@z by-1 + \advance\count@i by-1 + \repeat + \loop + \ifnum\count@i>1 + \@namexdef{OP@a@\the\count@i}{0}% + \advance\count@i by-1 + \repeat + \@namexdef{OP@a@1}{\Op@@b}% + \else + \count@z=\OP@a@d + \advance\count@z by-#2\relax + \advance\count@z by1 + \@namexdef{OP@a@\the\count@z}{\Op@@b}% + \fi + \op@unsplit{a}{#1}% + \fi + \endgroup +} +\def\opcastingoutnines#1#2{% + \begingroup + \op@split{#1}{a}% + \ifop@error + \op@errorwrite + \else + \count@z=\OP@a@w\relax + \count@i=0\relax + \loop + \ifnum\count@z>0 + \advance\count@i by\@nameuse{OP@a@\the\count@z}\relax + \ifnum\count@i>8 + \advance\count@i by-9 + \fi + \advance\count@z by-1 + \repeat + \opcopy{\the\count@i}{#2}% + \fi + \endgroup +} +\def\opcastingoutelevens#1#2{% + \begingroup + \op@split{#1}{a}% + \ifop@error + \op@errorwrite + \else + \count@ii=\OP@a@w + \advance\count@ii by1\relax + \count@i=0\relax + \count@z=-1\relax + \loop + \advance\count@z by2\relax + \ifnum\count@z<\count@ii + \advance\count@i by\@nameuse{OP@a@\the\count@z}\relax + \ifnum\count@i>10 + \advance\count@i by-11 + \fi + \repeat + \count@z=0\relax + \loop + \advance\count@z by2\relax + \ifnum\count@z<\count@ii + \advance\count@i by-\@nameuse{OP@a@\the\count@z}\relax + \ifnum\count@i<0 + \advance\count@i by11 + \fi + \repeat + \opcopy{\the\count@i}{#2}% + \fi + \endgroup +} +\def\opneg#1#2{% + \op@split{#1}{a}% + \ifop@error + \op@errorwrite + \else + \op@neg{a}{b}% + \op@unsplit{b}{#2}% + \fi +} +\def\op@neg#1#2{% + \begingroup + \op@copy{#1}{#2}% + \op@againfalse + \ifnum\@nameuse{OP@#2@d}>0 + \op@againtrue + \else\ifnum\@nameuse{OP@#2@i}>1 + \op@againtrue + \else\ifnum\@nameuse{OP@#2@1}>0 + \op@againtrue + \fi\fi\fi + \ifop@again + \count@z=1 + \advance\count@z by-\@nameuse{OP@#2@s}\relax + \@namexdef{OP@#2@s}{\the\count@z}% + \fi + \endgroup +} +\def\opabs#1#2{% + \op@split{#1}{a}% + \ifop@error + \op@errorwrite + \else + \xdef\OP@a@s{0}% + \op@unsplit{a}{#2}% + \fi +} +\def\oppower#1#2#3{% + \begingroup + \op@split{#1}{a}% + \op@split{#2}{b}% + \ifop@error\else + \op@unsplit{a}{@a}% + \op@unsplit{b}{@b}% + \ifnum\OP@b@d>0 + \op@error{Exponent must be an integer}% + {You can't use \string\oppower\space with non integer + exponent}% + \else + \op@cmp{a}{zero}% + \ifopeq + \op@cmp{b}{zero}% + \ifopeq + \opcopy{1}{#3}% + \else\ifopgt + \opcopy{0}{#3}% + \else + \op@error{Power of zero with negative exponent is an + error}% + {Remember that negative exponent involve inverse}% + \fi\fi + \else + \op@cmp{b}{zero}% + \ifoplt + \xdef\OP@b@s{0}% + \op@unsplit{b}{@b}% + \opdiv*{1}{@a}{@a}% + \fi + \op@cmp{b}{maxpower}% + \ifopgt + \op@error{Exponent is too big (>1073741824)}% + {Sorry}% + \else + \count@z=0 + \@namexdef{Op@@e0}{1}% + \xdef\Op@@tmp{1}% + \@namexdef{Op@@p0}{\Op@@a}% + \@namexdef{Op@@ptmp}{\@nameuse{Op@@p0}}% + \loop + \ifnum\@nameuse{Op@@e\the\count@z}<\Op@@b + \opadd*{@tmp}{@tmp}{@@tmp}% + \opmul*{@ptmp}{@ptmp}{@@ptmp}% + \advance\count@z by1 + \xdef\Op@@tmp{\Op@@@tmp}% + \xdef\Op@@ptmp{\Op@@@ptmp}% + \@namexdef{Op@@e\the\count@z}{\Op@@@tmp}% + \@namexdef{Op@@p\the\count@z}{\Op@@@ptmp}% + \repeat + \opcopy{1}{@r}% + \loop + \ifnum\Op@@b>0\relax + \ifnum\Op@@b<\@nameuse{Op@@e\the\count@z}\relax + \else + \opmul*{@r}{@p\the\count@z}{@r}% + \opsub*{@b}{@e\the\count@z}{@b}% + \fi + \advance\count@z by-1 + \repeat + \opcopy{@r}{#3}% + \fi + \fi + \fi + \fi + \ifop@error\op@errorwrite\fi + \endgroup +} +\def\opfloor#1#2#3{% + \op@split{#1}{fa}% + \op@split{#2}{fb}% + \ifop@error + \op@errorwrite + \else + \ifnum\OP@fa@s=1 + \xdef\OP@fa@s{0}% + \op@ceil{fa}{fb}% + \xdef\OP@fa@s{1}% + \else + \op@floor{fa}{fb}% + \fi + \op@unsplit{fa}{#3}% + \fi +} +\def\opround#1#2#3{% + \op@split{#1}{ra}% + \op@split{#2}{rb}% + \ifop@error + \op@errorwrite + \else + \op@unsplit{ra}{@ra}% + \op@unsplit{rb}{@rb}% + \ifnum\Op@@rb<0\relax + \opneg{@rb}{@rb}% + \ifnum\Op@@rb<\@nameuse{OP@ra@i}\relax + \else + \count@z=\@nameuse{OP@ra@i}% + \advance\count@z by-1 + \xdef\Op@@rb{\the\count@z}% + \fi + \opneg{@rb}{@rb}% + \fi + \oppower{0.1}{@rb}{@rr}% + \opmul*{0.5}{@rr}{@rr}% + \ifnum\OP@ra@s=0\relax + \opadd*{@ra}{@rr}{@ra}% + \opfloor{@ra}{#2}{#3}% + \else + \opneg{@ra}{@ra}% + \opadd*{@ra}{@rr}{@ra}% + \opfloor{@ra}{#2}{@ra}% + \opneg{@ra}{#3}% + \fi + \fi +} +\def\opceil#1#2#3{% + \op@split{#1}{ca}% + \op@split{#2}{cb}% + \ifop@error + \op@errorwrite + \else + \ifnum\OP@ca@s=1 + \xdef\OP@ca@s{0}% + \op@floor{ca}{cb}% + \xdef\OP@ca@s{1}% + \else + \op@ceil{ca}{cb}% + \fi + \op@unsplit{ca}{#3}% + \fi +} +\def\op@floor#1#2{% + \begingroup + \op@unsplit{#2}{@fb}% + \op@unzero{#1}% + \count@z=\Op@@fb\relax + \ifnum\count@z<0 + \count@z=-\count@z + \ifnum\count@z<\@nameuse{OP@#1@i}\relax\else + \count@z=\@nameuse{OP@#1@i}% + \advance\count@z by-1 + \fi + \op@integer{#1}{#1}% + \loop + \ifnum\count@z>0 + \@namexdef{OP@#1@\the\count@z}{0}% + \advance\count@z by-1\relax + \repeat + \else + \ifnum\count@z>\@nameuse{OP@#1@d}% + \advance\count@z by-\@nameuse{OP@#1@d}% + \count@i=\@nameuse{OP@#1@d}% + \advance\count@i by\count@z + \@namexdef{OP@#1@d}{\the\count@i}% + \count@i=\@nameuse{OP@#1@w}\relax + \count@ii=\count@i + \advance\count@ii by\count@z + \@namexdef{OP@#1@w}{\the\count@ii}% + \loop + \ifnum\count@i>0 + \@namexdef{OP@#1@\the\count@ii}{\@nameuse{OP@#1@\the\count@i}}% + \advance\count@i by-1 + \advance\count@ii by-1 + \repeat + \loop + \ifnum\count@ii>0 + \@namexdef{OP@#1@\the\count@ii}{0}% + \advance\count@ii by-1 + \repeat + \else + \advance\count@z by-\@nameuse{OP@#1@d}\relax + \count@z=-\count@z\relax + \count@i=\@nameuse{OP@#1@w}\relax + \count@ii=\count@i\relax + \advance\count@i by-\count@z + \@namexdef{OP@#1@w}{\the\count@i}\relax + \count@i=\@nameuse{OP@#1@d}\relax + \advance\count@i by-\count@z + \@namexdef{OP@#1@d}{\the\count@i}% + \count@i=0\relax + \loop + \ifnum\count@z<\count@ii + \advance\count@z by1\relax + \advance\count@i by1 + \@namexdef{OP@#1@\the\count@i}{\@nameuse{OP@#1@\the\count@z}}% + \repeat + \fi + \fi + \endgroup +} +\def\op@ceil#1#2{% + \op@unsplit{#1}{@Ca}% + \op@unsplit{#2}{@Cb}% + \op@unzero{#1}% + \count@z=\Op@@Cb\relax + \ifnum\count@z>0\relax + \ifnum\count@z<\@nameuse{OP@#1@d}\relax + \oppower{0.1}{\the\count@z}{@Cr}% + \opadd*{@Ca}{@Cr}{@Ca}% + \op@split{@Ca}{#1}% + \op@split{@Cb}{#2}% + \op@floor{#1}{#2}% + \else + \op@split{@Ca}{#1}% + \op@split{@Cb}{#2}% + \op@floor{#1}{#2}% + \fi + \else + \opneg{@Cb}{@Cb}% + \count@z=-\count@z\relax + \ifnum\count@z<\@nameuse{OP@#1@i}\relax + \oppower{10}{\the\count@z}{@Cr}% + \else + \count@z=\@nameuse{OP@#1@i}% + \advance\count@z by-1 + \oppower{10}{\the\count@z}{@Cr}% + \fi + \opadd*{@Ca}{@Cr}{@Ca}% + \opneg{@Cb}{@Cb}% + \op@split{@Ca}{#1}% + \op@split{@Cb}{#2}% + \op@floor{#1}{#2}% + \fi +} +\edef\opHatCode{\the\catcode`\^} +\catcode`\^=12\relax +\def\opexpr{\@ifnextchar[{\op@exprarg}{\op@exprarg[nil]}} +\def\op@exprarg[#1]{% + \opset{#1}% + \begingroup + \catcode`\^=12 + \catcode`*=12 + \catcode`/=12 + \catcode`:=12 + \catcode`+=12 + \catcode`-=12 + \catcode`.=12 + \catcode`,=12 + \catcode`(=12 + \catcode`)=12 + \catcode`\ =12 + \op@expr +} +\def\op@expr#1{% + \ifop@error + \op@errorwrite + \else + \xdef\op@expression{#1}\endgroup + \ifx\op@expression\empty + \op@error{Empty expression is not valid}% + {I say: "empty expression is not valid"}% + \else + \expandafter\op@scan@line\expandafter{\op@expression}% + \@ifundefined{OP@token\the\op@token}% + {\global\advance\op@token by-1}% + {\relax}% + \global\op@stack=0 + \op@search@term{1}{\the\op@token}% + \fi + \fi + \op@@expr +} +\def\op@@expr#1{% + \ifnum\op@stack=1 + \ifop@error + \op@errorwrite + \else + \opcopy{@s1}{#1}% + \fi + \else + \op@error{Bad expression (not enough operator or operand)}% + {Expression like 2 + 3 3 or 3 * 5 *}% + \op@errorwrite + \fi +} +\def\op@scan@line{% + \begingroup + \global\op@parenthesis=0 + \global\op@token=1 + \global\op@in@numberfalse + \global\op@in@decimalfalse + \global\op@in@namefalse + \global\op@in@signtrue + \catcode`\^=12 + \catcode`*=12 + \catcode`/=12 + \catcode`:=12 + \catcode`+=12 + \catcode`-=12 + \catcode`.=12 + \catcode`,=12 + \catcode`(=12 + \catcode`)=12 + \catcode`\ =12 + \op@scan@@line +} +\def\op@scan@@line#1{\op@scan@@@line#1\@nil\endgroup} +\def\op@scan@@@line#1#2\@nil{% + \op@testch@r{#1}% + \ifop@isdigit + \global\op@in@signfalse + \ifop@in@number + \op@token@append{#1}% + \else\ifop@in@name + \op@token@append{#1}% + \else + \op@in@numbertrue + \op@token@create{#1}% + \fi\fi + \fi + \ifop@isplus + \op@token@single{\op@string@add}% + \global\op@in@signtrue + \fi + \ifop@isminus + \op@token@single{\op@string@sub}% + \global\op@in@signtrue + \fi + \ifop@ismultiply + \op@token@single{\op@string@mul}% + \global\op@in@signtrue + \fi + \ifop@isdivide + \op@token@single{\op@string@div}% + \global\op@in@signtrue + \fi + \ifop@isidivide + \op@token@single{\op@string@idiv}% + \global\op@in@signtrue + \fi + \ifop@ispower + \op@token@single{\op@string@power}% + \global\op@in@signtrue + \fi + \ifop@isdot + \global\op@in@signfalse + \ifop@in@decimal + \op@error{Number width multiple decimal separators}% + {You write something like 12.34.56}% + \else\ifop@in@number + \op@in@decimaltrue + \op@token@append{.}% + \else + \op@token@create{.}% + \op@in@numbertrue + \op@in@decimaltrue + \fi\fi + \fi + \ifop@islparenthesis + \op@token@single{(}% + \global\op@in@signtrue + \fi + \ifop@isrparenthesis + \op@token@single{)}% + \global\op@in@signtrue + \fi + \ifop@iscomma + \op@token@single{,}% + \global\op@in@signtrue + \fi + \ifop@isspace + \ifop@in@number + \op@in@numberfalse + \op@in@decimalfalse + \global\advance\op@token by1 + \else\ifop@in@name + \op@in@namefalse + \global\advance\op@token by1 + \fi\fi + \fi + \ifop@isother + \global\op@in@signfalse + \ifop@in@name + \op@token@append{#1}% + \else\ifop@in@number + \op@in@numberfalse + \op@in@decimalfalse + \op@in@nametrue + \global\advance\op@token by1 + \op@token@create{#1}% + \else + \op@in@nametrue + \op@token@create{#1}% + \fi\fi + \fi + \def\@tempa{#2}% + \ifx\empty\@tempa + \let\next\relax + \else + \let\next\op@scan@@@line + \fi + \expandafter\next\@tempa\@nil +} +\def\op@search@subexpr#1#2{% + \begingroup + \count@i=#1\relax + \count@v=#2\relax + \ifnum\count@i=\count@v + \op@token@use{#1}% + \else + \count@iii=\count@v + \count@iv=\count@i + \advance\count@iv by-1 + \count@ii=0 + \loop + \ifnum\count@iii>\count@iv + \expandafter\ifx\csname OP@token\the\count@iii\endcsname + \op@string@rpar\relax + \advance\op@parenthesis by1 + \fi + \expandafter\ifx\csname OP@token\the\count@iii\endcsname + \op@string@lpar\relax + \advance\op@parenthesis by-1 + \fi + \expandafter\ifx\csname OP@token\the\count@iii\endcsname + \op@string@comma\relax + \ifnum\op@parenthesis=0 + \count@ii=\count@iii\relax + \count@iii=0 + \fi + \fi + \advance\count@iii by-1 + \repeat + \ifnum\count@ii=0\relax + \ifnum\op@parenthesis=0 + \op@search@term{\the\count@i}{\the\count@v}% + \else + \op@error{Unbalanced parenthesis in expression}% + {Error between tokens #1 and #2}% + \fi + \else + \advance\count@ii by-1 + \op@search@subexpr{\the\count@i}{\the\count@ii}% + \advance\count@ii by2 + \op@search@subexpr{\the\count@ii}{\the\count@v}% + \fi + \fi + \endgroup +} +\def\op@search@term#1#2{% + \begingroup + \count@i=#1\relax + \count@v=#2\relax + \ifnum\count@i=\count@v + \op@token@use{#1}% + \else + \count@iii=\count@v + \count@iv=\count@i + \advance\count@iv by-1 + \count@ii=0\relax + \loop + \ifnum\count@iii>\count@iv\relax + \expandafter\ifx\csname OP@token\the\count@iii\endcsname + \op@string@rpar\relax + \advance\op@parenthesis by1 + \fi + \expandafter\ifx\csname OP@token\the\count@iii\endcsname + \op@string@lpar\relax + \advance\op@parenthesis by-1 + \fi + \expandafter\ifx\csname OP@token\the\count@iii\endcsname + \op@string@add\relax + \ifnum\op@parenthesis=0 + \count@ii=\count@iii\relax + \count@iii=0 + \fi + \fi + \expandafter\ifx\csname OP@token\the\count@iii\endcsname + \op@string@sub\relax + \ifnum\op@parenthesis=0 + \count@ii=\count@iii\relax + \count@iii=0 + \fi + \fi + \advance\count@iii by-1 + \repeat + \ifnum\count@ii=0\relax + \ifnum\op@parenthesis=0 + \op@search@factor{\the\count@i}{\the\count@v}% + \else + \op@error{Unbalanced parenthesis in expression}% + {Error between tokens #1 and #2}% + \fi + \else + \advance\count@ii by-1 + \op@search@term{\the\count@i}{\the\count@ii}% + \advance\count@ii by2 + \op@search@term{\the\count@ii}{\the\count@v}% + \advance\count@ii by-1 + \op@token@use{\the\count@ii}% + \fi + \fi + \endgroup +} +\def\op@search@factor#1#2{% + \begingroup + \count@i=#1\relax + \count@v=#2\relax + \ifnum\count@i=\count@v + \op@token@use{#1}% + \else + \count@iii=\count@v + \count@iv=\count@i + \advance\count@iv by-1 + \count@ii=0 + \loop + \ifnum\count@iii>\count@iv + \expandafter\ifx\csname OP@token\the\count@iii\endcsname + \op@string@rpar\relax + \advance\op@parenthesis by1 + \fi + \expandafter\ifx\csname OP@token\the\count@iii\endcsname + \op@string@lpar\relax + \advance\op@parenthesis by-1 + \fi + \expandafter\ifx\csname OP@token\the\count@iii\endcsname + \op@string@mul\relax + \ifnum\op@parenthesis=0 + \count@ii=\count@iii\relax + \count@iii=0 + \fi + \fi + \expandafter\ifx\csname OP@token\the\count@iii\endcsname + \op@string@div\relax + \ifnum\op@parenthesis=0 + \count@ii=\count@iii\relax + \count@iii=0 + \fi + \fi + \expandafter\ifx\csname OP@token\the\count@iii\endcsname + \op@string@idiv\relax + \ifnum\op@parenthesis=0 + \count@ii=\count@iii\relax + \count@iii=0 + \fi + \fi + \advance\count@iii by-1 + \repeat + \ifnum\count@ii=0\relax + \ifnum\op@parenthesis=0 + \op@search@power{\the\count@i}{\the\count@v}% + \else + \op@error{Unbalanced parenthesis in expression}% + {Error between tokens #1 and #2}% + \fi + \else + \advance\count@ii by-1 + \op@search@factor{\the\count@i}{\the\count@ii}% + \advance\count@ii by2 + \op@search@factor{\the\count@ii}{\the\count@v}% + \advance\count@ii by-1 + \op@token@use{\the\count@ii}% + \fi + \fi + \endgroup +} +\def\op@search@power#1#2{% + \begingroup + \count@i=#1\relax + \count@v=#2\relax + \ifnum\count@i=\count@v + \op@token@use{#1}% + \else + \count@iii=\count@v + \count@iv=\count@i + \advance\count@iv by-1 + \count@ii=0 + \loop + \ifnum\count@iii>\count@iv + \expandafter\ifx\csname OP@token\the\count@iii\endcsname + \op@string@rpar\relax + \advance\op@parenthesis by1 + \fi + \expandafter\ifx\csname OP@token\the\count@iii\endcsname + \op@string@lpar\relax + \advance\op@parenthesis by-1 + \fi + \expandafter\ifx\csname OP@token\the\count@iii\endcsname + \op@string@power\relax + \ifnum\op@parenthesis=0 + \count@ii=\count@iii\relax + \count@iii=0 + \fi + \fi + \advance\count@iii by-1 + \repeat + \ifnum\count@ii=0\relax + \ifnum\op@parenthesis=0 + \op@search@primary{\the\count@i}{\the\count@v}% + \else + \op@error{Unbalanced parenthesis in expression}% + {Error between tokens #1 and #2}% + \fi + \else + \advance\count@ii by-1 + \op@search@power{\the\count@i}{\the\count@ii}% + \advance\count@ii by2 + \op@search@power{\the\count@ii}{\the\count@v}% + \advance\count@ii by-1 + \op@token@use{\the\count@ii}% + \fi + \fi + \endgroup +} +\def\op@search@primary#1#2{% + \begingroup + \count@i=#1\relax + \count@v=#2\relax + \ifnum\count@i=\count@v + \op@token@use{#1}% + \else + \expandafter\ifx\csname OP@token#1\endcsname\op@string@abs + \advance\count@i by1 + \op@search@primary{\the\count@i}{\the\count@v}% + \advance\count@i by-1 + \op@token@use{\the\count@i}% + \fi + \expandafter\ifx\csname OP@token#1\endcsname\op@string@ceil + \advance\count@i by1 + \op@search@primary{\the\count@i}{\the\count@v}% + \advance\count@i by-1 + \op@token@use{\the\count@i}% + \fi + \expandafter\ifx\csname OP@token#1\endcsname\op@string@decimal + \advance\count@i by1 + \op@search@primary{\the\count@i}{\the\count@v}% + \advance\count@i by-1 + \op@token@use{\the\count@i}% + \fi + \expandafter\ifx\csname OP@token#1\endcsname\op@string@floor + \advance\count@i by1 + \op@search@primary{\the\count@i}{\the\count@v}% + \advance\count@i by-1 + \op@token@use{\the\count@i}% + \fi + \expandafter\ifx\csname OP@token#1\endcsname\op@string@integer + \advance\count@i by1 + \op@search@primary{\the\count@i}{\the\count@v}% + \advance\count@i by-1 + \op@token@use{\the\count@i}% + \fi + \expandafter\ifx\csname OP@token#1\endcsname\op@string@gcd + \advance\count@i by1 + \op@search@primary{\the\count@i}{\the\count@v}% + \advance\count@i by-1 + \op@token@use{\the\count@i}% + \fi + \expandafter\ifx\csname OP@token#1\endcsname\op@string@mod + \advance\count@i by1 + \op@search@primary{\the\count@i}{\the\count@v}% + \advance\count@i by-1 + \op@token@use{\the\count@i}% + \fi + \expandafter\ifx\csname OP@token#1\endcsname\op@string@neg + \advance\count@i by1 + \op@search@primary{\the\count@i}{\the\count@v}% + \advance\count@i by-1 + \op@token@use{\the\count@i}% + \fi + \expandafter\ifx\csname OP@token#1\endcsname\op@string@rest + \advance\count@i by1 + \op@search@primary{\the\count@i}{\the\count@v}% + \advance\count@i by-1 + \op@token@use{\the\count@i}% + \fi + \expandafter\ifx\csname OP@token#1\endcsname\op@string@round + \advance\count@i by1 + \op@search@primary{\the\count@i}{\the\count@v}% + \advance\count@i by-1 + \op@token@use{\the\count@i}% + \fi + \expandafter\ifx\csname OP@token#1\endcsname + \op@string@lpar\relax + \expandafter\ifx\csname OP@token#2\endcsname + \op@string@rpar\relax + \advance\count@i by1 + \advance\count@v by-1 + \op@search@subexpr{\the\count@i}{\the\count@v}% + \else + \op@error{Garbage after parenthesis}% + {Error between tokens #1 and #2}% + \fi + \fi + \fi + \endgroup +} +\def\op@token@use#1{% + \edef\op@arg{\@nameuse{OP@token#1}}% + \ifx\op@arg\op@string@abs + \opabs{@s\the\op@stack}{@s\the\op@stack}% + \else\ifx\op@arg\op@string@add + \global\op@stackb=\op@stack + \global\advance\op@stackb by-1 + \opadd*{@s\the\op@stackb}{@s\the\op@stack}{@s\the\op@stackb}% + \global\op@stack=\op@stackb + \else\ifx\op@arg\op@string@ceil + \global\op@stackb=\op@stack + \global\advance\op@stackb by-1 + \opceil{@s\the\op@stackb}{@s\the\op@stack}{@s\the\op@stackb}% + \global\op@stack=\op@stackb + \else\ifx\op@arg\op@string@decimal + \opdecimal{@s\the\op@stack}{@s\the\op@stack}% + \else\ifx\op@arg\op@string@div + \global\op@stackb=\op@stack + \global\advance\op@stackb by-1 + \opdiv*{@s\the\op@stackb}{@s\the\op@stack}{@s\the\op@stackb}{r}% + \global\op@stack=\op@stackb + \else\ifx\op@arg\op@string@floor + \global\op@stackb=\op@stack + \global\advance\op@stackb by-1 + \opfloor{@s\the\op@stackb}{@s\the\op@stack}{@s\the\op@stackb}% + \global\op@stack=\op@stackb + \else\ifx\op@arg\op@string@gcd + \op@stackb=\op@stack + \global\advance\op@stackb by-1 + \opgcd{@s\the\op@stackb}{@s\the\op@stack}{@s\the\op@stackb}% + \global\op@stack=\op@stackb + \else\ifx\op@arg\op@string@idiv + \global\op@stackb=\op@stack + \global\advance\op@stackb by-1 + \opidiv*{@s\the\op@stackb}{@s\the\op@stack}{@s\the\op@stackb}{r}% + \global\op@stack=\op@stackb + \else\ifx\op@arg\op@string@integer + \opinteger{@s\the\op@stack}{@s\the\op@stack}% + \else\ifx\op@arg\op@string@mod + \global\op@stackb=\op@stack + \global\advance\op@stackb by-1 + \opidiv*{@s\the\op@stackb}{@s\the\op@stack}{@q}{@s\the\op@stackb}% + \global\op@stack=\op@stackb + \else\ifx\op@arg\op@string@mul + \global\op@stackb=\op@stack + \global\advance\op@stackb by-1 + \opmul*{@s\the\op@stackb}{@s\the\op@stack}{@s\the\op@stackb}% + \global\op@stack=\op@stackb + \else\ifx\op@arg\op@string@neg + \opneg{@s\the\op@stack}{@s\the\op@stack}% + \else\ifx\op@arg\op@string@power + \global\op@stackb=\op@stack + \global\advance\op@stackb by-1 + \oppower{@s\the\op@stackb}{@s\the\op@stack}{@s\the\op@stackb}% + \global\op@stack=\op@stackb + \else\ifx\op@arg\op@string@rest + \global\op@stackb=\op@stack + \global\advance\op@stackb by-1 + \opdiv*{@s\the\op@stackb}{@s\the\op@stack}{@q}{@s\the\op@stackb}% + \global\op@stack=\op@stackb + \else\ifx\op@arg\op@string@round + \global\op@stackb=\op@stack + \global\advance\op@stackb by-1 + \opround{@s\the\op@stackb}{@s\the\op@stack}{@s\the\op@stackb}% + \global\op@stack=\op@stackb + \else\ifx\op@arg\op@string@sub + \global\op@stackb=\op@stack + \global\advance\op@stackb by-1 + \opsub*{@s\the\op@stackb}{@s\the\op@stack}{@s\the\op@stackb}% + \global\op@stack=\op@stackb + \else + \global\advance\op@stack by1\relax + \opcopy{\op@arg}{@s\the\op@stack}% + \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi +} +\def\op@token@create#1{% + \@namexdef{OP@token\the\op@token}{#1}% + \global\advance\op@token by1 + \expandafter\global + \expandafter\let\csname OP@token\the\op@token\endcsname\relax + \global\advance\op@token by-1 +} +\def\op@token@append#1{% + \@namexdef{OP@token\the\op@token}{% + \@nameuse{OP@token\the\op@token}#1}% +} +\def\op@token@single#1{% + \edef\@tempa{#1}% + \ifop@in@name + \global\advance\op@token by1 + \op@in@namefalse + \fi + \ifop@in@number + \global\advance\op@token by1 + \op@in@numberfalse + \op@in@decimalfalse + \fi + \ifx\@tempa\op@string@add + \ifop@in@sign + \global\advance\op@token by-1 + \else + \op@token@create{#1}% + \fi + \else\ifx\@tempa\op@string@sub + \ifop@in@sign + \op@token@create{\op@string@neg}% + \else + \op@token@create{#1}% + \fi + \else + \op@token@create{#1}% + \fi\fi + \global\advance\op@token by1 +} +\def\op@testch@r#1{% + \op@isdigitfalse + \op@isplusfalse + \op@isminusfalse + \op@ismultiplyfalse + \op@isdividefalse + \op@isidividefalse + \op@ispowerfalse + \op@isdotfalse + \op@iscommafalse + \op@islparenthesisfalse + \op@isrparenthesisfalse + \op@isspacefalse + \op@isotherfalse + \count255=`#1\relax + \ifnum\count255=\op@plus \relax + \op@isplustrue + \else \ifnum\count255=\op@minus \relax + \op@isminustrue + \else \ifnum\count255=\op@multiply \relax + \op@ismultiplytrue + \else \ifnum\count255=\op@divide \relax + \op@isdividetrue + \else \ifnum\count255=\op@idivide \relax + \op@isidividetrue + \else \ifnum\count255=\op@pow \relax + \op@ispowertrue + \else \ifnum\count255=\op@dot \relax + \op@isdottrue + \else \ifnum\count255=\op@comma \relax + \op@iscommatrue + \else \ifnum\count255=\op@lparenthesis \relax + \op@islparenthesistrue + \else \ifnum\count255=\op@rparenthesis \relax + \op@isrparenthesistrue + \else \ifnum\count255=\op@space \relax + \op@isspacetrue + \else \ifnum\count255<\op@numbegin \relax + \op@isothertrue + \else \ifnum\count255>\op@numend \relax + \op@isothertrue + \else \op@isdigittrue + \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi +} +\op@split{0}{T0} +\op@split{0}{zero} +\op@split{1}{one} +\op@split{10}{ten} +\op@split{0.1}{tenth} +\op@split{2147483647}{maxinteger} +\op@split{214748364}{maxdivperiod} +\op@split{1073741823}{maxpower} +\catcode`\^=\opHatCode\relax +\catcode`\@=\opAtCode\relax +\endinput |