Read mathcodec++_subset.fm text version

The Compilable Mathematica Subset of MathCode C++

Appendix A The Compilable Mathematica Subset of MathCode C++

Note that the Compilable Subset varies from one release to another. Please read the Release Notes attached to your MathCode installation for the most actual information The MathCode1 system provides facilities to translate a subset of the Mathematica language to compiled programs in strongly typed languages such as C++ or Fortran90, and in the future other languages like Java, etc. This subset includes most elementary functions and operators that compute numeric values, but excludes symbolic and computer algebra related functions that compute symbolic expressions. However, it is possible to evaluate a symbolic expression (which may contain operations such as simplification, symbolic differentiation, substitution etc.) and generate executable numeric code from the symbolic expression resulting from this evaluation, provided that the resulting expression(s) only contain operators and functions in the compilable Mathematica subset described here. The arithmetic model used in the compilable Mathematica subset is specified by the IEEE Standard for Binary Floating Point Arithmetic, IEEE Standard 754.

A.1 Operations not in the Compilable Subset

The following is a short list of those Mathematica operations and functions that are not in the compilable subset. Since the primary reason to generate compiled code is to get high performance of numeric computing code, the operations in the compilable subset are oriented towards efficient computing on numbers and arrays. · Pattern matching is not supported, except for the simple case of function argument patterns like arg1_Integer or arg2_Real, which are handled by the static type system of the target language. However, overloading of functions is not supported by 1. This chapter describes the MathCode C++ release 1.3, February 2006

The Compilable Mathematica Subset of MathCode C++

the current version of the code generator, e.g. there may not be two functions with the same name and arguments, one having Integer typed arguments and the other having Real typed arguments. · When a function is declared, its arguments must be specified as single variable names, separated with commas. As an example, node patterns like Name[a_,b_] below are not permitted.

· Arbitrary precision numbers and arithmetic is not supported. Numbers and arithmetic operations are converted to either IEEE double precision floating point arithmetic or 32bit (or better) integer arithmetic. · Symbolic operations that give symbolic expressions as results are not included. However, such operations can be compiled if they are expanded to expressions in the compilable subset before code generation. Such expansion can handle many common cases of symbolic operations. · Negative array indexing relative to the end of arrays are not in the compilable subset. apart from the special cases of negative constant indices, e.g. as in arr[[-3]], array ranges, e.g. as in arr[[1|-n]], and submatrix extraction, as described on page 113. To index from the end of an array, FromEnd should be used with a positive argument. · String operations are not included. except for assignment to scalar variables and argument passing. · Input/Output operations are not included, apart from a simple Print operation. · Certain list (i.e. array) operations, specifically certain operations that change the size of arrays or are very inefficient, are not included in the set of functions mentioned in this appendix. Such functions can be added by the user e.g. in the system module. · The Return[] function is not included. Therefore loop constructs like For, While cannot be used as expressions returning values. · Some procedural style statements cannot be used within a CompoundExpression used in value context within arithmetic expressions. For instance, a=a+(While[i&lt;10,i=i+1];5) cannot be translated. The expression a=a+(c=3;5), however, can be translated to C++. More details on nested constructs are given below. · There are also a number of builtin standard Mathematica functions with numeric arguments and results which are not availiable outside Mathematica, but can be considered as beloning to the compilable subset in the sense that callback stub functions

The Compilable Mathematica Subset of MathCode C++

(via MathLink) for these Mathematica functions can be generated.

A.2 Predefined Functions and Operators

Expression operators listed in this section are predefined by the code generator and will be translated correctly from Mathematica into the target language (e.g. C++ or Fortran90) without any additional type declarations. Almost all operators belong to the compilable expression subset, i.e. all value-returning operators and predefined or user-defined functions without side effects (i.e. functions that do not change global variables or perform input/output). The reason to impose the condition of calls to side-effect free functions is that expressions can be re-ordered and common subexpressions removed in the generated code, in order to make execution more efficient. Another order in assigning and referencing global variables or performing input/output usually results in different, often unintended, program behavior. However, some restricted cases of side-effects can be re-ordered without changing the meaning of the program. One such case is when the elements of an array are assigned once, and independently of each other, and not used in the same expression. Such restricted side-effects are allowed for functions in the compilable expression subset. The code generator does not check the condition of side-effect freeness--this is the user's responsibility. All operators and functions in the compilable expression subset also belong to the compilable subset, which also contains control expressions (If, While, For, etc.), assignment statements and functions with side effects. All real and integer constants naturally belong to the compilable expression subset, except for the special case of arbitraryprecision values. Some operators and functions can be applied to arrays or return arrays as values. The current version of the compilable subset is oriented toward operations on real numbers and integers, and arrays containing such numbers. The basic mathematical functions usually found in C/C++ or Fortran are provided. In Mathematica there are also a number of special mathematical functions such as BesselJ[], Gamma[], etc. If the user has access to an implementation of such a function in C/C++ or Fortran, or a linkable object code library containing this function, it can be declared as an external function and thus automatically included in the compilable subset. Alternatively, such functions can be approximated by externally compiled interpolating functions or declared as callbacks which makes the code generator produce stub functions, e.g in C/C++, that perform callback to Mathematica. Since efficient computation based on mathematical models so far has been the main application of MathCode, the compilable Mathematica subset does not include string operations, file input, formatted file output and certain mapping and list operations.

The Compilable Mathematica Subset of MathCode C++

A.2.1

Statements and Value Expressions

In standard Mathematica all predefined and user-defined functions can appear as an argument of another function. Correctness of such constructs is tested during code interpretation. In procedural languages, such as C++ and Fortran, procedural statements cannot be used within expressions. Also, the type of allowed expressions is restricted. In order to compile Mathematica code to procedural language some restrictions in using statements and expressions are introduced. In the descriptions below &quot;stmt&quot; means that corresponding Mathematica expressions are used as statements. In the compiled subset they do not return values, their returned values cannot be used, and they cannot be applied where values are expected. In the compiled set there is no Null value. In descriptions below &quot;expr&quot; means that corresponding Mathematica expressions are used as values (l-value or r-value). These expressions must return some value when evaluated. This value cannot be Null. The word &quot;exprs&quot; means one or more expressions separated by a comma. Some Mathematica constructs - Set, If, Which, CompoundExpression - can appear both as statements and as values. Some specific restrictions on their use are described below.

A.2.2

Function Call

Operator funcname[exprs] Arg type(s) ... Result type(s) ...

Spec syntax

All user-defined functions which have been type declared according to the typing rules for typed Mathematica belong to the compilable subset. The same is true for functions declared as ExternalFunction or ExternalProcedure, and exist in a library or an object code file that can be linked together with the generated code in C++ or Fortran90. Compilable subset functions may only contain operations that belong to the compilable subset, or may contain non-subset operations inside bodies of functions compiled with the EvaluateFunction option, which will expand into compilable subset operations. Functions with multiple return arguments can be compiled if they are type declared. Such a function can only be used in the right hand side of an assignment statement in which the left hand side has to be a list of variables. Thus, a call that returns multiple values can for example look like this:

{a, b, c} = F[x+y, 3.4];

Calls to functions with no return arguments and functions with more than one return arguments are considered as statements (stmt).

The Compilable Mathematica Subset of MathCode C++

Calls to functions returning one argument are considered as expressions (expr).

In addition, functions can be defined as interpolating functions by using the Mathematica function FunctionInterpolation. Code generation is limited to interpolation function objects of one or two variables. Below is an example of a definition of an interpolation function.

A value can be returned from one of the above scope constructs when it occurs as a function body or when it is used in value context within an expression. The body is restricted as

The Compilable Mathematica Subset of MathCode C++

follows: · If a function does not return any value, the body is a statement. If it is a CompoundExpression statement, then all (possibly nested) elements in CompoundExpression must be statements. In the following example two nesting levels of CompoundExpression are demonstrated:

· If a function returns one or more values, the body is an expression. If it is a CompoundExpression construct, then the last (possibly nested) element in CompoundExpression must be an expression. All other components must be statements. In the following example two nesting levels of CompoundExpression are demonstrated; note that t+4 is an expression.

The control statements can appear wherever a statement is allowed, in which case they do not return any value. Spec syntax s1; s2;... Operator Arg type(s) Result type(s) none none none none none none none CompoundExpression [stmts] statements For [start-stmt, boolean-test-expr, incr-stmt, body-stmt] special While [boolean-test-expr, body-stmt] special If [boolean-test-expr, true-stmt, false-stmt] special Which [boolean-test-expr1, stmt1 boolean-test-expr2, stmt2,...] special Break [] Do [expr, iterators] special

CompoundExpression (a sequence of expressions separated by semicolon), Which and If can also appear as arithmetic expression. See &quot;Arithmetic expression&quot; for details.

The Compilable Mathematica Subset of MathCode C++

A.2.6

Mapping Operations

Map expressions can be compiled in the following cases:

var=Map[f,expr] var=Map[f,expr,{n}]

The result must be directly assigned to a variable as shown. The function f can be: · A function symbol of the compilable subset · An anonymous function, also called pure function in Mathematica · A user defined typed function for which code has been generated

n must be an integer constant. The var=Map[...] statement will be converted to a corresponding assignment statement with a call to Table on the right-hand side.

A.2.7

Iterator Expressions

Computing operations in Mathematica such as Do, Sum, Product and Table use iterators. Additionally there are a number of plotting functions such as Plot, ContourPlot, DensityPlot, Plot3D, ParametricPlot, also using iterators but with some limitations in form and usually constructing sets of real values for the purpose of plotting. These plotting functions are not part of the compilable subset. An iterator can take one of the following forms: Form {imax} {i,imax} {i,imin,imax} {i,imin,imax,di} {i,imin,imax},{j,jmin,jmax} Explanation iterate imax times i goes from 1 to imax in steps of 1 i goes from imin to imax in steps of 1 i goes from imin to imax in steps of di Two iterators: i controls the outer iteration loop, j controls the inner loop

Iterators in Mathematica can use either integer or real values for the iteration variables in the iteration. The compilable subset of iteration functions is limited to integer iteration variables. The iteration variables in Mathematica are declared in a local scope consisting of the body (the expr below) of the iteration function. Thus, translated code in C++ needs to declare those iteration variables in a way that does not clash with other local variables. Typically, these iteration constructs will be translated to (nested) for loops in the target language. Iteration functions in Mathematica may or may not return a value. The functions Sum,

The Compilable Mathematica Subset of MathCode C++

Product, Table and Range always return a value from the iteration. Loop-terminating constructs like Return, Break, Continue, or Throw can be used inside Do. However, Do in Mathematica does not return a value except in the case of an explicit Return of a value. The compilable subset currently does not support return of a value from a Do loop. Another constraint of the compilable subset is that the constructs Sum, Product and Table

may currently only occur on the right hand side of an assignment statement. Concerning Table, see also Section A.2.12. Spec syntax Operator Do[expr,iter1,iter2,...] Sum[expr,iter1,iter2,...] Product[expr,iter1,iter2,...] Table[expr,iter1,iter2,...] Arg type(s) special Real,Integer,Complex Real,Integer,Complex Real,Integer,Complex Result type(s) none Real, Integer,Complex Real, Integer,Complex Array

A.2.8

Input/Output Operations

Arg type(s) Real, Integer, Array, String,Complex Result type(s) none

Spec syntax Operator Print[exprs]

The output is placed on the standard output stream of the external process where the generated code is executing. The recommended way to perform formatted input/output from generated code is via callback functions or external functions.

For functions with two arguments the following rule applies: one argument can be Array and another argument can be either scalar (of the same type as the base type of the array) or Array of the same dimension. This does not apply to == and !=. The functions which return an integer value converted from real: Sign, Floor, Ceiling, Round, give an undefined value or an exception (depending on the underlying target language, e.g. C++) when trying to fit too big a number into an integer. The following functions are implemented according to Mathematica semantics1: · IntegerPart returns (int)x for Reals and int(Re(x)+ i int(Im(x)) for

Complexes

· FractionalPart returns x-IntegerPart(x) · Quotient[m,n] returns Floor(m/n) for Reals. It is not defined for

Complexes

· Floor(x) for Complexes is Floor (Re(x) + i Floor(Im(x) ) ) · Mod[m,n] returns m%n if m and n have the same sign and m%n+n if they have opposite sign. If m or n is a Real then m-n*floor(m/n) is returned. If there a Complex argument passed to these functions they return a Complex result · The Rational function is part of the compilable subset. It is treated exactly like Divide, and converted to Divide during code generation.

1. Read Release Notes for more information

The Compilable Mathematica Subset of MathCode C++

· The special purpose Cross function computes the cross product of n-1 vectors of length n and returns vector of length n. For example, Cross[{2,3,4},{5,6,7}] returns the vector {-3,6,-3} which is orthogonal to the two argument vectors. The function Cross is implemented for n= 3, 4, 5 according to the generalized Mathematica definition. The CompoundExpression construct when used as a value within another statement or expression (but not as a function definition) has the following limitation: the statements (stmt1,..., stmtn) allowed within CompoundExpression are assignments (Set), Print or Put only.1 Assignment to list cannot be used there. For instance:

Variables of type Boolean are not supported in the compilable subset. If boolean values are assigned to integer variables, False becomes 0, True becomes non-zero. Named constants are expressions (expr).

The supported main assignment functions, Set and SetDelayed, have return types. Therefore these can be used both as statements and as expressions. The arguments (left- and right-hand side of the assignment) must be of compatible types. Left and right hand side arguments are compatible if they can be made the same type by performing standard type promotion (e.g. promoting integer to real, or a scalar or lowerdimensional array to a higher-dimensional array), provided that this promotion does not change the type of the left-hand side. If it does, then the assignment is illegal. This means that an expression of a real type cannot be assigned to a variable of integer type without using explicit conversion of the right-hand side (e.g. using Floor[]). In the case of simultaneous assignment to a list of variables {vars}, funcall must be a call to a function returning a list of the same length as the list in the left hand side of the assignment. Also, the vars list in the left hand side must only contain variables.

See also section A.2.7 concerning iterator expressions. The following limitations currently apply to compilation of Array, Table, IdentityMatrix and DiagonalMatrix calls: the exprfunc used by Array may only be a constant function; local iteration variables used in iterators to Table are automatically created but are always of type Integer; calls to Array, Table, IdentityMatrix and DiagonalMatrix may only occur at the right hand side of an assignment statement, for example:

List is partially implemented when appearing within expressions, for instance when used as an actual parameter to a function. The arguments of List can be: · Real expressions (creates Array of Real) · Integer expressions (creates Array of Integer) · Arrays of Real (creates 2-, 3-, 4-dimensional Array of Real). Can be nested. · Arrays of Integers (creates 2-, 3-, 4-dimensional Array of Integers). Can be nested. List is also implemented when it appears on the left-hand-side of assignments. In this case Part is applied to the right-hand side, and all types should match1:

{a,b,{c,d}}=x (* is the same as a=x[[1]];b=x[[2]];c=x[[3,1]];d=x[[3,2]]; *)

Runtime error may occur if matrix appears to be non-rectangular. These special cases are implemented:

The number of arguments to the function must match the length of the expression. · Apply of anonymous (pure) functions, for example

var=Apply[Sin[#1+#2]&amp;,expression] Sin[#1+#2]&amp; @@ expression

The code Apply[foo,expr], equivalent to foo @@ expr, will be converted to foo[expr[[1]],expr[[2]],...]. Therefore the behaviour will be different from that of Mathematica (and hence probably unexpected) if the number of parameters is not the same as the length of the expression expr. It is the user's responsibility to ensure that the number of arguments to the pure function is the same as the length of the expression. The number of arguments is taken as the maximum slot number (for Function[body]) or the length of the variable list (for Function[{vars...}, body]). The expression given to Apply may be computed many times which may be a performance issue. If the expression is big it is better to assign the expression to a temporary variable before using Apply. No level specification is supported for Apply.

A.2.17 Operators Which May Have Side-effects

Spec syntax

var:= e

Operator

Arg type(s) all types all types special special special special special special special special special special

As already mentioned, there are a number of predefined basic types included in the compilable subset of Mathematica. There is also a set of predefined types, primarily array types, which are included for convenience.

Maximal rank of arrays is 4 in the current implementation. The base type should be Real or Integer.

A.4 Predefined Constants

The following constants are available within Mathematica, and are predefined to the following values with 18 decimal digits within generated C++ or Fortran90 code. A standard double precision floating point value can hold slightly less than 16 digits of precision. Name Pi E Value 3.14159265358979324 2.718 281 828 46