\documentclass[a4paper,11pt]{report} \RequirePackage[margin=2cm]{geometry} %\RequirePackage[pdftex]{graphicx} \RequirePackage{mathtools} % loads amsmath \RequirePackage{amssymb} % loads amsfonts \RequirePackage{breqn} % for d[group|math] \RequirePackage[utf8]{inputenc} \RequirePackage[unicode,pdftex,bookmarks,colorlinks,linkcolor=blue]{hyperref} \RequirePackage{listings} \RequirePackage{framed} \RequirePackage{array} \def\xcolorcmd{\colorlet{black}{blue}} \usepackage{xcolor} %% \definecolor{Red}{rgb}{0.6,0,0} % for strings \definecolor{DarkGreen}{rgb}{0.25,0.9,0.35} % comments %% \definecolor{myblue}{rgb}{0,0,1.0} % keywords \newcommand{\reduce}{REDUCE} %% formatting % use a san-serif font for online display \renewcommand\familydefault{cmss} \usepackage{parskip} \title{Using the redcas package} \date{\today} \author{Martin Gregory} %\VignetteIndexEntry{Using redcas} %% %% -- Start of document %% \usepackage{Sweave} \begin{document} \maketitle %% \DefineVerbatimEnvironment{Sinput}{Verbatim}{xleftmargin=2em,frame=single} %% \DefineVerbatimEnvironment{Soutput}{Verbatim}{xleftmargin=2em,frame=single} %\setkeys{Gin}{width=\textwidth} %% %% C: Overview %% \section*{Preface} \label{cha:intro} {\it redcas} is an interface to \reduce{}~\cite{REDUCE}, an open source, portable, general-purpose, computer algebra system supporting scalar, vector, matrix and tensor algebra, symbolic differential and integral calculus, arbitrary precision numerical calculations and output in \LaTeX{} format. Using examples, this vignette shows how to configure, start and stop \reduce{} sessions and control output format and explains the three different ways to interact with the \reduce{} session. \reduce{} is written in Lisp and can run on various Lisp dialects, the most common being CSL and PSL. For these two dialects pre-packaged releases known as snapshots are available for various operating systems. {\it redcas} can use the CSL and PSL versions. If you are unfamiliar with \reduce{} you should peruse the vignette {\it Brief Overview of \reduce{}} which provides a very short introduction to \reduce{} for R users, highlighting differences between the two environments. Full details are available in the \reduce{} user manual~\cite{manual} and detailed examples are available on the tutorials page~\cite{tutorials}. In this vignette we use upper case for \reduce{} keywords to easily distinguish them from R keywords. Note that \reduce{} is, by default, case-insensitive with the exception of the contents of strings. \newpage \tableofcontents %% %% C: Configuring, starting and stopping \reduce{} %% \chapter{Configuring, starting and stopping \reduce} \label{cha:conf-start-stop} {\it redcas} can be installed even if \reduce{} is not installed, but to use it requires a \reduce{} installation. Details on installing can be found on the \reduce{} web site~\cite{get-reduce}. %% %% S: Configuring \reduce %% \section{Configuring \reduce} \label{sec:conf-reduce} In order to use {\it redcas} we need to provide the location of the \reduce{} executables, {\it redcsl} or {\it redpsl}. There are four different ways do do this. These are, in order of precedence: \begin{enumerate} \item explicitly specifying the path using the {\it dirpath} argument of {\it redStart}: \begin{lstlisting} sessionId -> redStart(dialect="PSL", dirpath="/usr/local/bin") \end{lstlisting} \item the environment variable {\it REDUCE\_EXEC} exists and contains the path to a directory containing one or both executables \begin{lstlisting} Sys.setenv(REDUCE_EXEC="/usr/local/bin") sessionId -> redStart(dialect="CSL") \end{lstlisting} \item the R option {\it reduce\_exec} exists and contains the path to a directory containing one or both executables \begin{lstlisting} options(reduce_exec="/usr/local/bin") sessionId -> redStart(dialect="CSL") \end{lstlisting} \item the executable is located in a directory listed in the {\it PATH} environment variable. \end{enumerate} %% %% S: Starting and stopping \reduce %% \section{Starting and stopping \reduce{}} \label{sec:start-stop-reduce} A \reduce{} session is started using the {\it redStart} function. While the session is open, various functions can be used to send commands to the \reduce{} session and retrieve the output. This allows direct handling of the output from a given command or set of commands and easy separation of calculation and display. To close a session the {\it redClose} function is used. This optionally retrieves the complete transcript. To start a \reduce{} session load the package and call {\it redStart}: \begin{framed} \begin{Schunk} \begin{Sinput} > library(redcas) > s1 <- redStart(dialect="csl", echo=TRUE) \end{Sinput} \end{Schunk} \end{framed} This starts a CSL \reduce{} session. CSL is the default dialect and does not need to be specified. Sessions are started using a pipe which means they are interactive, i.e. the INT switch is on. The ECHO switch is on by default to facilitate parsing \reduce{} output. {\it redStart} provides the {\it echo} argument to turn the switch off at the start of the session but this is discouraged. {\it redStart} \begin{itemize} \item start a \reduce{} session with output directed to a file in the R session's temporary directory; \item loads the \textit{ASSIST} package which provides, among other features, functions which are indispensible for managing lists, \item loads the \reduce{} functions which are part of {\it redcas} and \item sets any switches specified in the switches argument; \item registers the session details (identifier, connection number, \reduce{} command, \reduce{} log file name, number of calls to redExec, number of lines read from the log file) in a data frame in the package environment. \end{itemize} if successful, {\it redStart} returns the identifier for the session otherwise it terminates with {\it stop}. The identifer is required by other {\it redcas} functions which communicate with the \reduce{} session. The session is closed by calling the {\it redClose} function. The optional {\it log} argument saves the entire \reduce{} transcript to the specified location. \begin{framed} \begin{Schunk} \begin{Sinput} > redClose(s1, log="controlling-reduce.clg") \end{Sinput} \begin{Soutput} [1] TRUE \end{Soutput} \end{Schunk} \end{framed} Session information can be viewed using the {\it showSessions} function and individual details can be retrieved programmatically using the {\it sessionGet} function. For example, to retrieve the session log one may use \begin{framed} readLines(sessionGet("logname")) \end{framed} %% %% C: Controlling output %% \chapter{Controlling output} \label{cha:controlling-output} \reduce{} provides a large number of {\it switches} for controlling how calculations are performed and how results are presented. These are similar to R options except that, as the name suggests, they are boolean only. For options requiring a non-boolean value, \reduce{} uses global variables. Finally there are three different packages for producing \LaTeX{} output, one of which is supported transparently by {\it redcas}. %% %% S: Switches %% \section{Switches} \label{sec:switches} There are approximately 200 switches available, some are part of the core system while the remainder are specific to user-contributed packages. In this section we show how the switches \textit{ROUNDED}, \textit{EXP}, \textit{MCD}, \textit{NAT} and \textit{DIV} affect how expressions are displayed or simplified. \textit{ROUNDED} affects expressions containing numeric values while the other four affect any expression. See the {\it Switch Summary}~\cite{switch} for an alphabetic listing of (most) documented switches including a description of the switch and the context in which it applies. Some additional switches are documented in Appendix A.7 of the \reduce{} user manual~\cite{manual}. The second of the \reduce{} interactive lessons~\cite{tutorials} also provides useful information. For convenience, the vignette {\it Switches by Context} presents the list from the switch summary by context. The function {\it redExec} communicates directly with the \reduce{} session. It returns a list with three named character vector elements: {\it out} is the output of the executed commands; {\it cmd} contains the commands executed as displayed in the \reduce{} log, including the line numbers; and {\it raw} contains the log lines including both commands and output. Here we are only interested in the {\it out} element of the output - we cover this function in more detail in section~\ref{sec:redexec}. As a numeric example, consider calculating $(987,654,321/15)^3$. We start a new session and then assign the result to the \reduce{} variable XN for later use: \begin{framed} includerangemarker=false] \begin{Schunk} \begin{Sinput} > s1 <- redStart(echo=TRUE) > o1 <- redExec(s1, "xn := (987654321/15)^3;", drop.blank.lines=TRUE) > writeLines(o1[["out"]]) \end{Sinput} \begin{Soutput} 35682160321981318855871043 xn := ---------------------------- 125 \end{Soutput} \end{Schunk} \end{framed} As we can see, by default \reduce{} uses exact, indefinite precision arithmetic. To display as a float we need to turn on the \textit{ROUNDED} switch: \begin{framed} \begin{Schunk} \begin{Sinput} > cmd <- c("ON ROUNDED;", "xn;", "OFF ROUNDED;") > redExec(s1, cmd, drop.blank.lines=TRUE)[["out"]] \end{Sinput} \begin{Soutput} [1] "2.85457282576e+23" \end{Soutput} \end{Schunk} \end{framed} As an analytical example consider the function $f(x,y)=(x+y)^2+1/(x+y)$ which can be displayed in various ways. Some are: \begin{equation*} \begin{array}{cc} \displaystyle \frac{(x+y)^3+1}{(x+y)} & \displaystyle \frac{x^3+3x^2y+3xy^2+y^3+1}{(x+y)} \medskip \\ (x+y)^2+(x+y)^{-1} & (x^3+3x^2y+3xy^2+y^3+1)(x+y)^{-1} \end{array} \end{equation*} In \reduce, variables do not need to be declared. A variable can be used with or without assigning it a value. If no value has been assigned the variable is termed unbound and stands for itself. It can, for example, be an independent variable with respect to which an expression is differentiated. Variables with a value are known as bound. In the following \reduce{} statement {\it f} is bound and {\it x} and {\it y} are unbound: \begin{framed} \verb!f := (x + y)^2;! \end{framed} First we look at the effect of the \textit{NAT} switch on how \reduce{} displays results by assigning the bound variable {\it f} and displaying it: \begin{framed} \begin{Schunk} \begin{Sinput} > expoff <- redExec(s1, "OFF EXP;") > f <- redExec(s1, "f := (x + y)^2;", drop.blank.lines=TRUE)[["out"]] > f \end{Sinput} \begin{Soutput} [1] " 2" "f := (x + y)" \end{Soutput} \end{Schunk} \end{framed} We turned the \textit{EXP} switch off to avoid expanding expressions for now. We have created a variable {\it f} in both the \reduce{} session and in R. We see that the resulting vector in R has two elements, even though {\it f} is a single entity. This is due to the fact that, even in plain text output, \reduce{} by default displays results in a way that is close to the normal maths display. This is controlled by the switch \textit{NAT} (natural) which is on by default. We can see how it would appear in \reduce{} if we use {\it writeLines} to display the variable: \begin{framed} \begin{Schunk} \begin{Sinput} > writeLines(f) \end{Sinput} \begin{Soutput} 2 f := (x + y) \end{Soutput} \end{Schunk} \end{framed} Alternatively we can turn the switch \textit{NAT} off to get: \begin{framed} \begin{Schunk} \begin{Sinput} > redExec(s1, c("OFF NAT;", "f ; ON NAT;"), drop.blank.lines=TRUE)[["out"]] \end{Sinput} \begin{Soutput} [1] "(x + y)**2$" " ON NAT;" \end{Soutput} \end{Schunk} \end{framed} Now the expression is written on a single line and is syntactically correct \reduce{} code including the dollar terminator. For parsing results generated by redExec in R this is much more suitable than with NAT on. {\it redcas} functions use NAT off internally to simplify parsing. We can now assign another bound variable, {\it h}, as a function of {\it f}: \begin{framed} \begin{Schunk} \begin{Sinput} > writeLines(h <- redExec(s1, "h := f + 1/f;", drop.blank.lines=TRUE)[["out"]]) \end{Sinput} \begin{Soutput} 4 (x + y) + 1 h := -------------- 2 (x + y) \end{Soutput} \end{Schunk} \end{framed} Again we have chosen to use {\it writeLines} to display {\it h} because \textit{NAT} is on. The default and recommended setting of the switch \textit{MCD} (Making Common Denominators) is on and this displays the expression as a fraction, calculating a common denominator when rational functions are added as in this case. Since we turned \textit{EXP} off, the expressions in parentheses are not expanded. If we turn off \textit{MCD} we get a product with a negative exponent for the divisor: \begin{framed} \begin{Schunk} \begin{Sinput} > writeLines(redExec(s1, c("OFF MCD ;", "h;"), + drop.blank.lines=TRUE)[["out"]]) \end{Sinput} \begin{Soutput} 4 -2 ((x + y) + 1)*(x + y) \end{Soutput} \end{Schunk} \end{framed} If we now turn both \textit{EXP} and \textit{MCD} on we get: \begin{framed} \begin{Schunk} \begin{Sinput} > writeLines(redExec(s1, c("ON EXP, MCD ;", "h;"), + drop.blank.lines=TRUE)[["out"]]) \end{Sinput} \begin{Soutput} 4 3 2 2 3 4 x + 4*x *y + 6*x *y + 4*x*y + y + 1 ----------------------------------------- 2 2 x + 2*x*y + y \end{Soutput} \end{Schunk} \end{framed} where all sub expressions are expanded and common denominators are separated out. Finally we consider the \textit{DIV} switch. As an example, consider the indefinite integral of $sin^4 x$ with respect to $x$: \begin{framed} \begin{Schunk} \begin{Sinput} > rf2 <- redExec(s1, "INT(sin(x)**4, x);") > writeLines(rf2[["out"]]) \end{Sinput} \begin{Soutput} 3 - 2*cos(x)*sin(x) - 3*cos(x)*sin(x) + 3*x --------------------------------------------- 8 \end{Soutput} \end{Schunk} \end{framed} As we can see, by default, \reduce{} displays results using a common denominator for all terms. If we want each term to have its own divisor we can turn on the \textit{DIV} switch which is off by default: \begin{framed} \begin{Schunk} \begin{Sinput} > rf3 <- redExec(s1, c("ON DIV;", "INT(sin(x)**4, x);", "OFF DIV;")) > writeLines(rf3[["out"]]) \end{Sinput} \begin{Soutput} 1 3 3 3 - ---*cos(x)*sin(x) - ---*cos(x)*sin(x) + ---*x 4 8 8 \end{Soutput} \end{Schunk} \end{framed} Note that both \textit{EXP} and \textit{MCD} must be on to produce this form. Further switches which are relevant for controlling simplification are those in the categories {\it Algebra} and {\it Output}. Note that the switch \textit{FACTOR} is a mirror image of \textit{EXP}: if one is on the other is automatically off. %% %% S: Global variables %% \section{Global variables} \label{sec:glob-vars} Several packages use global variables for different purposes including determining output. Most are fairly specialized packages but a useful example is the \textit{DF} operator (differentiation) which uses the variable \textit{FANCY\_PRINT\_DF} to determine how to display derivatives for \LaTeX output. The possible values are \begin{eqnarray*} Setting & df(f,x,2,y) \\ PARTIAL & \frac{\partial ^3 f}{\partial x^2 \partial y} \\ TOTAL & \frac{d^3 f}{dx^2 dy} \\ INDEXED & f_{x,x,y} \end{eqnarray*} with \textit{PARTIAL} being the default. %% %% S: Producing \LaTeX output %% \section{Producing \LaTeX{} output} \label{sec:latex-output} The function {\it redLatex} converts expressions, including the names of variables in the \reduce{} session, to \LaTeX{} using the \reduce{} package TMPRINT. This package is used because it can be easily applied to fragments, supports using the \textbackslash{}frac command and translates variable names which are Greek letters or certain mathematical operators to the corresponding \LaTeX{} command. {\it redLatex} adds the ability to define maps to convert arguments to raised or lowered indices, to translate object names and to enclose the results in a math environment\footnote{see the documentation for details}. It can also be called by any {\it redcas} function which supports the {\it outfmt=latex} argument. The function {\it R2latex} can convert certain R objects to \LaTeX. As an example of an expression, consider the variable {\it h} \begin{framed} f := (x + y)^2; h := f + 1/f; \end{framed} First with the switch \textit{MCD} off: \begin{framed} \begin{Schunk} \begin{Sinput} > writeLines(redLatex(s1, "h", mathenv="equation*", switches=c(off="mcd"))[["tex"]]) \end{Sinput} \begin{equation*} \left(x^2+2 x y+y^2\right)^{-1} \left(x^4+4 x^3 y+6 x^2 y^2+4 x y^3+y^4+1\right) \end{equation*}\end{Schunk} \end{framed} the function returns a list with the same three elements as {\it redExec} and a fourth, named ``tex'', containing the \LaTeX{} output. Since we only need the \LaTeX{} output here we select the ``tex'' list element. We use {\it writeLines} to avoid printing the vector index numbers. The {\it switches} argument causes \textit{MCD} to be turned off for the duration of the {\it redLatex} execution. With \textit{MCD} on the same call returns: \begin{framed} \begin{equation*} \frac{x^4+4 x^3 y+6 x^2 y^2+4 x y^3+y^4+1}{x^2+2 x y+y^2} \end{equation*}\end{framed} For more detailed examples, including converting matrices, arrays and lists, see section~\ref{sec:latex} %% %% C: Interacting with \reduce %% \chapter{Interacting with \reduce} \label{cha:inter-with-reduce} {\it redcas} provides three different methods for interacting with \reduce{} depending on one's knowledge of \reduce{} and on how results are to be returned. These methods are covered in sections~\ref{sec:redexec} to~\ref{sec:spec-interf} below. The different methods may be used together in the same session. In brief the methods are: \begin{description} \item [redExec] executes a vector of arbitrary \reduce{} code and returns its output. The code to execute may contain any element of the language and so requires a certain level of familiarity with \reduce{} programming; \item [redFunc] executes a vector of \reduce{} functions including those defined by the user. This requires knowledge of the arguments of the functions to be executed; \item [Special Interface] functions provide access to specific functions. These functions have arguments tailored to the specific function and construct the necessary \reduce{} calls. They also provide some level of validation of the inputs. Using these functions is described in detail in the package documentation. \end{description} In the following section we first describe some arguments common to each function which calls \reduce. %% %% S: Common arguments %% \section{Common arguments} \label{sec:common-arguments} There are a number of arguments common to multiple {\it redcas} functions. \begin{description} \item [id:] is the session identifier returned by {\it redStart}. It is required by all functions which interact with the session. \item [switches:] is a character vector with one or both of the following named elements \begin{description} \item [on:] a comma-separated string of switches which should be on \item [off:] a comma-separated string of switches which should be off. \end{description} This argument is available on all functions which interact with the session except {\it redExec} and causes the named switches to be set to the desired state for the duration of execution. When used with {\it redStart} the {\it switches} argument is used to set defaults for the session, i.e. the switches are not restored to the previous state after execution of {\it redStart}. Note that {\it swset} prohibits setting of the \textit{FANCY} switch because this formats all output as \LaTeX{}. This could cause issues for {\it redcas} functions when parsing \reduce{} output. Functions which support the {\it latex} option of the {\it outfmt} argument selectively turn on \textit{FANCY} when producing output, so there should generally not be any need to explicitly set \textit{FANCY}. \item [outfmt:] is one of the strings {\it expr}, {\it func}, {\it latex} or {\it text} and determines whether output is an expression, a function, \LaTeX{} or plain text, respectively. The argument is available on all functions which return \reduce{} output except {\it redExec}. The default varies depending on the function and not all options are available on all functions. \item [verbose:] is a logical value controlling printing of additional information. \item [notify:] numeric. If not zero, writes a message to the transcript every {\it notify} seconds to indicate execution is ongoing. Passed via \ldots to {\it redExec}. \item [timeout:] numeric. If not zero and the function is still executing after {\it timeout} seconds, the function terminates with a message to the transcript. Passed via \ldots to {\it redExec}. \item [vec:] logical. Determines whether output of {\it R2latex} is returned as a (nested) list or a vector. Also available from {\it odesolve} which calls {\it R2latex}. \item [eol:] logical. Determines whether a \LaTeX{} end of line character is added to the end of all but the last element of vectors in the output of {\it factorize}, {\it odesolve} or{\it R2latex}. \item [disallow:] a character vector of the names of switches which should not be changed for the called function. This is primarily for use in {\it redcas} functions which accept the switches argument and require a specific state of some switches, but could also be used in user defined functions. \end{description} %% %% S: redExec %% \section{redExec} \label{sec:redexec} {\it redExec} allows for the execution of a vector of abitrary \reduce{} commands. This means that the vector may also include conditional statements, compound statements and procedure definitions. All output generated\footnote{intermediate output can be suppressed by turning the OUT switch off but this {\bfseries must} be turned back on at the latest as the last command in the command vector.} is returned as a list\footnote{If {\it redExec} fails it returns {\it FALSE}.} with three character vector elements: \begin{description} \item [out] the output from the commands executed; \item [cmd] the commands as written to the \reduce{} transcript. This depends on the state of the ECHO switch which is on by default and generally should not be turned off; \item [raw] the portion of the \reduce{} transcript produced by the call. This includes interspersed commands and output. \end{description} {\it redExec} uses the {\it drop.blank.lines} option to make the output more compact - the \reduce{} transcript uses blank lines generously. Depending on what further processing will be done in R, we also need to consider that {\it redExec} returns all output from the commands submitted. So we may want to split execution of \reduce{} commands into appropriate separate calls to {\it redExec}. All other functions which execute \reduce{} code (factorize, odesolve, R2latex, red2Rarray, redDf, redFunc, redLatex, redSolve) do so using {\it redExec}. In the following example we define a \reduce{} procedure for determining the largest prime smaller than a given integer and use a second call to {\it redExec} to call the procedure and display the output: \begin{framed} \begin{Schunk} \begin{Sinput} > lp <- c("PROCEDURE lastprime (n) ;", + " BEGIN SCALAR k, kfact ;", + " k:=n+1 ;", + " REPEAT", + " << k:=k-1 ;", + " kfact:=factorize(k)", + " >> UNTIL LENGTH(kfact) = 1 and SECOND(FIRST(kfact))=1;", + " RETURN FIRST(FIRST(kfact))", + " end ;") > deflp <- redExec(s3, lp) > writeLines(sprintf("largest prime < 10^5: %d", + as.integer(redExec(s3, "lastprime(10e5);", + drop.blank.lines=TRUE)["out"]))) \end{Sinput} \begin{Soutput} largest prime < 10^5: 999983 \end{Soutput} \end{Schunk} \end{framed} %% %% S: redFunc %% \section{redFunc} \label{sec:redfunc} {\it redFunc} provides an alternative method for interfacing with \reduce. It allows the direct execution of a list of \reduce{} operators\footnote{including user-defined procedures} returning the results to R as a character vector or, if multiple operators are passed, a list of character vectors. {\it redFunc} does not assign the results to variables in the \reduce{} session. An example using numeric operators: \begin{framed} \begin{Schunk} \begin{Sinput} > rf1 <- redFunc(s3, func=c('nextprime', 'fix', 'max'), + param=list(10000, -5/4, c(2,3,-4,8))) > str(rf1) \end{Sinput} \begin{Soutput} List of 3 $ nextprime: chr "10007" $ fix : chr "-1" $ max : chr "8" \end{Soutput} \end{Schunk} \end{framed} Note that \textit{FIX} returns the integer part of its argument, i.e. is the \reduce{} version of the R {\it as.integer} function. We can also use {\it redFunc} to call the {\it lastprime} defined in the previous section: \begin{framed} \begin{Schunk} \begin{Sinput} > lp10e5 <- as.integer(redFunc(s3, "lastprime", 10e5)) > lp10e5 \end{Sinput} \begin{Soutput} [1] 999983 \end{Soutput} \end{Schunk} \end{framed} See section~\ref{sec:red2rfn} for how to convert expressions returned from \reduce{} to R functions. Some \reduce{} functions return a list. For example the \textit{MAP} function is the \reduce{} equivalent of {\it lapply} and can also be used on matrices and operator expressions as well as lists. The first argument to \textit{MAP} is the function to execute on each element. Unlike {\it lapply} a complete call to the function is required with a placeholder of the form {\it $\thicksim$identifier} for the argument where the element is referenced. The placeholder identifier may not appear in any of the expressions. The second argument is the data aggregate. Here is an example of integrating a list of expressions: \begin{framed} \begin{Schunk} \begin{Sinput} > rf5 <- redFunc(s3, "map", "int(~w,x), {x^2, 2*x^5, cos(x)^4}") ; > writeLines(rf5) \end{Sinput} \begin{Soutput} 3 x {----, 3 6 x ----, 3 3 - 2*cos(x)*sin(x) + 5*cos(x)*sin(x) + 3*x ---------------------------------------------} 8 \end{Soutput} \end{Schunk} \end{framed} \textit{MAP} returns an object of the same type as the second argument, in this case a list. We can use {\it red2Rlist} to convert this to an R list but need to turn off NAT for the {\it redFunc} call: \begin{framed} \begin{Schunk} \begin{Sinput} > rf6 <- red2Rlist(redFunc(s3, "map", "int(~w,x), {x^2, 2*x^5, cos(x)^4}", + switches=c(off="nat")) ) > str(rf6) \end{Sinput} \begin{Soutput} List of 3 $ : chr "x**3/3" $ : chr "x**6/3" $ : chr "( - 2*cos(x)*sin(x)**3 + 5*cos(x)*sin(x) + 3*x)/8" \end{Soutput} \end{Schunk} \end{framed} %% %% S: Special interfaces %% \section{Special interfaces} \label{sec:spec-interf} While {\it redFunc} can call any \reduce{} operator, the current version of {\it redcas} provides specialized interfaces to a small number of interesting functions. These interfaces run checks on the inputs, provide more features for controlling the output and convert output to appropriate R objects. Future versions of {\it redcas} will provide further such interfaces. %% %% subS: factorize %% \subsection{factorize: Factorizing polynomials, rationals or integers} \label{sec:factorize} The operator \textit{FACTORIZE} can factorize univariate and multivariate polynomials with integer, rational or complex coefficients. It can also factorize integers and rationals. The numbers $e$, $i$ and $pi$ may also appear as coefficients. If \textit{ROUNDED} is on, both $e$ and $pi$ are substituted by their values to the current precision level. To factorize polynomials involving $i$ \textit{COMPLEX} must be on. The {\it redcas} function {\it factorize}, provides an interface to the \reduce{} operator: \begin{framed} factorize(id, x, prime=integer(0), outfmt="text", switches=character(0), eol=FALSE, verbose=FALSE, ...) \end{framed} For each element in $x$ a list of factor/exponent pairs is returned, for example: \begin{framed} \begin{Schunk} \begin{Sinput} > fin <- c("x^2+1", + 360, + "4x^5+30x^4+107x^3+605x^2/2+600x+500", + "x^3 + i*x^2 + x + i", + "2x^7+17x^6+54x^5+72x^4+12x^3-69x^2-68x-20") > fotxt <- factorize(s3, fin, outfmt="text") > for (i in 1:length(fotxt)) writeLines(paste0(fotxt[[i]], collapse=", ")) \end{Sinput} \begin{Soutput} list("x**2 + 1", 1) list(2, 3), list(3, 2), list(5, 1) 0.5, list("x**2 + 8", 1), list("2*x + 5", 3) list("i + x", 1), list("x**2 + 1", 1) list("2*x + 5", 1), list("x - 1", 1), list("x + 2", 2), list("x + 1", 3) \end{Soutput} \end{Schunk} \end{framed} In the case of a common numeric factor, this factor is the first element in the list as can be seen in the result for {\it fin[3]}. Because values containing only digits are converted by {\it redcas} to numeric, it is displayed as $0.5$ instead of $\frac{1}{2}$. \subsubsection{\LaTeX{} output} \label{sec:factorize-latex} We can ask for \LaTeX{} output when factorizing the expressions in the vector {\it fin} above by specifying {\texttt outfmt="latex"}. In this case a single list is returned, each element being a vector of the prime factors raised to the appropriate power. In order to display the factors for each expression on a single line we use the {\it array} environment. This requires adding an appropriate number of blanks to the expressions with fewer factors, adding column separators (\&) and using the {\it ltx.append.eol} function to append \LaTeX{} end of line commands as in the following: \begin{framed} \begin{Schunk} \begin{Sinput} > foltx <- factorize(s3, fin, outfmt="latex") > foltx.l <- unlist (lapply(foltx, length)) > foltx <- ltx.append.eol( + unlist( + lapply(1:length(foltx), + function(z){paste0(c(foltx[[z]], rep(" ", 4-foltx.l[z])), + collapse=" & ")})) + ) > writeLines(c("\\[", "\\begin{array}{llll}", + foltx, + "\\end{array}", "\\]")) \end{Sinput} \[ \begin{array}{llll} x^2+1 & & & \\ 2^3 & 3^2 & 5 & \\ \frac{1}{2} & x^2+8 & \left(2 x+5\right)^3 & \\ i+x & x^2+1 & & \\ 2 x+5 & x-1 & \left(x+2\right)^2 & \left(x+1\right)^3 \end{array} \]\end{Schunk} \end{framed} \subsubsection{Complex roots} \label{sec:factorize-cplx-roots} Note that the polynomial $x^2+1$ is not factorized because neither the \textit{COMPLEX} nor the \textit{ROUNDED} switch is on. Because of the explicit $i$ in $x^3+ix^2+x+i$, complex roots are returned for this polynomial. If we try $x^2+1$ with \textit{COMPLEX} on: \begin{framed} \begin{Schunk} \begin{Sinput} > foltx1 <- factorize(s3, fin[1], outfmt="latex", switches=c(on="complex")) > writeLines(c("\\[", paste0(unlist(foltx1), collapse=" \\quad "), "\\]")) \end{Sinput} \[ x+i \quad x-i \]\end{Schunk} \end{framed} Furthermore, if \textit{ROUNDED} is on and \textit{COMPLEX} off, the factor $x^2+8$ of {\it fin[3]} is further factorized to $(x+\sqrt{8}i)(x-\sqrt{8}i)$: \begin{framed} \begin{Schunk} \begin{Sinput} > foltx3 <- factorize(s3, fin[3], outfmt="latex", switches=c(on="rounded")) > writeLines(c("\\[", paste0(unlist(foltx3), collapse=" \\quad "), "\\]")) \end{Sinput} \[ 4 \quad 2.82842712475 i+x \quad -\left(2.82842712475 i-x\right) \quad \left(x+2.5\right)^3 \]\end{Schunk} \end{framed} If both switches are on, this further factorization is not performed. \subsubsection{Using the \textit{ROUNDED} switch} \label{sec:factorize-rounded} With \LaTeX{} output the numbers $e$ and $pi$ are displayed in the usual mathematical form: \begin{framed} \begin{Schunk} \begin{Sinput} > foepi <- factorize(s3, c("2pi^2 + 9pi*x - 5x^2", "x^e*e - x^e*x + e - x"), + outfmt="latex") > writeLines(c("\\[", "\\begin{array}{llll}", + ltx.append.eol(unlist(lapply(foepi, paste0, collapse=" & "))), + "\\end{array}", "\\]")) \end{Sinput} \[ \begin{array}{llll} 2 \pi-x & \pi+5 x\\ x^e+1 & e-x \end{array} \]\end{Schunk} \end{framed} The \textit{ROUNDED} switch replaces $e$ and $pi$ with their values at the current precision: \begin{framed} \begin{Schunk} \begin{Sinput} > foepi <- factorize(s3, c("2pi^2 + 9pi*x - 5x^2", "x^e*e - x^e*x + e - x"), + outfmt="latex", switches=c(on="rounded")) > writeLines(c("\\[", "\\begin{array}{llll}", + ltx.append.eol(unlist(lapply(foepi, paste0, collapse=" & "))), + "\\end{array}", "\\]")) \end{Sinput} \[ \begin{array}{llll} -5 & x+0.628318530718 & x-6.28318530718\\ -\left(x^{0.718281828459} x^2+1\right) & x-2.71828182846 \end{array} \]\end{Schunk} \end{framed} \subsubsection{Multivariate polynomials}\label{sec:mult-polyn} {\it factorize} can also handle polynomials of high degree with ease. We show this using $x^{33}+y^{33}$ and because the first factor contains 31 terms we display using \LaTeX{} as this is much easier to read. \begin{framed} \begin{Schunk} \begin{Sinput} > q33 <- factorize(s3, "x^33+y^33", outfmt="latex") > writeLines(c("\\begin{dgroup*}", + paste0("\\begin{dmath*}", ltx.append.eol(unlist(q33)), "\\end{dmath*}"), + "\\end{dgroup*}")) \end{Sinput} \begin{dgroup*} \begin{dmath*}x^{20}+x^{19} y-x^{17} y^3-x^{16} y^4+x^{14} y^6+x^{13} y^7-x^{11} y^9-x^{10} y^{10}-x^9 y^{11}+x^7 y^{13}+x^6 y^{14}-x^4 y^{16}-x^3 y^{17}+\\\end{dmath*} \begin{dmath*}x y^{19}+y^{20}\\\end{dmath*} \begin{dmath*}x^{10}-x^9 y+x^8 y^2-x^7 y^3+x^6 y^4-x^5 y^5+x^4 y^6-x^3 y^7+x^2 y^8-x y^9+y^{10}\\\end{dmath*} \begin{dmath*}x^2-x y+y^2\\\end{dmath*} \begin{dmath*}x+y\end{dmath*} \end{dgroup*}\end{Schunk} \end{framed} Note that requesting \LaTeX{} output can take up to four times longer than for plain text. %% %% subS: redSolve %% \subsection{redSolve: Solving systems of equations} \label{sec:redsolve} The operator \textit{SOLVE}~\cite{solve} is a powerful tool for solving one or more simultaneous algebraic equations in one or more variables, both linear and non-linear. Equations may contain arbitrary constants. The operator takes two arguments: a list of the equations comprising the system and a list of the unknowns. The latter is optional unless the equations contain arbitrary constants, such as {\it c} in the following example. First we use {\it redExec} to call {\it solve} in order to show the raw \reduce{} output: \begin{framed} \begin{Schunk} \begin{Sinput} > code <- c("eq1:= x + y + z ;", + "eq2:= x^2 + y^2 + z^2 -9 ;", + "eq3:= x^2 + c*y^2 - z^2 ;", + "on rounded ;") > def.eqn <- redExec(s3, code) # to avoid printing the equations again > sol1 <- redExec(s3, "sol1:=solve({eq1, eq2, eq3}, {x, y, z});")[["out"]] \end{Sinput} \end{Schunk} \end{framed} which produces the following nested (\reduce) list. \begin{framed} %% to complete boxes which break across pages \begin{Schunk} \begin{Soutput} 2.12132034356*c - 2.12132034356 sol1 := {{x=---------------------------------, 2 0.5 (c + 3) 4.24264068712 y=---------------, 2 0.5 (c + 3) - 2.12132034356*(c + 1) z=--------------------------}, 2 0.5 (c + 3) - 2.12132034356*c + 2.12132034356 {x=------------------------------------, 2 0.5 (c + 3) -4.24264068712 y=----------------, 2 0.5 (c + 3) 2.12132034356*(c + 1) z=-----------------------}, 2 0.5 (c + 3) {x=2.12132034356,y=0,z=-2.12132034356}, {x=-2.12132034356,y=0,z=2.12132034356}} \end{Soutput} \end{Schunk} \end{framed} The top-level list has four elements, one for each solution, each of which is a list containing the values of the unknowns. Note that the arbitrary constant {\it c} is part of the first two solutions. Even turning NAT off, this can be very unwieldy so {\it redcas} provides the {\it redSolve} function which parses the output and returns an object of class {\it redcas.solve} containing both inputs and outputs. For convenience, {\it redSolve} supports the {\it switches} argument to allow turning switches on or off before calling {\it solve}: \begin{framed} \begin{Schunk} \begin{Sinput} > soln <- redSolve(s3, + eqns=c("x + y + z = 0", "x^2 + c*y^2 + z^2 = 9", + "x^2 + y^2 - z^2 = 0"), + unknowns=c("x", "y", "z"), + switches="on rounded;") > print(soln) \end{Sinput} \begin{Soutput} Equations: x + y + z = 0 x^2 + c*y^2 + z^2 = 9 x^2 + y^2 - z^2 = 0 Number of solutions: 4 Solutions: x y z 2.12132034356 0 -2.12132034356 -2.12132034356 0 2.12132034356 0 3.0/(c + 1)**0.5 ( - 3)/(c + 1)**0.5 0 ( - 3.0)/(c + 1)**0.5 3/(c + 1)**0.5 Unknowns: x,y,z Switches: on: rounded \end{Soutput} \end{Schunk} \end{framed} As can be seen, {\it redcas} provides a print method which attempts to display the solutions in as compact a manner as possible but will not always be as neat as in this example. The individual slots of the class can be accessed in the usual way using @. Note that the {\it solutions} slot has type character since values may contain variable names which may or may not exist in the R session. Even if they do exist, using these values might cause unintended results. The object has another slot {\it rsolutions} which contains evaluated versions of the {\it solutions} slot if these are numbers otherwise character. The print method does not display the {\it rsolutions} slot. In this particular case one could evaluate the results for a specific value of {\it c} as follows: \begin{framed} \begin{Schunk} \begin{Sinput} > c <- 25 > sol25 <- lapply(soln@solutions, + function(x){unlist(lapply(x, + function(y){eval(str2expression(y))}))}) > print(sol25) \end{Sinput} \begin{Soutput} [[1]] x y z 2.12132 0.00000 -2.12132 [[2]] x y z -2.12132 0.00000 2.12132 [[3]] x y z 0.0000000 0.5883484 -0.5883484 [[4]] x y z 0.0000000 -0.5883484 0.5883484 \end{Soutput} \end{Schunk} \end{framed} An alternative is to use the function {\it red2Rfn} --- see section~\ref{sec:red2rfn} Switches can have a significant effect on the result. As an example consider the following set of equations with the \textit{ROUNDED} switch on and then off: \begin{framed} \begin{Schunk} \begin{Sinput} > r.on <- redSolve(id=s3, + eqns=c("x+y+z = 0", "x^2 + y^2 + z^2 = 9", "x^2 + y^2 = z"), + unknowns=c("x", "y", "z"), switches="on rounded;" ) > r.off <- redSolve(id=s3, + eqns=c("x+y+z = 0", "x^2 + y^2 + z^2 = 9", "x^2 + y^2 = z"), + unknowns=c("x", "y", "z"), switches="off rounded;" ) \end{Sinput} \end{Schunk} \end{framed} With \textit{ROUNDED} on, \reduce{} returns a set of solutions containing only real and complex constants (we have rounded to 6 digits to show the solutions as side-by-side columns): %% solve turns off print_precision, so to get the output as multiple columns in LaTeX we %% need to round \begin{framed} \begin{Schunk} \begin{Soutput} Equations: x+y+z = 0 x^2 + y^2 + z^2 = 9 x^2 + y^2 = z Number of solutions: 4 Solutions: x y z 1.77069 + 2 .21496i 1.77069 - 2 .21496i - 3.54138 - 1.27069 + 0 .58648i - 1.27069 - 0 .58648i 2.54138 - 1.27069 - 0 .58648i - 1.27069 + 0 .58648i 2.54138 1.77069 - 2 .21496i 1.77069 + 2 .21496i - 3.54138 Unknowns: x,y,z Switches: on: rounded \end{Soutput} \end{Schunk} \end{framed} and in this case the {\it rsolutions} slot contains complex or numeric types. With \textit{ROUNDED} off we get the same set of solutions but not simplified: \begin{framed} \begin{Schunk} \begin{Soutput} Equations: x+y+z = 0 x^2 + y^2 + z^2 = 9 x^2 + y^2 = z Number of solutions: 4 Solution 1: x: (2*sqrt( - sqrt(37) - 7)*sqrt(3) + sqrt(74) + sqrt(2))/(4*sqrt(2)) y: ( - 2*sqrt( - sqrt(37) - 7)*sqrt(3) + sqrt(74) + sqrt(2))/(4*sqrt(2)) z: ( - (sqrt(37) + 1))/2 Solution 2: x: ( - 2*sqrt( - sqrt(37) - 7)*sqrt(3) + sqrt(74) + sqrt(2))/(4*sqrt(2)) y: (2*sqrt( - sqrt(37) - 7)*sqrt(3) + sqrt(74) + sqrt(2))/(4*sqrt(2)) z: ( - (sqrt(37) + 1))/2 Solution 3: x: (2*sqrt(sqrt(37) - 7)*sqrt(3) - sqrt(74) + sqrt(2))/(4*sqrt(2)) y: ( - 2*sqrt(sqrt(37) - 7)*sqrt(3) - sqrt(74) + sqrt(2))/(4*sqrt(2)) z: (sqrt(37) - 1)/2 Solution 4: x: ( - 2*sqrt(sqrt(37) - 7)*sqrt(3) - sqrt(74) + sqrt(2))/(4*sqrt(2)) y: (2*sqrt(sqrt(37) - 7)*sqrt(3) - sqrt(74) + sqrt(2))/(4*sqrt(2)) z: (sqrt(37) - 1)/2 Unknowns: x,y,z Switches: off: rounded \end{Soutput} \end{Schunk} \end{framed} Although the expressions contain no variables, they do contain negative square roots which would produce NaNs if evaluated. In this case, the expressions may be evaluated by substituting {\texttt sqrt(-x)} with {\texttt complex(imaginary=sqrt(x))}. A future release of {\it redcas} may implement handling of such cases. \subsubsection{Underdetermined systems} In cases where there are more variable than unknowns, \reduce{} provides solutions which contain arbitrary constants of the form $ARBINT(n)$ for real and $ARBCOMPLEX(n)$ for complex solutions where $n$ is the $n^{th}$ such constant generated in the session. For \LaTeX{} output We can convert this to $C_n$ with the {\it usermap} argument: the : \begin{framed} \begin{Schunk} \begin{Sinput} > arbon <- redSolve(id=s3, eqns=c("x^3+y", "y^2+z"), unknowns=c("x", "y", "z"), + outfmt="latex", + usermap=list(ident=c(arbcomplex="C"), index=c(C="_"))) > writeLines(ltx.append.eol(c("x & y & z", + unlist(lapply(arbon@solutions, paste0, + collapse=" & "))))) \end{Sinput} \end{Schunk} \begin{equation*} \begin{array}{lll} x & y & z\\ C_{1} & -x^3 & -x^6 \end{array} \end{equation*} \end{framed} To avoid arbitrary constants altogether and present the solutions as expressions of one or more of the variables, we can turn off the \textit{ARBVARS} switch: \begin{framed} \begin{Schunk} \begin{Sinput} > arboff <- redSolve(id=s3, eqns=c("x^3+y", "y^2+z"), unknowns=c("x", "y", "z"), + outfmt="latex", switches=c(off="arbvars")) > writeLines(ltx.append.eol(c("y & z", + unlist(lapply(arboff@solutions, paste0, + collapse=" & "))))) \end{Sinput} \end{Schunk} \begin{equation*} \begin{array}{lll} y & z\\ -x^3 & -x^6 \end{array} \end{equation*} \end{framed} %% %% subS: redDf %% \subsection{redDf: Differentiation} \label{sec:reddf} {\it redDf} provides an interface to the \textit{DF} operator~\cite{redDf} which differentiates expressions by one or more variables specifying the degree for each variable. The syntax is \begin{framed} redDf(id, expr, depend=character(0), style=character(0), outfmt="func", switches=character(0), name=character(0), verbose=FALSE, ...) \end{framed} The argument {\it expr} is a character vector with each element containing the expression to be differentiated, the variable(s) to differentiate by, and the corresponding degree \begin{equation*} \begin{array}{c!{\quad}c!{\quad}c!{\quad}c!{\quad}c!{\quad}c} x & , v_1 & (, d_1) & \ldots & (, v_n & (, d_n)) \end{array} \end{equation*} where \begin{description} \item [()] indicate optional entries, \item [$x$] is the expression to be differentiated, \item [$v_i$] are the variables to differentiate by. The order of the $v_i$ determines the order of differentiation, and \item [$d_i$] is the degree of differentiation by $v_i$. If $d_i$ is 1 it may be omitted. \end{description} By default, {\it redDf} returns a single function if {\it expr} contains only one element, otherwise a list of functions. We will use the following expressions to illustrate the use of {\it redDf}: \begin{equation*} f1 = v cos(w) \quad f2 = (a+b)^2 \quad f3 = x^3+x^2/2 \end{equation*} We start with differentiation by a single variable: \begin{framed} \begin{Schunk} \begin{Sinput} > redDf(s1, c("v*cos(w), w", "(a+b)^2, a", "x^3+x^2/2, x, 2")) \end{Sinput} \begin{Soutput} $fn1 function (w, v) { return(-sin(w) * v) } $fn2 function (a, b) { return(2 * (a + b)) } $fn3 function (x) { return(6 * x + 1) } \end{Soutput} \end{Schunk} \end{framed} \subsubsection{Implicit dependencies} The argument {\it depend} can be used to define dependencies between variables by calling the command \textit{DEPEND} prior to differentiation. If the dependent variable is prefixed by a tilde, the dependency is removed using the \textit{NODEPEND} command after differentiation. We specify text output to reduce the size of the output. \begin{framed} \begin{Schunk} \begin{Sinput} > print(unlist(redDf(s1, c("v*cos(w), w", "(a+b)^2, a"), depend=c("~v, w", "b, a"), + outfmt="text"))) \end{Sinput} \begin{Soutput} [1] "cos(w)*df(v,w) - sin(w)*v" "2*(df(b,a)*a + df(b,a)*b + a + b)" \end{Soutput} \begin{Sinput} > print(unlist(redDf(s1, c("v*cos(w), w", "(a+b)^2, a"), outfmt="text"))) \end{Sinput} \begin{Soutput} [1] " - sin(w)*v" "2*(df(b,a)*a + df(b,a)*b + a + b)" \end{Soutput} \end{Schunk} \end{framed} Since the dependency of $v$ on $w$ is removed after the first call, the result differs for the first element. %% style with ~ \subsubsection{Controlling appearance of derivatives} When producing \LaTeX{} we can use the {\it style} argument to determine how derivatives are to be displayed. There are three possibilities: the default {\it partial} ($\partial{y}/\partial{x}$), {\it total} ($dy/dx$) and {\it indexed} ($y_x$). In \reduce{} this is implemented using a global variable, \textit{FANCY\_PRINT\_DF}. As a result, the style is applied to all results as we can see: \begin{framed} \begin{Schunk} \begin{Sinput} > rdf1 <- c("\\[", "\\begin{array}{lll}", + paste0(unlist(redDf(s1, c("v*cos(w), w", "(a+b)^2, a", + "log(x)*(x+y)^2, y,x"), + depend=c("~v,w", "~b,a"), outfmt="latex")), + collapse="& \\quad"), + "\\end{array}", + "\\]") > writeLines(rdf1) \end{Sinput} \[ \begin{array}{lll} \cos\left(w\right) \frac{\partial v}{\partial w}-\sin\left(w\right) v& \quad2 \left(\frac{\partial b}{\partial a} a+\frac{\partial b}{\partial a} b+a+b\right)& \quad\frac{2 \left(\log\left(x\right) x+x+y\right)}{x} \end{array} \]\end{Schunk} \end{framed} while specifying {\it style="total"} produces \begin{framed} \[ \begin{array}{lll} \cos\left(w\right) \frac{d v}{d w}-\sin\left(w\right) v& \quad2 \left(\frac{d b}{d a} a+\frac{d b}{d a} b+a+b\right)& \quad\frac{2 \left(\log\left(x\right) x+x+y\right)}{x} \end{array} \]\end{framed} Note that the style applies to all elements of {\it expr} so if different styles are required for different elements, it is necessary to use separate calls for each style. %% output as functions - graph \subsubsection{Using function output format} Returning a function can be useful if, for example, the derivative should be plotted. The {\it curve} function can take a function as its first argument: \begin{framed} \begin{Schunk} \begin{Sinput} > pdf(file="Using-redcas-plotdf.pdf") #, width=3, height=3) > curve(x^3+x^2/2, col="red", xlim=c(-1,1), ylim=c(-0.5,1), asp=1, ann=FALSE) > dfx <- redDf(s1, "x^3+x^2/2, x") > curve(dfx, col="blue", add=TRUE) > legend(x=0.45, y=-0.15, legend=expression(x^3+x^2/2,frac(d(x^3+x^2/2),dx)), + col=c("red","blue"), lty=1, bty="n") > dev.off() \end{Sinput} \begin{Soutput} null device 1 \end{Soutput} \end{Schunk} \end{framed} and the result can be seen in Figure~\ref{fig:plotdf}. \begin{figure}[h] \caption{$x^3+x^2/2$ and its first derivate} \label{fig:plotdf} \begin{center} \includegraphics[scale=0.65]{Using-redcas-plotdf.pdf} \end{center} \end{figure} %% how to do it directly from Sweave but this uses the Rnw file name to construct the %% output and LaTeX complains that it's not platform independent. %% \begin{Scode}{label=plotdfdone, echo=FALSE, fig=TRUE, pdf=FALSE, png=TRUE} %% \Scoderef{plotdf} %% \end{Scode} %% rules \subsubsection{Defining relations between expressions} The {\it OPERATOR} declaration can be used to implicitly define dependencies because it allows a variable to be treated as a function with an undefined number of arguments. For example \begin{verbatim} 1: OPERATOR f, g ; 2: DF(f(x), x) ; \end{verbatim} returns $df(x)/dx$ because $f(x)$ implies that $f$ depends on $x$. The \textit{LET} operator goes a step further by defining explict relations between variables or expressions. We could define $g(x)$ to be the derivative of $f$ w.r.t. $x$: \begin{framed} \begin{verbatim} 4: LET DF(f(x),x) => g(x) ; 5: DF(f(x),x,2) + DF(f(x),x)); \end{verbatim} \end{framed} which returns $dg(x)/dx + g(x)$. This rule only applies when the name $x$ is used. To generalize to any variable we use: \begin{framed} \begin{verbatim} 6: LET DF(f(~x),x) => g(x) ; 7: DF(f(y),y,2) + DF(f(y),y)); \end{verbatim} \end{framed} which returns $dg(y)/dy + g(y)$. In order to define rules through {\it redcas} we use the {\it redExec} function. %% %% subS: odesolve %% \subsection{odesolve: Solving Ordinary Differential Equations} \label{sec:odesolve} %% we need to ensure rounded is off {\it odesolve} provides an interface to the \reduce{} ODESOLVE operator which solves ordinary differential equations supporting initial and boundary conditions and providing information on the method of solution. \begin{framed} \begin{lstlisting}[language=R] odesolve(id, eqn, depvar=character(0), indvar=character(0), icond=character(0), bcond=character(0), opt=character(0), outfmt="text", vec=FALSE, eol=TRUE, switches=character(0), verbose=FALSE, ...) \end{lstlisting} \end{framed} The function returns an object of class {\it redcas.odesolve} which contains the equation, dependent and independent variables, any specified conditions, options and switches, the solution if any, messages and the generated \reduce{} code. If conditions were provided and the option {\it trode} specified, the general solution is also included. \subsubsection{General solution} \label{sec:ode-general} Our first example solves the equation $dy/dx - y = x^2$. The solution contains an arbitrary constant rendered by \reduce{} as \texttt{arbconst(n)} so we use the {\it usermap} argument to convert this to $C_n$. We use \LaTeX{} output throughout this section. \begin{framed} \begin{Schunk} \begin{Sinput} > ode.1 <- odesolve(s3, eqn="df(y,x) - y = x^2", + depvar="y", indvar="x", outfmt="latex", + usermap=list(ident=c("arbconst"="C"), index=c("C"="_"))) > writeLines(ltx.append.eol(unlist(ode.1@solution))) \end{Sinput} \end{Schunk} \begin{eqnarray*} y=e^x C_{1}-x^2-2 x-2\end{eqnarray*} \end{framed} \subsubsection{Initial and boundary conditions} \label{sec:ode-conditions} As an example of initial conditions, consider $y'-y=e^x$ with $y=0$ when $x=0$: \begin{framed} \begin{Schunk} \begin{Sinput} > ode.2 <- odesolve(s3, eqn="df(y,x,2) - 2*df(y,x) - 3y = 0", + depvar="y", indvar="x", icond="x=0, y=2, df(y,x)=-4", + outfmt="latex") > writeLines(ltx.append.eol(unlist(ode.2@solution))) \end{Sinput} \end{Schunk} \begin{eqnarray*} y=\frac{-e^{4 x}+5}{2 e^x}\end{eqnarray*} \end{framed} Note that we don't need the {\it usermap} argument here because there are no arbitrary constants when conditions are specified. The result is: If we wish to display this as a sum of expressions, we can turn on the \textit{DIV} switch. This, however, does not affect expressions which are equations and so has no effect on the output of {\it odesolve} which is an equation. To get around this we first call {\it swset} to turn on \textit{DIV}, then call {\it odesolve} with text output and finally call {\it R2latex} on the right hand side of the equation to produce \LaTeX{} output\footnote{a future release of odesolve may automate this if on="div" is specified}: \begin{framed} \begin{Schunk} \begin{Sinput} > ode.2t <- odesolve(s3, eqn="df(y,x,2) - 2*df(y,x) - 3y = 0", + depvar="y", indvar="x", icond="x=0, y=2, df(y,x)=-4", + outfmt="text") > div.on <- swset(s3, c(on="div")) > sol.2t <- paste("y=", R2latex(s3, sub("^y=", "", ode.2t@solution))) > writeLines(ltx.append.eol(unlist(sol.2t))) \end{Sinput} \end{Schunk} \begin{eqnarray*} y= e^{-x} \left(-\frac{1}{2} e^{4 x}+\frac{5}{2}\right)\end{eqnarray*} \end{framed} As an example of boundary conditions, consider $y''=y$ with $y=a$ when $x=0$ and $y=b$ when $x=1$: \begin{framed} \begin{Schunk} \begin{Sinput} > ode.3 <- odesolve(s3, "df(y,x,2) = y",depvar="y", indvar="x", + bcond=c("x = 0, y = a, x = 1, y = b"), + outfmt="latex") > writeLines(ltx.append.eol(unlist(ode.3@solution))) \end{Sinput} \end{Schunk} \begin{eqnarray*} y=\frac{-e^{2 x} a+e^{2 x} b e+a e^2-b e}{e^x e^2-e^x}\end{eqnarray*} \end{framed} Note that we don't need the {\it usermap} argument here because there are no arbitrary constants when conditions are specified. The result is: \subsubsection{ODESOLVE options} \label{sec:ode-options} Depending on the solution techniques chosen, \textit{ODESOLVE} produces an explicit, implicit or parametric solution. An {\it explicit} solution is an equation with $y$ isolated on the left, an {\it implicit} solution is an equation that determines $y$ as one or more of its solutions and a {\it parametric} solution expresses both $x$ and $y$ in terms of some additional parameter\footnote{for convenience we use $y$ and $x$ for the dependent and independent variables, respectively.}. \textit{ODESOLVE} provides the following options which request a specific form: \begin{description} \item [\textit{EXPLICIT}] attempt to convert solutions to explicit form; \item [\textit{IMPLICIT}] attempt to convert a parametric solution to implicit form; \end{description} A further option, \textit{basis}, requests the solution as a list of two elements. The first is a list of basis equations for the solution and the second is a specific solution. If conditions are applied, \emph{basis} is ignored. The option \textit{TRODE} (TRace ODE) provides diagnostic information: classification of the ODE, intermediate results such as reduced equations. If conditions are specified it also returns the general equation, if any. The {\it redcas} function {\it odesolve} returns the diagnostic messages in the slot {\it msg} and the general solution, if any, in the slot {\it gen.solution}. We can illustrate the use of \textit{basis} and \textit{trode} using the equation $y'' + 9y = sin(2x)$. If we use only the \textit{trode} option and specify initial conditions $x=0, y=2$ we get both the specific~\eqref{eq:ode-opt-1} and general~\eqref{eq:ode-opt-2} solutions: \begin{framed} \begin{Schunk} \begin{Sinput} > odeopt1 <- odesolve(s3, "df(y,x,2) + 9*y = sin(2*x)", depvar="y", indvar="x", + icond="x=0, y=2, df(y,x)=-4", opt="trode", outfmt="latex", + usermap=list(ident=c("arbconst"="C"), index=c("C"="_"))) > writeLines(c("\\begin{gather}", + paste0(unlist(odeopt1@solution), "\\label{eq:ode-opt-1} \\\\"), + paste0(unlist(odeopt1@gen.solution), "\\label{eq:ode-opt-2}"), + "\\end{gather}")) \end{Sinput} \begin{gather} y=\frac{30 \cos\left(3 x\right)-22 \sin\left(3 x\right)+3 \sin\left(2 x\right)}{15}\label{eq:ode-opt-1} \\ y=\frac{5 C_{9} \sin\left(3 x\right)+5 C_{8} \cos\left(3 x\right)+\sin\left(2 x\right)}{5}\label{eq:ode-opt-2} \end{gather}\end{Schunk} \end{framed} If we use the \textit{basis} option we get the following result where \begin{framed} \begin{Schunk} \begin{Sinput} > odeopt2 <- odesolve(s3, "df(y,x,2) + 9*y = sin(2*x)", depvar="y", indvar="x", + opt="basis", outfmt="latex") > writeLines(c("\\begin{gather}", + ltx.append.eol(paste0(unlist(odeopt2@solution), + "\\label{eq:ode-opt-", 3:5, "}")), + "\\end{gather}")) \end{Sinput} \begin{gather} \cos\left(3 x\right)\label{eq:ode-opt-3}\\ \sin\left(3 x\right)\label{eq:ode-opt-4}\\ \frac{1}{5} \sin\left(2 x\right)\label{eq:ode-opt-5} \end{gather}\end{Schunk} \end{framed} equations~\eqref{eq:ode-opt-3} and~\eqref{eq:ode-opt-4} are the basis and \eqref{eq:ode-opt-5} is a specific solution. As we see in the following section, solving the Lagrange equation $v = 2uv' - a(v')^3$ produces a solution in parametric form. We can request the implicit form as follows: \begin{framed} \begin{Schunk} \begin{Sinput} > odeopt3 <- odesolve(s3, eqn="v = 2u*df(v,u) - a*df(v,u)^3", + depvar="v", indvar="u", outfmt="latex", opt="implicit", + switches=c(off="allfac, rounded",on="div,intstr"), + usermap=list(ident=c("arbparam"="p", "arbconst"="C"), + index=c("p"="_", "C"="_")), eol=FALSE) > writeLines(c("\\begin{dmath}\\label{eq:ode-opt-7}", + paste0(unlist(odeopt3@solution), collapse=""), + "\\end{dmath}")) \end{Sinput} \begin{dmath}\label{eq:ode-opt-7} -64 C_{10}^3 a^2-128 C_{10}^2 a u^2+144 C_{10} a u v^2-64 C_{10} u^4-27 a v^4+16 u^3 v^2=0 \end{dmath}\end{Schunk} \end{framed} We use the \LaTeX{} {\it dmath} environment from the package {\it breqn} in case the solution needs to be broken across multiple lines. Since \reduce{} output line size may cause equations to be split over multiple lines and {\it odesolve} uses {\it eol=TRUE} we need to set the {\it eol=false} to avoid unnecessary splitting before {\it dmath} is called. %% %% Switches affecting odesolve %% \subsubsection{Switches affecting odesolve} \label{sec:ode-switches} Note that some switches can affect whether {\it odesolve} finds a solution. As an example, consider the Lagrange equation $v = 2uv' - a(v')^3$. If \textit{DIV} and \textit{INTSTR} are off and \textit{ALLFAC} is on, which are the defaults for these switches, no solution is found. Toggling these switches does produce a solution. \begin{framed} \begin{Schunk} \begin{Sinput} > ode.x <- odesolve(s3, eqn="v = 2u*df(v,u) - a*df(v,u)^3", + depvar="v", indvar="u", outfmt="latex", + switches=c(off="allfac, rounded",on="div,intstr"), + usermap=list(ident=c("arbparam"="P", "arbconst"="C"), + index=c("P"="_", "C"="_"))) > writeLines(c("\\begin{eqnarray}", + ltx.append.eol(unlist(ode.x@solution)), + "\\end{eqnarray}")) \end{Sinput} \begin{eqnarray} v=2 C_{11} P_{1}^{-1}+\frac{1}{2} P_{1}^3 a\\ u=C_{11} P_{1}^{-2}+\frac{3}{4} P_{1}^2 a\\ P_{1} \end{eqnarray}\end{Schunk} \end{framed} In this case ODESOLVE has returned the solution in parametric form. %% complex %% %% subS: redLatex %% \subsection{redLatex} \label{sec:latex} %% R2Latex short title: functions -> function %% set up the session for this section %% \begin{Scode}{label=ex1.1, echo=FALSE} %% sltx <- redStart(echo=TRUE) %% \end{Scode} With {\it redLatex} we can send expressions or the names of one or more \reduce{} variables, arrays or matrices to the \reduce{} process for display as \LaTeX. The function is also called by other functions to convert their results to \LaTeX{} when using the {\it outfmt=latex} argument. Note that because \reduce{} lists use braces as list delimiters, {\it redLatex} cannot produce correct \LaTeX{} output for lists. In this case use {\it red2Rlist} specifying {\it outfmt=text} to obtain an R list and then use {\it R2latex} to convert it to \LaTeX. \subsubsection{Expressions} \label{sec:expressions} {\it redLatex} can convert mathematical expressions written in R or \reduce{} syntax to \LaTeX: \begin{framed} \begin{Schunk} \begin{Sinput} > operators <- redExec(s3, c("operator !G, !T;", "korder kappa, !T;")) > writeLines(c("\\begin{eqnarray*}", + ltx.append.eol(redLatex(s3, c("!G(i,j)=kappa*!T(i,j)", "(x+y)**2"), + switches=c(off="exp"))[["tex"]]), + "\\end{eqnarray*}")) \end{Sinput} \begin{eqnarray*} G\left(i,j\right)=\varkappa T\left(i,j\right)\\ \left(x+y\right)^2 \end{eqnarray*}\end{Schunk} \end{framed} In order to treat $G$ and $R$ as functions it is necessary to first declare them as operators. Turning the EXP switch off ensures that $(x+y)^2$ is not expanded. Because the vector to display contains more than one element we need two provide a math array-type environment. \subsubsection{Arrays} \label{sec:arrays} {\it redLatex} can also print arrays of any dimension. \reduce{} has no print method for arrays - instead a loop over each element of the array is needed. {\it redcas} provides a simple method which prints each element optionally preceded by the array name and element indices. As an example, consider the tensor \begin{equation*} g_{ij} = \begin{bmatrix} -\omega_1u^{-2} & 0 & 0 & 0 \\ 0 & (ux)^2 & 0 & 0 \\ 0 & 0 & g_{1,1} * (sinx)^2 & 0 \\ 0 & 0 & 0 & \omega_2u^2 \end{bmatrix} \end{equation*} where $(t, x, y, z)$ is a coordinate system, u is an arbitrary constant and $\omega$ is a vector. In \reduce{} we define the tensor as follows: \begin{framed} \begin{Schunk} \begin{Sinput} > gm <- c("operator omega;", + "array g(3,3) ;", + "g(0,0) := -omega(1)*u^(-2);", + "g(1,1) := (u*z)^2;", + "g(2,2) := g(1,1) * (sin(x))^2;", + "g(3,3) := omega(2)*u^2;") > o4 <- redExec(s3, gm) \end{Sinput} \end{Schunk} \end{framed} Here the tensor is represented by an array. We now call {\it redLatex} to display $g$ as \LaTeX. Since we have a sparse tensor, we turn on the NERO switch to suppress printing the zeroes. \begin{framed} \begin{Schunk} \begin{Sinput} > g <- redLatex(s3, "g", use.names=TRUE, switches=c(on="nero"))[["tex"]] > writeLines(paste0(g, collapse=(";\\quad&"))) \end{Sinput} \end{Schunk} \begin{equation*} \begin{matrix} g(0,0)=\frac{-\omega\left(1\right)}{u^2};\quad&g(1,1)=u^2 z^2;\quad&g(2,2)=\sin\left(x\right)^2 u^2 z^2;\quad&g(3,3)=\omega\left(2\right) u^2 \end{matrix} \end{equation*} \end{framed} Here we see that \reduce{} variables with Greek letter names are automatically converted to the corresponding \LaTeX command. Displaying the indices for a tensor as arguments is not the standard notation. We now show how to define a mapping of the arguments to raised or lowered indices and to change the name of the $g$ tensor to $\Gamma$. We construct a named list containing named vectors {\it ident} and {\it index}. An {\it ident} element's name specifies the current name of an identifier while the value is the new name. An {\it index} element's name specifies the identifier to convert from arguments to indices and the value is a series of underscores and circumflexes to indicate lowered and raised indices, respectively. Since the index map is applied after the ident map, it must use the mapped identifier names. This list is passed as the {\it usermap} argument to {\it redLatex}: \begin{framed} \begin{Schunk} \begin{Sinput} > gmap <- list(ident=c(g="\\\\Gamma"), + index=c("\\\\Gamma"="_^", "\\\\omega"="_")) > g <- redLatex(s3, "g", use.names=TRUE, switches=c(on="nero"), + usermap=gmap)[["tex"]] > writeLines(paste0(g, collapse=(";\\quad&"))) \end{Sinput} \end{Schunk} \begin{equation*} \begin{matrix} \Gamma_{0}^{0}=\frac{-\omega_{1}}{u^2};\quad&\Gamma_{1}^{1}=u^2 z^2;\quad&\Gamma_{2}^{2}=\sin\left(x\right)^2 u^2 z^2;\quad&\Gamma_{3}^{3}=\omega_{2} u^2 \end{matrix} \end{equation*} \end{framed} We need to use four backslashes because the map is used as a regular expression which needs an escaped backslash and a further escaped backslash to get it into the string. Note that the usermap list does not have to have both elements. %% %% subS: Matrices %% \subsubsection{Matrices} \label{sec:matrices} \reduce{} has a print method for matrices so when {\it redLatex} is passed a \reduce{} matrix name this method is called: \begin{framed} \begin{Schunk} \begin{Sinput} > redmat <- c("operator omega;", + "gm:=mat((-omega(1)*u^2, u^2z^2),", + " (sin(x)^2u^2z^2, omega(2)u^2));") > m1 <- redExec(s3, redmat); > writeLines(redLatex(s3, "gm", mathenv="equation*", usermap=gmap)[['tex']]) \end{Sinput} \begin{equation*} \left(\begin{matrix}-\omega_{1} u^2&u^2 z^2\\\sin\left(x\right)^2 u^2 z^2&\omega_{2} u^2\end{matrix}\right) \end{equation*}\end{Schunk} \end{framed} This also works for plain text: \begin{framed} \begin{Schunk} \begin{Sinput} > writeLines(redLatex(s3, "gm", outfmt="text")[['tex']]) \end{Sinput} \begin{Soutput} [ 2 2 2 ] [ - omega(1)*u u *z ] [ ] [ 2 2 2 2] [sin(x) *u *z omega(2)*u ] \end{Soutput} \end{Schunk} \end{framed} \subsubsection{Using \LaTeX{} array-type environments} We may wish to display results from {\it redLatex} in a \LaTeX{} {\it array}, {\it eqnarray}, {\it align} or similar environment. In our example in section~\ref{sec:arrays}, we have space for multi-column display, but {\it redLatex} does only single column. We can use the same approach as that in section~\ref{sec:factorize-latex} to produce multi-column output. Here we will use the {\it align} environment. It is important to call {\it redLatex} without the {\it mathenv} argument and, since we have space, not to set the NERO switch. We then construct a vector for each row, insert column separators and apply the {\it ltx.append.eol} function: \begin{framed} \begin{Schunk} \begin{Sinput} > otex <- redLatex(s3, "g", use.names=FALSE, + usermap=list(ident=c(g="\\\\Gamma"), + index=c("\\\\Gamma"="_^", "\\\\omega"="_")))[["tex"]] > atex <- t(array(otex, c(4,4))) > atex <- ltx.append.eol( + unlist(lapply(1:4, + function(z){paste0(atex[z,], collapse=" & ")}))) > writeLines(c("\\[", "\\begin{array}{llll}", + atex, + "\\end{array}", "\\]")) \end{Sinput} \[ \begin{array}{llll} \frac{-\omega_{1}}{u^2} & 0 & 0 & 0\\ 0 & u^2 z^2 & 0 & 0\\ 0 & 0 & \sin\left(x\right)^2 u^2 z^2 & 0\\ 0 & 0 & 0 & \omega_{2} u^2 \end{array} \]\end{Schunk} \end{framed} %% %% sub: switch handling %% \subsection{Switch handling} \label{sec:switch-handling} All {\it redcas} functions which support the {\it switches} argument use the functions {\it swset} and {\it swreset} to set desired switch states for the duration of the {\it redcas} function's execution. Both of these functions are exported and can be called by the user to set switch states for as long as needed and restore them as necessary. Suppose we wish to make multiple calls to {\it odesolve} with the switches DIV and INTSTR off and ALLFAC\footnote{odesolve is currently not vectorized and the default states of these switches can lead to no solution be found when one exists.} on we call {\it swset} as follows: \begin{framed} \begin{Schunk} \begin{Sinput} > toggled <- swset(s3, c(on="div, intstr", off="allfac"), swlist="demo") > print(toggled) \end{Sinput} \begin{Soutput} [1] "intstr" "allfac" \end{Soutput} \end{Schunk} \end{framed} The elements of the vector {\it toggled} are the names of the switches which were toggled. The argument {\it swlist} names a \reduce{} list in which to store the names of the toggled switches. After completing the calls to {\it odesolve} we can, if desired, restore the switches to their previous state: \begin{framed} \begin{Schunk} \begin{Sinput} > swreset(s3, swlist="demo") \end{Sinput} \end{Schunk} \end{framed} If we use the default value for the {\it swlist} argument we should avoid using the {\it switches} argument until after calling {\it swreset} because it uses the default. We should also avoid using {\it redExec} to call the \textit{ON} or \textit{OFF} statements as mixing the two methods can lead to unexpected results. %% %% C: Conversion functions %% \chapter{Conversion functions} \label{cha:conversion-functions} This chapter discusses the {\it redcas} functions which convert \reduce{} output into corresponding R objects. With the exception of {\it R2latex} and {\it red2Rarray}, all conversion functions convert or transform \reduce{} output using only R code. {\it R2latex} uses \reduce{} as a translation tool from plain text to \LaTeX. {\it red2Rarray} requires some specific formatting of the arrays to be converted and so needs to call \reduce. %% %% subS: R2latex %% \section{R2latex} \label{sec:r2latex} This function uses \reduce{} to transform a numeric, character or expression vector, a data frame or a possibly nested list to \LaTeX{} and returns the output in a list of the same structure. List elements of type other than those mentioned are returned unchanged. {\it R2latex} uses the {\it redLatex} function to do the transformation. Note that for vectors {\it redLatex} can be used directly. \begin{framed} \begin{Schunk} \begin{Sinput} > op <- redExec(s4, "operator c, f;") > tmap <- list(ident=c(abc="a"), index=c(f="_")) > t1 <- R2latex(s4, list("y=c(3) + c(2)*x + e**x", + data.frame(v1=c("f(1)**(-1)", "exp(-i*pi)"), + v2=c("exp(i*pi)", "f(2)**2"), + v3=c("pi", "gamma")), + list(expression(f(1)**(-1), f(2)**2), + "1/abc^6+1/abc^5"), + matrix(c("sqrt(x)", "x**y", "gamma", "pi"), + nrow=2, ncol=2)), + usermap=tmap) > str(t1) \end{Sinput} \begin{Soutput} List of 4 $ : chr "y=c\\left(3\\right)+c\\left(2\\right) x+e^x" $ :'data.frame': 2 obs. of 3 variables: ..$ v1: chr [1:2] "\\frac{1}{f_{1}}" "-1" ..$ v2: chr [1:2] "-1" "f_{2}^2" ..$ v3: chr [1:2] "\\pi" "\\gamma" $ :List of 2 ..$ : chr [1:2] "\\frac{1}{f_{1}}" "f_{2}^2" ..$ : chr "\\frac{a+1}{a^6}" $ : chr [1:2, 1:2] "sqrt(x)" "x**y" "gamma" "pi" \end{Soutput} \end{Schunk} \end{framed} Note that the matrix is returned without conversion because this type is not supported by {\it R2latex}. We can display the data frame in a math array environment by collapsing its rows to produce a single vector with separator, and use {\it ltx.append.eol} to add end of line commands: %% tvec <- character(dim(t1[[2]])[1]) %% for (i in 1:dim(t1[[2]])[1]) tvec[i] <- paste0(t1[[2]][i,], collapse=" & ") %% tvec <- ltx.append.eol(tvec) \begin{framed} \begin{Schunk} \begin{Sinput} > tvec <- ltx.append.eol(apply(t1[[2]],1,paste0,collapse=" & ")) > writeLines(c("\\[", "\\begin{array}{lll}", tvec, "\\end{array}", "\\]")) \end{Sinput} \[ \begin{array}{lll} \frac{1}{f_{1}} & -1 & \pi\\ -1 & f_{2}^2 & \gamma \end{array} \]\end{Schunk} \end{framed} %% %% subS: red2Rarray %% \section{red2Rarray} \label{sec:red2rarray} This function converts \reduce{} arrays to R arrays. The arrays must exist in the \reduce{} session because {\it red2Rarray} uses the \reduce{} operator GETTYPE to determine which elements of the input are arrays and the operator LENGTH to get their dimensions. As an example, consider the following array with 3 dimensions of length 2 each: \begin{equation*} \begin{array}{l|rr} i, j, 1 & & \\ \hline & i, 1, k & i, 2, k \\ 1, j, k & 111 & 121 \\ 2, j, k & 211 & 221 \end{array} \hspace{1cm} \begin{array}{l|rr} i, j, 2 & & \\ \hline & i,1,k & i, 2, k \\ 1, j, k & 112 & 122 \\ 2, j, k & 212 & 222 \end{array} \end{equation*} First we build this array in \reduce{}, convert it to R in plain text format and print. \begin{framed} \begin{Schunk} \begin{Sinput} > a3d <- redin('array a3d(1,1,1) ; + for i:=1:2 do for j:=1:2 do for k:=1:2 do + a3d(i-1,j-1,k-1) := 100*i + 10*j + 1*k ;') > a3d.red <- redExec(s4, a3d) > a3d.R <- red2Rarray(s4, "a3d")[[1]] > mode(a3d.R) <- "numeric" > a3d.R \end{Sinput} \begin{Soutput} , , 1 [,1] [,2] [1,] 111 121 [2,] 211 221 , , 2 [,1] [,2] [1,] 112 122 [2,] 212 222 \end{Soutput} \end{Schunk} \end{framed}With some transformations we can present results of the conversion in \LaTeX{} form with the two sub-arrays side by side. We need to adjust for the fact that \reduce{} array indices are zero-based. We also need to use the zero space argument to the \LaTeX{} end of line command in order to avoid the \begin{verbatim} ! Illegal unit of measure (pt inserted) \end{verbatim} error which would otherwise be triggered by the brackets in the R output. \begin{framed} \begin{Schunk} \begin{Sinput} > a3d.ltx <- red2Rarray(s4, "a3d", outfmt="latex")[[1]] > k1 <- gsub(" +", " & ", capture.output(print(a3d.R[,,1]), type="output")) > k2 <- gsub(" +", " & ", capture.output(print(a3d.R[,,2]), type="output")) > writeLines(c("\\[", "\\begin{array}{lrr}", + ltx.append.eol(k1, ,eol="\\\\[0pt]"), "\\end{array}", + "\\hspace{1cm}", + "\\begin{array}{lrr}", + ltx.append.eol(k1, ,eol="\\\\[0pt]"), "\\end{array}", + "\\]")) \end{Sinput} \[ \begin{array}{lrr} & [,1] & [,2]\\[0pt] [1,] & 111 & 121\\[0pt] [2,] & 211 & 221 \end{array} \hspace{1cm} \begin{array}{lrr} & [,1] & [,2]\\[0pt] [1,] & 111 & 121\\[0pt] [2,] & 211 & 221 \end{array} \]\end{Schunk} \end{framed} %% %% subS: red2Rfn %% \section{red2Rfn} \label{sec:red2rfn} This function converts algebraic expressions returned by \reduce{} into R functions with an argument for each variable in the expression. As an example consider the output of {\it redFunc} for integration (INT) and differentiation (DF). \begin{framed} \begin{Schunk} \begin{Sinput} > flist <- c('int','df') > plist <-list(c('sin(x)**4','x'), c('y^(3*x)', 'x', 'y')) > isx <- redFunc(s4, func=flist, param=plist) > for (i in names(isx)) writeLines(isx[[i]]) \end{Sinput} \begin{Soutput} 3 - 2*cos(x)*sin(x) - 3*cos(x)*sin(x) + 3*x --------------------------------------------- 8 3*x 3*y *(3*log(y)*x + 1) ------------------------- y \end{Soutput} \end{Schunk} \end{framed} The output is in the ``natural'' form which is why we used {\it writeLines} to display the result. In order to convert to a function we need to execute with NAT off: \begin{framed} \begin{Schunk} \begin{Sinput} > (isx <- redFunc(s4, func=flist, param=plist, switches=c(off='nat'))) \end{Sinput} \begin{Soutput} $int [1] "( - 2*cos(x)*sin(x)**3 - 3*cos(x)*sin(x) + 3*x)/8" $df [1] "(3*y**(3*x)*(3*log(y)*x + 1))/y" \end{Soutput} \begin{Sinput} > isx.fn <- red2Rfn(unlist(isx), name=c("xint", "xdf")) > isx.fn \end{Sinput} \begin{Soutput} $xint function (x) { return((-2 * cos(x) * sin(x)^3 - 3 * cos(x) * sin(x) + 3 * x)/8) } $xdf function (y, x) { return((3 * y^(3 * x) * (3 * log(y) * x + 1))/y) } \end{Soutput} \end{Schunk} \end{framed} We can assign names to the functions either in the {\it redFunc} or {\it red2Rfn} call. Names assigned by {\it redFunc} are used in {\it red2Rfn}. To make the functions available in the current environment we can use the following: \begin{framed} \begin{Schunk} \begin{Sinput} > for (f in names(isx.fn)) assign(f,isx.fn[[f]]) \end{Sinput} \end{Schunk} \end{framed} We used the names {\it xint} and {\it xdf} to avoid clashing with existing R functions. %% %% subS: red2Rlist %% \section{red2Rlist} \label{sec:red2Rlist} {\it red2Rlist} takes as input a character vector containing \reduce{} output and converts any \reduce{} lists found in the vector to R lists. \reduce{} lists, which may be recursive, are enclosed in braces (\{, \}). For this reason {\it red2Rlist} produces only plain text output because of the difficulty distinguishing \LaTeX{} braces from \reduce{} list braces. See below for how to obtain \LaTeX{} output. As an example of converting a \reduce{} list, consider the following character vector which contains arbitrary text, a \reduce{} informational message and three \reduce{} lists of various depths. The lists are outputs from the {\it redSolve} or {\it odesolve} functions. \begin{framed} \begin{Schunk} \begin{Sinput} > writeLines(redls) \end{Sinput} \begin{Soutput} Some arbitrary text and list starts here: {{x=2.21*i + 1.77,y= - 2.21*i + 1.77,z= -3.54}, {x=0.58*i - 1.27,y= - 0.58*i - 1.27,z=2.54}, {x= - 0.58*i - 1.27,y=0.58*i - 1.27,z=2.54}, {x= - 2.21*i + 1.77,y=2.21*i + 1.77,z=-3.54}} and we have text at the end$ *** depend v , u {v=arbconst(1)/e**(a*u)}$ {{q=myfun1(p^2+1,exp(r)), p=cos(r), r=myf2(a,b,c)},{ q=myfun1(p^2+1,exp(-r)), p=cos(-r), r=myf2(a,b,c,d+e,f)}} \end{Soutput} \end{Schunk} \end{framed} Calling {\it red2Rlist} on this input returns an R list with three elements, one for each \reduce{} list in the input. Notice that the structure of the R lists is identical to that of the \reduce{} lists. \begin{framed} \begin{Schunk} \begin{Sinput} > str(Rls <- red2Rlist(redls)) \end{Sinput} \begin{Soutput} List of 3 $ :List of 4 ..$ :List of 3 .. ..$ : chr "x=2.21*i + 1.77" .. ..$ : chr "y= - 2.21*i + 1.77" .. ..$ : chr "z= -3.54" ..$ :List of 3 .. ..$ : chr "x=0.58*i - 1.27" .. ..$ : chr "y= - 0.58*i - 1.27" .. ..$ : chr "z=2.54" ..$ :List of 3 .. ..$ : chr "x= - 0.58*i - 1.27" .. ..$ : chr "y=0.58*i - 1.27" .. ..$ : chr "z=2.54" ..$ :List of 3 .. ..$ : chr "x= - 2.21*i + 1.77" .. ..$ : chr "y=2.21*i + 1.77" .. ..$ : chr "z=-3.54" $ :List of 1 ..$ : chr "v=arbconst(1)/e**(a*u)" $ :List of 2 ..$ :List of 3 .. ..$ : chr "q=myfun1(p^2+1,exp(r))" .. ..$ : chr " p=cos(r)" .. ..$ : chr " r=myf2(a,b,c)" ..$ :List of 3 .. ..$ : chr "q=myfun1(p^2+1,exp(-r))" .. ..$ : chr " p=cos(-r)" .. ..$ : chr " r=myf2(a,b,c,d+e,f)" \end{Soutput} \end{Schunk} \end{framed} To produce a list formatted as \LaTeX{} we call {\it R2latex} on the output of {\it red2Rlist}. Since we will display the result in an {\it eqnarray} environment we use the {\it tochar=TRUE} argument so that the sublists containing only character elements are converted to character vectors and we can add new line commands. For simplicity consider the first sublist of the last element of the previous example with the definitions of $q$, $p$ and $r$. The {\it R2latex} argument {\it eol} allows us to specify that an end of line command be appended to all but the last element\footnote{using {\it ltx.append.eol}, which adds end of line commands to all but the last element requires a vector as input. Since the default output from red2Rlist contains only vectors of length one, {\it ltx.append.eol} has no effect without setting {\it tochar=TRUE}.}. First we show the \LaTeX{} code: \begin{framed} \begin{Schunk} \begin{Sinput} > writeLines( + lx <- c("\\begin{eqnarray*}", + R2latex(s4, red2Rlist(redls[8:9], tochar=TRUE)[[1]], eol=TRUE), + "\\end{eqnarray*}")) \end{Sinput} \begin{Soutput} \begin{eqnarray*} q=myfun1\left(p^2+1,e^r\right)\\ p=\cos\left(r\right)\\ r=myf2\left(a,b,c\right) \end{eqnarray*} \end{Soutput} \end{Schunk} \end{framed} We can display this in typeset form: \begin{framed} \begin{Schunk} \begin{Sinput} > writeLines(lx) \end{Sinput} \begin{eqnarray*} q=myfun1\left(p^2+1,e^r\right)\\ p=\cos\left(r\right)\\ r=myf2\left(a,b,c\right) \end{eqnarray*}\end{Schunk} \end{framed} %% %% subS: Miscellaneous %% \section{Miscellaneous conversion functions} \label{sec:misc-conv-funct} {\it redcas} exports several conversion functions which are used internally as these could be useful in processing output produced directly in \reduce{}. For completeness the functions and a brief description of their purpose follows. \begin{description} \item [dlmMatch]: searches a character vector for matching delimiter pairs (brace, bracket, parenthesis) and returns a data frame with the coordinates of matching open/close pairs and the level of nesting. \item [fnMatch]: searches a character vector for function calls and returns a list containing a character vector of the function calls and a character vector of the function calls with commas replaced by a user-specified character. This is used by {\it red2Rlist} to prevent function calls being interpreted as lists. \item [redlsExtract]: searches a character vector for \reduce{} lists and returns a list with one character vector element for each \reduce{} list found. \item [sublist2char]: searches a list for elements containing only character types and returns a list with these elements converted to character vectors. \item [redDropOut]: removes blank lines or the submit block end marker from the REDUCE output. \item [redExpand]: a vector of commands to send to \reduce{} may contain the name of one or more files containing \reduce{} commands. {\it redExpand} returns a vector containing the commands up to the element containing the file name, the contents of the file and the elements following the file name. \item [redSplitOut]: converts a vector of \reduce{} output into a list containing a vector of commands and a vector of command output. \end{description} %% %% Bibliography %% \begin{thebibliography}{1} \bibitem{REDUCE} REDUCE Developers. \newblock {\href{https://reduce-algebra.sourceforge.io}{\em What is REDUCE?} [Online; accessed 2026-10-10]} \bibitem{get-reduce} REDUCE Developers. \newblock {\href{https://reduce-algebra.sourceforge.io/obtaining.html}{\em How to Obtain and Run REDUCE} [Online; accessed 2026-10-10]} \bibitem{manual} REDUCE Developers. \newblock {\href{https://reduce-algebra.sourceforge.io/manual/manual.html}{\em \reduce{} User's Manual, Revision 7419, September 26, 2026 } [Online; accessed 2026-10-10]} \bibitem{solve} REDUCE Developers. \newblock {\href{https://reduce-algebra.sourceforge.io/manual/manualse44.html#x56-1000007.17}{\em The SOLVE Operator, Revision 7419, September 26, 2026} [Online; accessed 2026-10-10]} \bibitem{redDf} REDUCE Developers. \newblock {\href{https://reduce-algebra.sourceforge.io/manual/manualse34.html#x44-830007.7}{\em The DF Operator, Revision 7419, September 26, 2026} [Online; accessed 2026-10-10]} \bibitem{odesolve} REDUCE Developers. \newblock {\href{https://reduce-algebra.sourceforge.io/manual/manualse167.html#x190-113100020.41}{\em ODESOLVE: Ordinary Differential Equation Solver, Revision 7419, September 26, 2026} [Online; accessed 2026-10-10]} \bibitem{switch} REDUCE Developers. \newblock {\href{https://reduce-algebra.sourceforge.io/switches.html}{\em Switch Summary, Page last modified on Tuesday 2nd January 2024} [Online; accessed 2026-10-10]} \bibitem{tutorials} David Stoutemyer, Arthur Norman, Francis Wright \newblock {\href{https://reduce-algebra.sourceforge.io/tutorials.html}{\em Tutorials, Page last modified on Thursday 1st October 2026} [Online; accessed 2026-10-10]} %% \bibitem{Reuter-EDEO} %% G. E. H. Reuter. %% {\em Elementary Differential Equations \& Operators}. Routledge \& Kegan Paul, first %% edition, 1958. \end{thebibliography} \appendix %% %% C: Appendices %% \chapter{Appendices} %% %% S: Known issues %% \section{Known issues} \label{sec:known-issues} \subsection{MacOS/Intel/\reduce{} 6866} \label{sec:macos-6866} For 6866/CSL on MacOS (Intel) some calculations can cause \reduce{} to abort because of an issue with garbage collection. This has been reported to the \reduce{} developers and is specific to CSL. This issue can be mitigated by using the $-k$ option to allocate more memory to the CSL process. In the case where we found the issue, test program 07-redExecLong.R, allocating 2.5GB worked: \begin{verbatim} sessionID <- redStart("csl", options="-k2.5g") \end{verbatim} If you encounter this issue you will have to determine what amount of memory suffices. \subsection{Passing FACTOR, MODULAR in switches argument} \label{sec:pass-fact-switch} Passing FACTOR in the {\it switches} argument leads to an error: \begin{verbatim} ***** nil invalid as kernel Stopping. No list called 'sw!-to!-toggle' exists in REDUCE session. \end{verbatim} but turning on factor in REDUCE and calling R2latex works. Alternatively set EXP to off. Passing MODULAR in the {\it switches} argument leads to an error: \begin{verbatim} ***** Zero divisor Stopping. dlmMatch: No delimiter '{' found. redlsExtract: stopping. ***** No switches specified Stopping. No list called 'asltx!-to!-toggle' exists in REDUCE session. No list called 'redltx!-sw!-set' exists in REDUCE session. \end{verbatim} Curiously, the state of MODULAR is changed. The issue here is that the modulus must first be set using {\it redExec} to call the SETMOD declaration first: \begin{verbatim} redExec(id, "setmod n;") \end{verbatim} \subsection{Error displaying omicron in \LaTeX} \label{sec:csl-error-omicron} When producing \LaTeX{} output \reduce{} converts variables which are Greek letter names to the corresponding \LaTeX{} command. An exception is {\it omicron} which produces the following error message: \begin{verbatim} ***** unknown print item \end{verbatim} Any subsequent output as \LaTeX{} also produces this error. The only solution is to close the session. If PSL is run independently of {\it redcas} and the package TMPRINT is not loaded, this is not an issue. \subsection{Long equations in odesolve} \label{sec:long-equat-odesolve} \subsection{trode option in odesolve} \label{sec:trode-odesolve} If the option \textit{trode} is specified and \textit{verbose} is not, ODESOLVE writes the first line of \textit{trode} messages on a line starting with a command number. \subsection{\reduce{} is mostly case insensitive} \label{sec:case-insensitive} By default \reduce{} ignores case in identifiers and converts them to lower case on output. This can lead to issues when using mixed case for a \reduce{} variable name and then, in R, searching the output using the mixed case version. One way to avoid this is to avoid using upper case. However, if upper case letters in \reduce{} code are escaped using {\it !} they are preserved. When referring to these variables in R, for example in the {\it usermap} argument, do not escape upper case. Another example is when producing \LaTeX{} to produce Greek upper case letters. \reduce{} converts lower case names of Greek letters to the lower case Greek letter, e.g. {\it gamma} to $\gamma$, while capitalized names are converted to the capital letter, eg {\it Gamma} to $\Gamma$. The feature \reduce{} provides for using non-standard characters in variable names, escaping the character with an exclamation mark, can be used to keep the case of the following character: \begin{framed} \begin{verbatim} 13: write gamma, " ", Gamma ; gamma gamma 14: write gamma, " ", !Gamma ; gamma Gamma \end{verbatim} \end{framed} Note that using {\it redLatex} or {\it R2latex} to convert mathematical expressions to LaTeX upper case characters and braces in the expression must be escaped. \subsection{redin, lstlisting and Sweave don't mix} \label{sec:redin-lstlisting-nono} Using the {\it redin} function in an {\it lstlisting} environment which uses text marker line ranges with the {\it includerangemarker=false} options to drop the {\it Schunk, Sinput} and {\it Soutput} begin and end commands causes the exclusion of these markers to fail. %% %% S: Testing %% \newpage \section{Testing} \label{sec:testing} The aim of testing is to prove that \reduce{} output is correctly transformed to corresponding R objects. No attempt is made to test the correctness of the \reduce{} output as \reduce{} itself provides extensive testing. Since it is unreasonable to expect CRAN to provide a \reduce{} installation, package tests which execute \reduce{} code are skipped when no \reduce{} executables are found. Prior to CRAN submission all tests are run for various combinations of R and \reduce{} versions for both Linux (5.15 and 6.6) and MacOS (Intel and arm M5). \subsection{Test categories} The {\it redcas} package comprises a small number of functions which execute \reduce{} code but the majority use only R. Tests of functions which execute \reduce{} code are skipped if no \reduce{} executable is found. There are 1004 tests grouped as shown in Table~\ref{tab:tests}. \begin{table}[h] \caption{Tests} \label{tab:tests} \begin{center} \begin{tabular}{|l|r|r|r|r|} \hline Group & Tests & CSL & PSL & R \\ \hline 01 Finding Reduce executables & 11 & 0 & 0 & 11 \\ 02 Session handling & 24 & 0 & 0 & 24 \\ 03 Output handling & 20 & 0 & 0 & 20 \\ 04 Output: file not found & 6 & 3 & 3 & 0 \\ 05 Execution & 123 & 54 & 37 & 32 \\ 06 Execution: prompts & 5 & 5 & 0 & 0 \\ 07 Execution: long-running & 4 & 4 & 0 & 0 \\ 08 Execution: Many redExec calls & 16 & 8 & 8 & 0 \\ 09 Arrays & 72 & 36 & 36 & 0 \\ 10 Expressions & 36 & 18 & 18 & 0 \\ 11 asltx from REDUCE & 52 & 26 & 26 & 0 \\ 12 redLatex & 109 & 64 & 37 & 8 \\ 13 Bug fixes & 22 & 15 & 7 & 0 \\ 14 redSolve & 88 & 40 & 31 & 17 \\ 15 redcas Utils & 170 & 44 & 0 & 126 \\ 16 odesolve & 76 & 39 & 0 & 37 \\ 17 red2Rfn & 24 & 0 & 0 & 24 \\ 18 redFunc & 68 & 34 & 34 & 0 \\ 19 Calculus & 45 & 15 & 0 & 30 \\ 20 Polynomial & 33 & 25 & 0 & 8 \\ \hline All Groups & 1004 & 430 & 237 & 337 \\ \hline \end{tabular} \end{center} \end{table} The R column shows the number of tests which do not require a \reduce{} installation. The CSL and PSL columns show the number of tests which would be executed if the corresponding dialect is present and a \reduce{} session can be started. Groups for which the number of tests in both the CSL and PSL columns is non-zero, are run for each dialect which is present. Groups for which the number of tests in the CSL column is non-zero and in the PSL column zero, are only executed for one dialect. In this case if both are present only CSL is used. Some tests require only R for execution and these are always run. Since CRAN does not have a \reduce{} installation, these are the only tests which are run there. Therefore we recommend installing the tests and executing locally. In the directory where the tests are run, the file {\it 99-test-results.Rout} provides a summary summary test results for each group and overall: \begin{framed} \begin{verbatim} Group: All Groups Tests: 1004 Passed: 337 Failed: 0 Skipped: 667\end{verbatim} \end{framed} If any tests have failed, this program calls {\it stop()} after printing the summary to draw attention to the failures. In this case the transcript is named {\it 99-test-results.Rout.fail}. \subsection{Pre-CRAN testing and results} \label{sec:pre-cran-testing} Prior to submission to CRAN this release has been tested so that test groups requiring \reduce{} are also run to ensure everything passes. Table~\ref{tab:releases-tested} shows the combinations of R and \reduce{} releases tested for Linux kernel 6.6 (L6), Linux kernel 5.15 (L5), MacOS Intel 12 (Mi) and MacOS arm 26 (Ma). \begin{table}[h] \begin{center}\caption{R and \reduce{} releases tested} \label{tab:releases-tested} \begin{tabular}{l|lllll}\hline & 7335 & 7131 & 6866 & 6860 & 6658 \\ \hline R-devel & - & L5 & - & L5 & L5 \\ R-4.6.1 & L6 & L5 & Mi, Ma & L5 & L5, Mi, Ma \\ R-4.5.3 & - & L5 & - & L5 & L5, - \\ R-4.5.1 & - & - & Mi & L5 & L5, Mi \\ \hline \end{tabular} \end{center} \end{table} Note that revision 7335 is named as Snapshot 2026-03-08 on the \reduce{} website. Prior snapshots are named for the revision. All tests passed except for the following, all of which also fail when run directly in reduce{}: \begin{description} \item [ 6866/CSL on MacOS (Intel)] one test, red7ExeLong-001 failed on the issue reported in section~\ref{sec:macos-6866} for a work-around. \item [ 6658 Linux] CSL/PSL: redLtxTyp-rok-003/007, redLtxTyp-gen-003/012, 007/016. Variable {\it gamma} is rendered as $\Gamma$ in \LaTeX. Corrected in later versions of REDUCE. \item [ 6658 MacOS Intel and arm] CSL: redLtxTyp-rok-003, redLtxTyp-gen-[003,007]. Variable {\it gamma} is renedered as $\Gamma$ in \LaTeX. Corrected in later versions. \end{description} \subsection{Post-installation testing} We recommend executing the tests after installation. While {\it 99-test-results.Rout} shows the expected and actual values if the test fails, it is not very convenient for checking exactly how the two differ. For each set of tests there is an RData file containing two lists, expect and actual. To find this, open the Rout file for the failing category - the RData file name is in the statement which prints and saves the results, for example, in {\it 170-many-input.Rout} the line \begin{verbatim} > print(save.results('redMany',expect,actual)) \end{verbatim} indicates that {\it redMany.RData} contains the lists. %% %% S: Producing this vignette %% \section{Producing this vignette} \label{sec:prod-this-vign} Since it is unreasonable to expect \reduce{} to be installed on CRAN, the Sweave step for this vignette has been executed prior to submission outside the package directory and the resulting \LaTeX{} file copied to the {\it vignettes} directory as {\it Using.redcas.Rnw}. The actual {\it Rnw} file is copied as {\it Using.redcas.Rnw.src} and the output of {\it Stangle} as {\it Using.redcas.R.src}. \end{document} %% %% -- End of document %%