Contents Previous Next Index
Internal Representation
The table below lists the structures that are currently implemented in Maple.
Each structure, along with the constraints on its length and contents, is described in the sections that follow.
AND
ASSIGN
BINARY
BREAK
CATENATE
COMPLEX
CONTROL
DCOLON
DEBUG
EQUATION
ERROR
EXPSEQ
FLOAT
FOR
FOREIGN
FUNCTION
GARBAGE
HASH
HASHTAB
HFLOAT
IF
IMPLIES
INEQUAT
INTNEG
INTPOS
LESSEQ
LESSTHAN
LEXICAL
LIST
LOCAL
MEMBER
MODDEF
MODULE
NAME
NEXT
NOT
OR
PARAM
POLY
POWER
PROC
PROD
RANGE
RATIONAL
READ
RETURN
RTABLE
SAVE
SDPOLY
SERIES
SET
STATSEQ
STOP
STRING
SUM
TABLE
TABLEREF
TRY
UNEVAL
USE
XOR
ZPPOLY
Internal Functions
The internal functions in Maple are divided into five groups:
Evaluators
The evaluators are the main functions responsible for evaluation. There are six types of evaluations: statements, algebraic expressions, Boolean expressions, name forming, arbitrary precision floating-point arithmetic, and hardware floating-point arithmetic. The user interface calls only the statement evaluator, but thereafter there are many interactions between evaluators. For example, the statement
if a > 0 then b||i := 3.14/a end if;
is first analyzed by the statement evaluator, which calls the Boolean evaluator to resolve the if condition. Once completed (for example, a true result is returned), the statement evaluator is invoked again to perform the assignment, for which the name-forming evaluator is invoked with the left-hand side of the assignment, and the expression evaluator with the right-hand side. Since the right-hand side involves floating-point values, the expression evaluator calls the arbitrary precision floating-point evaluator.
Normally, you do not specifically call any of the evaluators. However, in some circumstances, when a nondefault type of evaluation is needed, you can directly call evalb (the Boolean evaluator), evaln (the name-forming evaluator), evalf (the arbitrary precision floating-point evaluator), or evalhf (the hardware floating-point evaluator).
Algebraic Functions
Algebraic functions are commonly called basic functions. Some examples are taking derivatives (diff), dividing polynomials (divide), finding coefficients of polynomials (coeff), computing series (series), mapping a function (map), expanding expressions (expand), and finding indeterminates (indets).
Algebraic Service Functions
These functions are algebraic in nature, but serve as subordinates of the functions in the previous group. In most cases, these functions cannot be explicitly called. Examples of such functions are the internal arithmetic packages, the basic simplifier, and retrieval of library functions.
Data Structure Manipulation Functions
These are similar to the algebraic functions, but instead of working on mathematical objects, such as polynomials or sets, they work on data structures, such as expression sequences, sums, products, or lists. Examples of such functions are operand selection (op), operand substitution (subsop), searching (has), and length determination (length).
General Service Functions
Functions in this group are at the lowest hierarchical level. That is, they can be called by any other function in the system. They are general purpose functions, and not necessarily specific to symbolic or numeric computation. Some examples are storage allocation and garbage collection, table manipulation, internal I/O, and exception handling.
Flow of Control
The flow of control does not need to remain internal to the Maple kernel. In many cases, where appropriate, a decision is made to call functions that are written in Maple and are a part of the Maple library. For example, many uses of the expand function are handled in the kernel. However, if an expansion of a sum to a large power is required, the internal expand function calls the external Maple library function 'expand/bigpow' to resolve it. Functions such as diff, evalf, series, and type make extensive use of this feature.
Therefore, for example, the basic function diff cannot differentiate any function. All of that functionality is included in the Maple library in procedures named 'diff/functionName'. This is a fundamental feature of Maple since it permits:
Flexibility (the ability to change the Maple library)
Customization (by defining your refined handling functions)
Readability (much of the Maple functionality is visible at the user level)
Maple allows the kernel to remain small by offloading nonessential functions to the library.
Internal Representations of Data Types
The parser and some internal functions build all of the data structures used internally by Maple. All of the internal data structures have the same general format:
Header
Data1
...
Datan
The header field, stored in one or more machine words, encodes the length of the structure and its type. Additional bits are used to record simplification status, garbage collection information, persistent store status, and various information about specific data structures (for example, whether a for loop contains a break or next statement).
The length is encoded in 26 bits on 32-bit architectures, resulting in a maximum single object size of 67,108,863 words (268,435,452 bytes, or 256 megabytes). On 64-bit architectures, the length is stored in 32 bits, for a maximum object size of 4,294,967,295 words (34,359,738,360 bytes or 32 gigabytes).
Every structure is created with its own length, and that length does not change during the existence of the structure. Furthermore, the contents of most (but not all) data structures are never changed during execution because it is unpredictable how many other data structures are referring to them and relying on them not to change. The normal process for modifying a structure is to copy it and then to modify the copy. Structures that are no longer used are eventually reclaimed by the garbage collector.
The following sections describe each of the structures currently implemented in Maple, along with the constraints on their lengths and contents. The 6-bit numeric value identifying the type of structure is of little interest, so symbolic names will be used.
The notation ^something in the data structure depictions indicates that the value stored in that field of the structure is a pointer to the value (something), rather than being the something itself.
AND: Logical AND
^expr1
^expr2
Maple syntax: expr1 and expr2
Length: 3
ASSIGN: Assignment Statement or Expression
^name-seq
^expr-seq
Maple syntax: name1, name2, ... := expr1, expr2, ...
The left-hand side name entries must evaluate to assignable objects: NAME, FUNCTION, MEMBER or TABLEREF structures, or a sequence thereof. If the left-hand side is a sequence, the right-hand side must be a sequence of the same length.
BINARY: Binary Object
data
Maple syntax: none
Length: arbitrary
The BINARY structure can hold any arbitrary data. It is not used directly as a Maple object, but is used as storage for large blocks of data within other Maple objects (currently only RTABLE structures). It is also sometimes used as temporary storage space during various kernel operations.
BREAK: Break Statement
Maple syntax: break
Length: 1
CATENATE: Name Concatenation
^name
^expr
Maple syntax: name || expr
If the name entry is one of NAME, CATENATE, LOCAL, or PARAM, and if the expr entry evaluates to an integer, NAME, or STRING, the result is a NAME.
If the name entry is a STRING or CATENATE that resolves to a STRING, and if the expr entry evaluates to an integer, NAME, or STRING, the result is a STRING.
If expr is a RANGE, the result is to generate an EXPSEQ of the NAME or STRING structures.
COMPLEX: Complex Value
^re
^im
Maple syntax: Complex(re,im), Complex(im), re + im * I or im * I
Length: 2 or 3
The re and im fields must point to INTPOS, INTNEG, RATIONAL, or FLOAT structures, one of the NAMEs infinity or undefined, or a SUM structure representing -infinity. In the length 3 case, if either re or im is a FLOAT, the other must be a FLOAT as well.
CONTROL: Communications Control Structure
^integer
Length: 2
This is an internal structure used for communication between the kernel and user interface. Such a structure never reaches the user level, or even the mathematical parts of the kernel.
DCOLON: Type Specification or Test
^type-expr
Maple syntax: expr :: typeExpr
This structure has three interpretations depending on the context in which it is used. When it appears in the header of a procedure definition, it is a parameter declaration that has a type. When it appears in the local section of a procedure or on the left-hand side of an assignment, it is a type assertion. When it appears elsewhere (specifically, in a conditional expression), it is a type test.
DEBUG: Debug
Length: 2 or more
This is another structure that is only used internally. It is used by the kernel when printing error traceback information to transmit that information up the call stack.
EQUATION: Equation or Test for Equality
Maple syntax: expr1 = expr2
This structure has two interpretations depending on the context in which it is used. It can be either a test for equality, or a statement of equality (not to be confused with an assignment).
ERROR: Error Statement
Maple syntax: error "msg", arg, ... arg
This structure represents the Maple error statement. The expr is either a single expression (if only a message is specified in the error statement), or an expression sequence (if arguments are also specified). The actual internal tag used for the ERROR structure is MERROR to prevent a conflict with a macro defined by some C compilers.
EXPSEQ: Expression Sequence
Maple syntax: expr1, expr2, ...
Length: 1 or more
An expression sequence is an ordered sequence of expressions. It is most commonly used to construct lists, sets, and function calls. Extracting an expression sequence from a list or set L can be done by using the command op(L). This operation is very efficient as it does not involve creation of a new structure. Similarly, if E is an expression sequence, then constructing a list using [E] involves almost no work and is also very efficient. Constructing a set using {E} requires E to be sorted. A function call data structure is made up of the function name plus the expression sequence of arguments. During evaluation of a function call, the argument sequence gets flattened into one expression sequence. That is, f(E1,E2) is turned into f(e11,e12,...e1n,e21,e22,...e2m) where e1i constitutes the members of the expression sequence E1, and e2i constitutes the members of the expression sequence E2. Thus it is not possible to pass raw expression sequences as arguments to functions. Typically sequences are wrapped in lists, as f([E1],[E2]) in order to keep the element groupings intact. The special value NULL is represented by an empty expression sequence. Thus, [NULL] is equivalent to [], and f(NULL) is equivalent to f().
FLOAT: Software Floating-Point Number
^integer1
^integer2
^attrib-expr
Maple syntax: 1.2, 1.2e3, Float(12,34), Float(infinity)
Length: 2 (or 3 with attributes)
A floating-point number is interpreted as integer1 * 10^integer2. A floating-point number can optionally have attributes, in which case, the length of the structure is 3 and the third word points to a Maple expression. This means that several floating-point numbers with the same value but different attributes can exist simultaneously.
The integer2 field can optionally be one of the names, undefined or infinity, in which case the FLOAT structure represents an undefined floating-point value (not-a-number, or NaN, in IEEE terminology), or a floating-point infinity. When integer2 is undefined, integer1 can accept different small integer values, allowing different NaN values to exist. When integer2 is infinity, integer1 must be 1 or -1.
FOR: For/While Loop Statement
^from-expr
^by-expr
^to-expr
^while-expr
^stat-seq
^until-expr
Maple syntax:
for name from fromExpr by byExpr to toExpr while whileExpr do statSeq end do
for name from fromExpr by byExpr to toExpr while whileExpr do statSeq until untilExpr
^in-expr
for name in inExpr while whileExpr do statSeq end do
for name in inExpr while whileExpr do statSeq until untilExpr
Length: 8 or 6
The name follows the same rules as the name field of the ASSIGN structure, except that it can also be the empty expression sequence (NULL), indicating that there is no controlling variable for the loop.
The from-expr, by-expr, to-expr, while-expr, and until-expr entries are general expressions. All are optional in the syntax of for loops and are therefore be replaced with default values (1, 1, NULL, true, and false respectively) by the parser if omitted.
The stat-seq entry can be a single Maple statement or expression, a STATSEQ structure, or NULL indicating an empty loop body. An additional bit in the header of the FOR structure is used to indicate whether the stat-seq entry contains any break or next statements.
FOREIGN: Foreign Data
This structure is similar to the BINARY structure, except that it is for use by Maple components outside the kernel, such as the user interface. A FOREIGN structure is exempt from garbage collection, and the external component is responsible for freeing this structure when it is finished using it.
FOREIGN data structures can be created and managed in external code by using the MaplePointer API functions. For more information, refer to the OpenMaple,C,MaplePointer help page.
FUNCTION: Function Call
Maple syntax: name( exprSeq )
This structure represents a function invocation (as distinct from a procedure definition that is represented by the PROC structure). The name entry follows the same rules as in ASSIGN, or it can be a PROC structure. The expr-seq entry gives the list of actual parameters; this entry is always an expression sequence (possibly of length 1, which indicates that no parameters are present).
GARBAGE: Garbage
This structure is used internally by the Maple garbage collector as a temporary object type for free space.
HFLOAT: Hardware Float
floatword
Length: 2 on 64-bit architectures; 3 on 32-bit architectures
This structure is used to store a hardware floating-point value. The one or two words (always 8 bytes) after the header store the actual double-precision floating-point value. HFLOAT objects can appear as the result of floating-point computations, I/O operations, or by extracting elements from hardware floating-point RTABLE structures. They look like and are treated as indistinguishable from software FLOAT objects.
IF: If Statement
^cond-expr1
^stat-seq1
^cond-expr2
^stat-seq2
^stat-seqN
if condExpr1 then statSeq1 elif condExpr2 then statSeq2 ... else statSeqN end if
Length: 3 or more
This structure represents the if ... then ... elif ... else ... end if statements in Maple. If the length is even, the last entry is the body of an else clause. The remaining entries are interpreted in pairs, where each pair is a condition of the if or elif clause, followed by the associated body.
IMPLIES: Logical IMPLIES
Maple syntax: expr1 implies expr2
INEQUAT: Not Equal or Test for Inequality
Maple syntax: expr1 < > expr2
This structure has two interpretations, depending on the context in which it is used. It can be either a test for inequality or an inequality statement.
INTNEG: Negative Integer
GMP-integer
Maple syntax: -123
This data structure represents a negative integer of arbitrary precision. For a complete description of the integer representation, including positive integers, see the following section.
INTPOS: Positive Integer
Maple syntax: 123
This data structure represents a positive integer of arbitrary precision. Integers are represented internally in a base equal to the full word size of the host machine. On 32-bit architectures, this base is 4294967296. On 64-bit architectures, the base is 2^64. Integers in this range use the GNU Multiple Precision Arithmetic (GMP) library for integer arithmetic.
Small integers are not represented by data structures. Instead of a pointer to an INTPOS or INTNEG structure, a small integer is represented by the bits of what would normally be a pointer. The least significant bit is 1, which makes the value an invalid pointer (since pointers must be word-aligned). Such an integer is called an immediate integer.
The range of integers that can be represented in this way is -1,073,741,823 to 1,073,741,823 (that is, about +-10^9) on 32-bit architectures, and -4,611,686,018,427,387,903 to 4,611,686,018,427,387,903 (that is, about +-410^18) on 64-bit architectures. (Note that the maximum (non-immediate) integer magnitude in Maple is about 2^2,147,483,488 on 32-bit architectures and 2^274,877,906,688 on 64-bit architectures.)
LESSEQ: Less Than or Equal
Maple syntax: expr1 <= expr2, expr2 >= expr1
This structure has two interpretations, depending on the context. It can be interpreted as a relation (that is, an inequation) or as a comparison (for example, in the condition of an if statement, or the argument to a call to evalb). Maple does not have a greater-than-or-equal structure. Any input of that form is stored as a LESSEQ structure.
LESSTHAN: Less Than
Maple syntax: expr1 < expr2, expr2 > expr1
Similar to the LESSEQ structure above, this structure has two interpretations, depending on the context. It can be interpreted as a relation (that is, an inequation), or as a comparison (for example, in the condition of an if statement, or the argument to a call to evalb).
Maple does not have a greater-than structure. Any input of that form is stored as a LESS structure.
LEXICAL: Lexically Scoped Variable within an Expression
integer
Maple syntax: name
This represents an identifier within an expression in a procedure or module that is not local to that procedure, but is instead declared in a surrounding procedure or module scope. The integer field identifies which lexically scoped variable of the current procedure is being referred to. The integer, multiplied by 2, is an index into the lexical-seq structure referred to by the PROC DAG of the procedure. Specifically, |integer| * 2 - 1 is the index to the NAME of the identifier, and |integer| * 2 is the index to a description (LOCAL, PARAM, or LEXICAL) relative to the surrounding scope. The value of integer can be positive or negative. If integer is a positive value, the original identifier is a local variable of a surrounding procedure; if integer is a negative value, it is a parameter of a surrounding procedure.
LIST: List
Maple syntax: [ expr, expr, ... ]
The elements of the expr-seq are the elements of the list. The list can optionally have attributes.
LOCAL: Local Variable within an Expression
This structure indicates a local variable when it appears within an expression in a procedure or module. The integer is an index into the procedure local-seq. At procedure execution time, it is also an index into the internal data structure storing the active locals on the procedure activation stack, and stores private copies of the NAMEs of the local variables (private copies in the sense that these NAMEs are not the same as the global NAMEs of the same name).
MEMBER: Module Member
^module
Maple syntax: module:-name
This structure represents a module member access in an expression. MEMBER objects typically do not persist when a statement is simplified. Instead, they are replaced by the actual member that they refer to (an instance of a NAME).
MODDEF: Module Definition
param-seq
local-seq
option-seq
export-seq
stat-seq
desc-seq
global-seq
lexical-seq
mod-name
static local-seq
static export-seq
static name-seq
module modName ( ) description d1, d2, ...; local l1, l2, ...; local sl1::static, sl2::static, ...; export e1, e2, ...; export se1::static, se2::static, ...; global g1, g2, ...; option o1, o2, ...; statSeq end module
Length: 13
The parameter sequence (param-seq), which occurs between the parentheses after modName, points to an expression sequence describing the formal parameters of the module. Currently, Maple does not support parameterized modules, so this field always points to the sequence containing only an instance of the name thismodule.
The local sequence (local-seq) points to an expression sequence listing the explicitly and implicitly declared local variables. Each entry is a NAME. The explicitly declared variables appear first. Within the module, locals are referred to by LOCAL structures, the local variable number being the index into the local sequence. The instances of these names appear in the MODULE structure.
The export sequence (export-seq) points to an expression sequence listing the exported module members. Each entry is a NAME. Within the module, exports are referred to by LOCAL structures, the local variable number being the number of elements in the local sequence, plus the index into the export sequence. The instances of these names appear in the MODULE structure.
The option sequence (option-seq) points to an expression sequence of options to the module (for modules, options are the same as attributes). Each entry is a NAME or EQUATION specifying an option. Typical options are package, load=... and unload=...
The statement sequence (stat-seq) field points to a single statement or a statement sequence (STATSEQ). If the module has an empty body, this is a pointer to NULL instead.
The description sequence (desc-seq) field points to an expression sequence of NAMEs or STRINGs. These sequences are meant to provide a brief description of what the module does and are displayed even when the value of interface(verboseproc) is less than 2.
The global sequence (global-seq) field points to a list of the explicitly declared global variables in the module (those that appeared in the global statement). This information is never used at run time, but is used when simplifying nested modules and procedures to determine the binding of lexically scoped identifiers (for example, an identifier on the left-hand side of an assignment in a nested procedure can be global if it appears in the global statement of a surrounding context). This information is also used at printing time, so that the global statement contains exactly the global identifiers that were declared originally.
The lexical sequence (lexical-seq) field points to an expression sequence of links to identifiers in the surrounding scope, if any. The sequence consists of pairs of pointers. The first pointer of each pair is to the globally unique NAME of the identifier; this is needed at simplification and printing time. The second pointer is a pointer to a LOCAL, PARAM, or LEXICAL structure which is understood to be relative to the surrounding scope. When a module definition is evaluated, the lexical sequence is updated by replacing each of the second pointers with a pointer to the actual object represented. The name pointers are not modified, so that the actual identifier names are still available. The lexical-seq for a module contains entries for any surrounding-scope identifiers used by that module or by any procedures or modules contained within it.
The module name (mod-name) field points to the optional name of the module. If a module name is specified when the module is declared, the name appears there. If no module name is specified, this field will contain a value of NULL.
The static local-seq points to an expression sequence listing the local variables that were explicitly declared as :static. Each entry is a NAME. Within the module, static locals are referred to by LOCAL structures, the local variable number being the index into the static local-seq minus the number of nonstatic locals and exports. A static local shares its value among all instances of a class.
The static export-seq points to an expression sequence listing the exported module members declared as static. Each entry is a NAME. Within the module, exports are referred to by LOCAL structures, the local variable number being the number of elements in the local-seq, static local-seq, and export-seq, plus the index into the static export-seq.
The static name-seq stores the instances of the static locals and exports. It appears in the MODDEF structure as these static variables are shared among all modules with the same definition.
MODULE: Module Instance
^export-seq
^mod-def
^local-seq
Length: 4
Executing a module definition (MODDEF) results in a module instance. Each local or exported member of the module is instantiated and belongs to that instance of the module. The export-seq field points to an expression sequence of names of the instantiated exports (as opposed to the global names, as stored in the module definition). The mod-def field points back to the original module definition. The local-seq field points to an expression sequence of names of the instantiated local variables of the module.
NAME: Identifier
^assigned-expr
characters
Length: 4 or more
The assigned-expr field points to the assigned value of the name. If the name has no assigned value, this field is a null pointer (not a pointer to NULL). The next field points to an expression sequence of attributes of the name. If there are no attributes, this field points to the empty expression sequence (NULL). The remaining fields contain the characters that form the name, stored 4 or 8 for each machine word (for 32-bit and 64-bit architectures respectively). The last character is followed by a zero-byte. Any unused bytes in the last machine word are also zero. The maximum length of a name is 268,435,447 characters on 32-bit architectures and 34,359,738,351 characters on 64-bit architectures.
NEXT: Next Statement
Maple syntax: next
NOT: Logical NOT
Maple syntax: not expr
OR: Logical OR
Maple syntax: expr1 or expr2
PARAM: Procedure Parameter in an Expression
This structure indicates a parameter when it appears in a procedure. The integer is an index into the procedure param-seq. Several special PARAM structures exist:
0
This structure represents the Maple symbol _npassed (formerly nargs), the number of arguments passed when the procedure was called.
-1
This structure represents the Maple symbol _passed (formerly args), the entire sequence of arguments passed when the procedure was called.
-2
This structure represents the Maple symbol procname, referring to the currently active procedure.
-3
This structure represents the Maple symbol _nresults, the number of results expected to be returned from the procedure.
-4
This structure represents the Maple symbol _params, the sequence of declared positional arguments passed when the procedure was called.
-5
This structure represents the Maple symbol _nparams, the number of declared positional arguments passed when the procedure was called.
-6
This structure represents the Maple symbol _rest, the sequence of undeclared arguments passed when the procedure was called.
-7
This structure represents the Maple symbol _nrest, the number of undeclared arguments passed when the procedure was called.
-8
This structure represents the Maple symbol _options, the sequence of options in the procedure.
-9
This structure represents the Maple symbol _noptions, the number of options in the procedure.
-10
This structure represents the Maple symbol thisproc, referring to the instance of the currently active procedure.
At procedure execution time, the integer (if positive) is used as an index into the internal data structure Actvparams, which is part of the Maple procedure activation stack, and stores pointers to the values (which are also Maple structures) of the actual parameters passed to the procedure.
POLY: Multivariate Polynomials with Integer Coefficients
^indet_seq
m[i] degrees
m[i] coeff
m[i+1] degrees
m[i+1] coeff
x^3 + 2*x*y + 1;
Length: 2*(number of monomials) + 2
This is an internal representation for multivariate polynomials of limited degree and integer coefficients. SUM DAGs are automatically simplified to POLY DAGs if possible, provided the polynomial has at least two terms and its total degree is greater than 1.
Each degree word stores the total degree of the monomial and the individual degrees. For example, 5*x^2*y^3 + 1 is a two-variable polynomial whose first term has total degree 5: degree 2 in x, and degree 3 in y. The numbers 5, 2, and 3 are packed into a single degree word. The packing depends on the number of variables in the polynomial and the machine word length. Because the packing must fit in one word of memory, not all polynomials can be represented in this way. But many polynomials are stored in this data structure, which can be operated on efficiently.
Each coefficient word must be an integer data structure.
The indet_seq is the sequence of indeterminates that occur in the polynomial. The indeterminates must be Maple NAMEs or TABLEREFs. They are always sorted into descending order under the ordering used for sets.
The terms of the polynomial are always stored in graded lexicographical order. That is, monomials are compared first by their total degree, with ties broken by degree in the first variable, then degree the second variable, and so on.
If the sort command is used to sort a polynomial, and it would reorder either the terms or the variables, then the POLY DAG is automatically converted to a SUM DAG in place. Should this occur, it is not possible to convert the SUM back into a POLY.
The precise representation of monomials is as follows. For univariate polynomials, the entire degree word is used and the maximum degree of a POLY is the largest immediate integer kernelopts(maximmediate). For polynomials in n variables, we require n < WORDSIZE/2, so the maximum number of variables is 31 on a 64-bit machine and 15 on a 32-bit machine. The total degree and all of the exponents are given floor(WORDSIZE/(n+1)) bits each, flush against the bottom of the word. For example, on a 64-bit machine a polynomial in x,y will use the lowest 21 bits for y, the next 21 bits for x, and the next 21 bits for the total degree. Any unused bits at the top of a word must remain unset.
POWER: Power
Maple syntax: expr1 ^expr2
This structure is used to represent a power when the exponent is not an integer, rational, or floating-point value. When the exponent is numeric, the POWER structure is converted to a length 3 PROD structure.
PROC: Procedure Definition
^param-seq
^option-seq
^rem-table
^desc-seq
^global-seq
^lexical-seq
^eop
^return-type
proc ( paramSeq ) :: returnType; description descSeq; local localSeq; export exportSeq; global globalSeq; option optionSeq; statSeq end proc
Length: 10 or 11 (the return type is optional)
The param-seq points to an expression sequence describing the formal parameters of the procedure. Each entry is either a NAME or a DCOLON (which, in turn, contains a NAME and an expression specifying a type). Within the procedure, parameters are referred to by PARAM structures, the parameter number being the index into the param-seq.
The local-seq points to an expression sequence listing the explicitly and implicitly declared local variables. Each entry is a NAME. The explicitly declared variables appear first. Within the procedure, locals are referred to by LOCAL structures, the local variable number being the index into the local-seq.
The option-seq field points to an expression sequence of options to the procedure (for procedures, options are the same as attributes). Each entry is a NAME or EQUATION specifying an option. Commonly used options are cache, operator, and `Copyright ...`.
The rem-table field points to a hash table containing remembered values of the procedure. Entries in the table are indexed by the procedure arguments, and contain the resulting value. If there is no remember table, this field contains a pointer to NULL, which is the empty expression sequence.
The stat-seq field points to a single statement or a statement sequence (STATSEQ). If the procedure has an empty body, this is a pointer to NULL instead. For each procedure that is built into the kernel, there is a wrapper PROC that has the option builtin in its option-seq, and a single Maple integer pointed to by its stat-seq. The integer gives the built-in function number.
The desc-seq field points to an expression sequence of NAMEs or STRINGs. These are meant to provide a brief description of what the procedure does, and are displayed even when the interface(verboseproc) command is less than 2.
The global-seq field points to a list of the explicitly declared global variables in the procedure (those that appeared in the global statement). This information is never used at run time, but it is used when simplifying nested procedures to determine the binding of lexically scoped identifiers. For example, an identifier on the left-hand side of an assignment in a nested procedure can be global if it appears in the global statement of a surrounding procedure. This information is also used at procedure printing time, so that the global statement will contain exactly the same global identifiers that were declared in the first place.
The lexical-seq field points to an expression sequence of links to identifiers in the surrounding scope, if any. The sequence consists of pairs of pointers. The first pointer of each pair is to the globally unique NAME of the identifier; this is needed at simplification and printing time. The second pointer is a pointer to a LOCAL, PARAM, or LEXICAL structure which is understood to be relative to the surrounding scope. When a procedure is evaluated (not necessarily called), the lexical-seq is updated by replacing each of the second pointers with a pointer to the actual object represented. The name pointers are not modified, so that the actual identifier names are still available. The lexical-seq for a procedure contains entries for any surrounding-scope identifiers used by that procedure or by any procedures contained within it.
The eop field is BINARY. The first entry specifies the number of positional parameters of the procedure. The remaining entries, if any, specify the evaluation order permutation for the procedure (that is, an evaluation order for the arguments that is consistent with any dependencies among the parameter specifications).
The return-type field is present only if a return type has been specified for the procedure. A return type is an assertion about the type of the value returned by the procedure; if kernelopts(assertlevel) is set to 2, then this type is checked as the procedure returns.
PROD: Product, Quotient, Power
^expon1
^expon2
Maple syntax: expr1 ^ expon1 * expr2 ^ expon2 ...
Length: 2n + 1
This structure is interpreted as pairs of factors and their numeric exponents. Rational or integer expressions to an integer power are expanded. If a rational constant is in the product, this constant is moved to the first entry by the simplifier. A simple power, such as a2, is represented as a PROD structure. More complex powers involving non-numeric exponents are represented as POWER structures.
RANGE: Range
Maple syntax: expr1 .. expr2
RATIONAL: Rational
^pos-integer
Maple syntax: 1/2
This structure is one of the basic numeric objects in Maple. Note that this is not a division operation, but only a representation for rational numbers. Both fields must be integers (INTPOS, INTNEG, or an immediate integer) and the second must be positive.
READ: Read Statement
Maple syntax: read expr
The Maple read statement. The expression must evaluate to either a string or symbol (STRING or NAME structure), and specifies the name of the file to read.
RETURN: Return Statement
Maple syntax: return expr1, expr2, ...
The Maple return statement. The expression sequence is evaluated, giving the value(s) to return.
RTABLE: Rectangular Table
^data
^maple-type
^index-func
^attrib
flags
num-elems
L1
U1
LN
UN
P1
P2
Maple syntax: rtable(...)
Length: 2n + p where n is the number of dimensions (0 to 63), and p is 0, 1, or 2, depending on the number of Pi parameters.
The data field points to either a block of memory (for dense and NAG-sparse RTABLEs), or to a HASHTAB structure (for Maple-sparse RTABLEs). The data block is either an object of type BINARY, or memory allocated directly from the storage manager of the operating system when the block is too large to be allocated as a Maple data structure. If the data block is a BINARY object, the data pointer points to the first data word, not to the object header.
The maple-type field points to a Maple structure specifying the data type of the elements of an RTABLE of Maple objects. If the RTABLE contains hardware objects, the maple-type field points to the Maple NAME anything.
The index-func field points to either an empty expression sequence (NULL), or an expression sequence containing at least one indexing function and a pointer to a copy of the RTABLE structure. The copy of the RTABLE is identical to the original structure, except that its index-func field refers to one less indexing function (either NULL, or another expression sequence containing at least one indexing function and a pointer to another copy of the RTABLE with one less indexing function again).
The attrib field points to an expression sequence of zero or more arbitrary attributes, which can be set by the setattribute command and queried by using the attributes command.
The flags field is a bit field containing the following subfields.
data type - 5 bits - indicates that one of several hardware data types or a Maple data type (as specified by maple-type) is being used.
subtype - 2 bits - indicates if the RTABLE is an Array, Matrix, or Vector.
storage - 4 bits - describes the storage layout (for example, sparse, upper triangular, and so on)
order - 1 bit - indicates C or Fortran ordering of RTABLE elements.
read only - 1 bit - indicates that the RTABLE is to be read-only once created.
foreign - 1 bit - indicates that the space pointed to by the data field does not belong to Maple, so Maple should not garbage collect it.
eval - 1 bit - indicates if full evaluation should occur on lookup. For more information, refer to the rtable_eval help page.
literal - 1 bit - optimization for internal type checking of data contained in an RTABLE.
number of dimensions - 6 bits - the number of dimensions of the RTABLE, from 0 to 63.
The num-elems field indicates the total number of elements of storage allocated for the data. For a Maple-sparse RTABLE, num-elems is not used. For a NAG-sparse RTABLE, and for other formats that grown in size since initial allocation, num-elems specifies the number of elements currently allocated, some of which might not be in use.
The Li..Ui fields specify the upper and lower bounds of each dimension; they are stored directly as signed machine integers. The limits on bounds are -2,147,483,648 to 2,147,483,647 for 32-bit architectures and -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 for 64-bit architectures. The total number of elements cannot exceed the upper limit numbers either. Space is always reserved for at least 4 dimensions in case the rtable is redimensioned.
The remaining Pi fields refer to storage specific properties such as the number of bands above and below the diagonal and the number of elements that are sorted in NAG-sparse storage.
SAVE: Save Statement
Maple syntax: save expr, expr, ...
The Maple save statement. The expression sequence gives a list of names of objects to save, and either a file name or Maple library archive name (.mla) in which to save them. The file or library archive name can be specified as a NAME or STRING.
SDPOLY: Sparse Distributed Multivariate Polynomial
^term_ordering
^coeff_domain
^coeff_1
exp_1
exp_n
^coeff_m
Length: For a polynomial of m terms with n variables, the length is 4+m⁢n+1
The expr entry stores the indeterminates of the polynomial (symbol for univariate cases or expression sequence of symbols for multivariate cases).
The term_ordering is either null or a pointer to a Maple procedure that is used to compare the exponent_vector to sort the polynomial terms. When term_ordering is null, lexicographic order is used to sort the polynomial terms.
The coeff_domain is either null or a pointer to a Maple module that is used to perform coefficient arithmetic (addition and multiplication). When coeff_domain is null, ordinary arithmetic is used. Each of the following m terms consists of a coefficient coeff_i (i=1..m) followed by an exponent_vector [exp_j] (j=1..n). Coefficient coeff_i is a non-zero Maple expression. Exponent_vector [exp_j] is an array of n hardware integers. Each integer stores the exponent of the corresponding indeterminate. By default, the polynomial terms are sorted by lexicographic order (that is, sorted by descending powers of indeterminate).
SERIES: Series
^expr3
Length: 2n + 2
This is the internal representation of a series in Maple. There is no input syntax for a series; one can only be generated from a computation. The first expression has the general form x-a, where x denotes the variable of the series used to perform that expansion, and a denotes the point of expansion. The remaining entries are interpreted as pairs of coefficients and exponents. The exponents are integers, not pointers to integers or immediate integers. The exponents appear in increasing order. A coefficient O(1) (a function call to the function O, with parameter 1) is interpreted specially by Maple as an order term.
SET: Set
Maple syntax: { expr, expr, ... }
The entries in the expression sequence of the set are sorted in a deterministic order. For details, see the set help page.
STATSEQ: Statement Sequence
^stat1
^stat2
Maple syntax: stat1; stat2; ...
This structure represents a sequence of two or more statements, and can be used wherever a single statement (for example, ASSIGN, IF, FOR) can appear. A statement sequence, containing only a single statement, is replaced by that statement. A statement sequence containing no statements is replaced by the empty expression sequence (NULL). Nested STATSEQ structures are flattened. All of the above transformations are made by the simplifier.
STOP: Quit Statement
Maple syntax: quit, done, or stop
STRING: Character String
reserved
Maple syntax: "This is a string"
A Maple string is structurally similar to a NAME, except that it has no assigned-value field. The attrib-expr field points to an expression sequence of attributes of the string. If there are no attributes, this field points to the empty expression sequence (NULL). The remaining fields contain the characters that form the string, stored 4 or 8 per machine word (for 32-bit and 64-bit architectures respectively). The last character is followed by a zero-byte. Any unused bytes in the last machine word are also zero.
The maximum length of a string is 268,435,447 characters on 32-bit architectures and 34,359,738,351 characters on 64-bit architectures.
SUM: Sum, Difference
^factor1
^factor2
Maple syntax: expr1 * factor1 + expr2 * factor2 ...
This structure is interpreted as pairs of expressions and their numeric factors. Rational or integer expressions with an integer factor are expanded and the factor replaced with 1. If there is a rational constant in the sum, this constant is moved to the first entry by the simplifier. Simple products, such as a*2, are represented as SUM structures. More complex products involving non-numeric factors are represented as PROD structures.
TABLE: Table
^array-bounds
^hash-tab
Maple syntax: N/A
This is a general table type, as created by the table and array commands in Maple. The index-func points to either a NAME or a PROC. For general tables, the array-bounds field points to the empty expression sequence (NULL). For arrays (not to be confused with Arrays, which are implemented as RTABLEs), the array-bounds field refers to an expression sequence of RANGEs of integers. The hash-tab field points to a HASHTAB structure containing the elements.
TABLEREF: Table Reference
Maple syntax: name [ expr ]
Length: 3 (or 4 with attributes)
This data structure represents a table reference, or indexed name. The name entry follows the same rules as for ASSIGN, or it may be a TABLE or MODULE structure. (The parser will not generate a TABLEREF with a TABLE structure for the name entry, but this can occur internally.) The expression sequence contains the indices.
TRY: Try Statement
^try-stat-seq
^catch-str
^catch-stat-seq
^final-stat-seq
try tryStat catch "catchStr": catchStat ... finally finalStat; end try
This structure represents a try statement, and can have an arbitrary length, depending on how many catch blocks are contained within it, and whether it has a finally block. The catch-strs point to the catch string of the corresponding catch block. If no catch string is specified, the catch-str points to NULL. Empty catch-stat-seqs are also represented by pointers to NULL, as is an empty (but present) finally block.
The actual internal tag used for the TRY structure is MTRY to prevent collision with a macro defined by some C exception handling libraries.
UNEVAL: Unevaluated Expression
Maple syntax: 'expr'
USE: Use Statement
^bindings
^statseq
Maple Syntax:
use bindings in statseq end use
The bindings component points to an expression sequence of equations whose left-hand sides are symbols, and the statseq component points to a sequence of statements that form the body of the use statement. The right-hand sides of the binding equations can be arbitrary expressions.
The use statement introduces a new binding contour and binds the names that appear on the left-hand side of the equations in bindings. For convenience, on input, a module 'm' can appear among the bindings, and is treated as if it were the sequence e1 = m:-e1, e2 = m:-e2, ..., where the ei are the exports of 'm'. Within the sequence statseq of statements, the symbols appearing on the left-hand side of the equations in bindings are bound to the corresponding right-hand sides. The previous bindings of those symbols are restored upon exit from the use statement. Bindings are resolved during automatic simplification.
XOR: Logical Exclusive-Or
Maple syntax: expr1 xor expr2
ZPPOLY: Polynomials with Integer Coefficients modulo n
^indet
mod
coef0
coef1
^zppoly0
^zppoly1
Maple syntax: modp1( ConvertIn( expr, indet ), n );
Maple syntax: modp2( ConvertIn( expr, indet1, indet2 ), n );
Length: degree(zppoly) + 2 (for the zero polynomial)
Length: degree(zppoly) + 3 (otherwise)
This is the internal representation of univariate and bivariate polynomials modulo some integer. The modp1() and modp2() front ends provide a suite of functions to work on this data structure operating in the domain of polynomials in one or two variables with integer coefficients modulo n, written Znx or Znx,y, respectively. indet_seq is an expression sequence of the indeterminates of the polynomial: (x), or (x,y). mod is the integer modulus of the integer domain. In a univariate polynomial, the coefficients are stored in the following order.
(coef0*indet^0 + coef1*indet^1 + ... + coefi*indet^i) mod n
A bivariate polynomial contains pointers to univariate ZPPOLY structures representing the coefficients of the first indeterminate.
(coef0(indet2)*indet1^0 + coef1(indet2)*indet1^1 + ...) mod n
where each coefi is a univariate polynomial in indet1 mod n.
All coefficients are stored, including zero coefficients. The leading coefficient is always non-zero.
Hashing in Maple
An important factor in achieving the overall efficient performance of Maple is the use of hash table-based algorithms for critical functions. Tables are used in both simplification and evaluation, as well as for less critical functions. For simplification, Maple keeps a single copy of each expression, or subexpression, during a session. This is done by keeping all objects in a table. In procedures, the cache and remember options specify that the result of each computation of the procedure is to be stored in a remember table associated with the procedure. Finally, tables are available to the user as one of the Maple data types.
All table searching is done by hashing. Three types of hash tables are available: basic, dynamic, and cache. Basic hash tables are used for most Maple hashing. They are automatically promoted to dynamic hash tables when they are filled with a large number of elements. Dynamic hash tables are designed to work with a large number of elements. Cache tables are a type of hash table that store only recently inserted items.
Basic Hash Tables
The algorithm used for the basic hash tables is direct chaining, except that the chains are dynamic vectors instead of the typical linked lists. The two data structures used to implement hash tables are HASHTAB and HASH.
Hash Table
^hash-chain1
^hash-chain2
Length: 2n+1
This is an internal data structure with no Maple syntax equivalent. It is used in the representation of tables within Maple. Each entry points to a hash chain (a HASH structure), or is a null pointer if no entry has been created in that hash chain yet (that is, with that entry location as its hash value). The size of a HASHTAB structure depends on the type of table and the platform, but is always a power of 2 plus one.
Hash Chain
key
Each table element is stored as a pair of consecutive entries in a hash bucket vector. The first entry of this pair is the hash key, and the second is a pointer to a stored value. In some cases (for example, procedure remember tables and user-defined tables), the key is also a pointer. In other cases, the key is a hashed value (for example, the simplification table, the symbol table). The key cannot have the value zero (or the null pointer) since this is used to indicate the bottom of the bucket.
Dynamic Hash Tables
The Maple dynamic hash table is a complicated data structure. a brief overview is presented here.
Instead of using a flat, fixed-length directory, Maple dynamic hash tables use a tree structure with contiguous bits from the hash key to select a child. A child of a directory can be a subdirectory or a hash chain. For example, a top-level directory may use the first 10 bits to index 1024 children. One of its children may be a directory that uses, for example, the next 8 bits of the key to index 256 children.
A hash chain in a dynamic table stores elements using key value pairs (in the same way that a hash chain does in a basic hash table). The first n bits of the keys in a hash chain are identical, where n is the number of bits required to locate the hash chain. The remaining bits are arbitrary. Using the example in the previous paragraph, the elements of a hash chain that is a child of the directory with 256 children have hash keys that are identical in the first 18 bits.
When a hash chain with unused bits overflows, it is split into two. This may require creating a subdirectory with two children or doubling the size of the hash chain's parent directory. In either case, another bit from the hash key is introduced for indexing. This bit is used to divide the elements of the old chain into the two new chains. If the hash chain has no unused bits for indexing, the chain grows as needed. This growth occurs only if many elements are inserted with identical hash keys.
Cache Hash Tables
Cache tables have two classes of entries: permanent and temporary. Each bucket in the table has 4 entries reserved as temporary, followed by a pointer to a variable-sized chain.
Permanent entries, as designated by the way they are inserted, are stored exclusively in the variable-sized chain, which can grow as needed.
Temporary entries are inserted in the normal way you would include a value in a basic hash table or remember table. These are hashed to identify the bucket in which they are to be stored. The existing entries in that bucket are pushed right by one, and the new entry is put in the leading, ''most-recent'' spot. Reinserting an expression will cause it to be promoted to the ''most-recent'' spot. Inserting a fifth element that hashes to the same bucket will cause the least recently inserted temporary element to be removed from the table.
The maximum size of the cache table can be specified at creation time. Because cache tables have a maximum size, and because as new elements are added old ones may be removed, the cache table does not grow continuously as values are added. When used as a remember table, they are useful for temporarily storing elements that were recently computed, and likely to be needed again. Over time, as more elements are inserted, the old elements will be discarded.
Cache tables can be created by using the Cache command, or as a remember table in a procedure with the cache option specified. The advantage of using a cache table over standard remember tables is that a cache table has a maximum size. This means that a cache table does not act as a memory trap, storing a large number of values that cannot be reclaimed by the garbage collector. As cache tables allow permanent elements to be added, they can be used in procedures that cannot use option system remember tables.
The Simplification Table
The most important table maintained by the Maple kernel is the simplification table. All simplified expressions and subexpressions are stored in the simplification table. The main purpose of this table is to ensure that simplified expressions have a unique instance in memory. Every expression which is entered into Maple or generated internally is checked against the simplification table. If it is found in the simplification table, the new expression is discarded and the old one (the one in the simplification table) is used. This task is done by the simplifier, which recursively simplifies (applies all the basic simplification rules) and checks against the table. The garbage collector deletes the entries in the simplification table that cannot be reached from a global name or from a live local variable.
The task of checking for equivalent expressions within thousands of subexpressions would not be feasible if it were not done with the aid of hashing. Every expression is entered in the simplification table using its signature as a key. The signature of an expression is a hashing function itself, with one important attribute: signatures of trivially equivalent expressions are equal. For example, the signatures of the expressions a+b+c and c+a+b are identical; the signatures of a*b and b*a are also identical. If the signatures of two expressions disagree, the expressions cannot be equal at the basic level of simplification.
In Maple 13, the use of the basic and dynamic hash tables as the data structure behind the simplification table was phased out in favor of a new structure that worked better in a multithreaded environment. In particular, the new table guarantees atomic inserts. This removed the need for locking, and, because the simplification table is used so often, greatly improved performance when running many threads.
Searching for an expression in the simplification table is done by:
Simplifying recursively all of its components
Applying the basic simplification rules
Computing its signature and searching for this signature in the table
If the signature is found, then a full comparison is performed (taking into account that additions and multiplications are commutative) to verify that it is the same expression. If the expression is found, the one in the table is used and the searched one is discarded. A full comparison of expressions has to be performed only when there is a collision of signatures.
Since simplified expressions are guaranteed to have a unique occurrence, it is possible to test for equality of simplified expressions using a single pointer comparison. Unique representation of identical expressions is significant for the efficiency of tables, and therefore the remember option. Also, since the relative order of objects is preserved during garbage collection, sequences of objects can be ordered by machine address. For example, sets containing mutable objects are represented this way. The set operations, such as union or intersection, can be done in linear time by merging sorted sequences. Sorting by machine address is also available by using the sort command.
The Name Table
The simplest use of hashing in the Maple kernel is the name table. This is a symbol table for all of the global names. Each key is computed from the character string of the name and the entry is a pointer to the data structure for the name. The name table is used to locate global names formed by the lexical scanner or by name concatenation. It is also used by functions that perform operations on all global names. These operations include:
Marking for garbage collection
Saving a Maple session environment in a file
The Maple commands anames and unames, which return all assigned and unassigned global names, respectively
Remember Tables
A remember table is a hash table in which the argument(s) to a procedure call are stored as the table index, and the result of the procedure call is stored as the table value. Because a simplified expression in Maple has a unique instance in memory, the address of the arguments can be used as the hash function. Therefore, searching a remember table is very fast.
Several kernel functions use remember tables including evalf, series, divide, normal, expand, diff, readlib, and frontend. The functions evalf, series, and divide are handled internally in a special way for the following reasons:
evalf and series need to store some additional environment information ('Digits' for evalf and 'Order' for series). Consequently, the entries for these are extended with the precision information. If a result is requested with the same or less precision than what is stored in the table, the table value is retrieved and rounded. If a result is produced with more precision than what is stored, it is stored in the table, replacing the lower precision value.
evalf remembers only function calls (this includes named constants); it does not remember the results of arithmetic operations.
If a division operation succeeds and the divisor is a nontrivial polynomial, the divide function stores the quotient in its remember table. Otherwise, no value is stored in the remember table.
If option remember is specified together with option system, at garbage collection time, the remember table entries which refer to expressions no longer in use elsewhere in the system are removed. This provides a relatively efficient use of remembering that does not waste storage for expressions that have disappeared from the expression space. As garbage collection time can be unpredictable, cache remember tables provide an alternate approach similar to option system, by remembering only the most recently computed results.
Maple Language Arrays and Tables
Tables and arrays are provided as data types in the Maple language through the table and array commands.
Note: Unlike the array command, the Array command creates a rectangular table, which is described in the following subsection. An array is a table for which the component indices must be integers within specified bounds. Tables and arrays are implemented using the Maple internal hash tables. Because of this, sparse arrays are equally as efficient as dense arrays. A table object consists of the following.
Index bounds (for arrays only)
A hash table of components
An indexing function
The components of a table T are accessed using a subscript syntax (for example, T[a,b*cos(x)]). Since a simplified expression is guaranteed to have a unique instance in memory, the address of the simplified index is used as the hash key for a component. If no component exists for a given index, then the indexed expression is returned.
The semantics of indexing into a table are described by its indexing function. Aside from the default, general indexing, some indexing functions are provided by the Maple kernel. Other indexing functions are loaded from the library or are supplied by the user.
Maple Language Rectangular Tables
Rectangular tables (as implemented by the RTABLE structure) can use a variety of storage formats. One format, Maple-sparse, is identical to that used in tables and arrays, namely a hash table. For Matrices, there is another sparse format, NAG-sparse, which uses one vector for each dimension to record indices, and one more vector to record the values of the entries. Most RTABLE storage formats are dense, the simplest being the rectangular format. Other dense formats include upper-triangular and band, where storage is allocated only for the upper triangle or a band of elements respectively. To the user, rectangular tables appear as objects of type Array, Matrix, Vector[row], and Vector[column]. Note that an Array is not the same as an array. For more information, refer to the Array and array(deprecated) help pages.
Portability
The Maple kernel and the command-line interface are not associated with any one operating system or hardware architecture. The Maple kernel is designed to be portable to any system which supports a C compiler, a flat address space, and a 32-bit or 64-bit word size. Refer to the Install.html file on your product installation disc for a list of currently supported operating system versions.
Most of the source code comprising the kernel is the same across all platforms. Extensive use of macros and conditional compilation take care of platform dependencies, such as word size, byte ordering, storage alignment requirements, differences in hardware floating point support, and sometimes, C compiler bugs.
The Maple library is interpreted by the Maple kernel. Therefore, other than issues such as maximum object size, it is completely independent of the underlying architecture.
The Standard worksheet graphical user interface is implemented in Java, which is platform-independent. This includes custom GUI features such as embedded components and Maplets.
Download Help Document