gp2c types and the description systemBy Bill Allombert |
The main feature GP2C adds above GP is the use of types. Types give a semantic to PARI objects, so that GP2C can generate code that use specialized (hence faster) PARI functions instead of generic ones. Please read the section ’Advanced use of GP2C’ in the GP2C manual for how to use the GP2C types and examples.
Such types are used in conjunctions with so-called descriptions which are stored in the field ’Description:’ of the file pari.desc and provide the actual C code to use depending of the types of the arguments. They are described in Section 2.
Abstractly, a GP2C type is a set of pairs (A,B) where A is a mathematical object and B its computer representation. Two different types can contain the same mathematical object, with a different computer representation. For example the type bool is the set {(true,1L), (false,0L)}, i.e. true and false with true coded by the C-long integer 1 and false coded by the C-long integer 0; the type negbool is the set {(true,0L), (false,1L)} which is the same set of mathematical objects, but now true is coded by the C-long integer 0 and false by the C-long integer 1.
For each GP2C type, there exists a C type Ct such that for all pairs (A,B) belonging to the type, the C type of B is Ct. This C type is specified by the description _typedef.
The GP2C types are preordered. Abstractly, we say that t1≺
t2 if and only if there is a map f such that (A,B)↦ (A,f(B))
defines a one-to-one mapping from t1 to t2.
Practically we restrict the relation ≺ to make it a partial order
such that any two types have an upper bound.
This partial order is defined by the chains in the description
_type_preorder. It can be printed by running gp2c -t.
The process of converting a mathematical object from one type to another is called casting. The casting methods known to GP2C are given by the _cast description.
In this section, we list the types known to PARI/GP. The current list is available in the description _typedef.
The following types are mainly for internal use inside GP2C.
These types are mainly defined to allow the use of inline member functions.
A C-Type is just a level of indirection toward real C types. C-types are defined by the descriptions _decl_base and _decl_ext. Each type belongs to a C-type as specified by the description _typedef.
The description system is a way to describe the PARI application programming interface in a way understandable by both the GP2C compiler and human beings. The present document is mostly addressed to this second category. We start by a simple example:
The description of the GP function sqr is
(int):int sqri($1) (mp):mp gsqr($1) (gen):gen gsqr($1)
Each line is called a rule, which in this case consists of three
parts. Let us consider the first one: the parts (int), :int and
sqri($1) are respectively called the pattern, type,
and action part.
When GP2C compiles sqr(1), it computes the types of the arguments
(here 1 is of type small) and matches them against the patterns
from top to bottom. The “best” rule is used; in case of a tie, the topmost
rule wins. Here, all three rules apply, and the first rule wins. Since the type
of this rule is int, GP2C sets the type of the expression
sqr(1) to int. The action part is sqri($1), so GP2C
generates the C code sqri($1) where $1 is replaced by the
code of the argument 1 cast to the pattern type (int). The result
is the C code sqri(gen_1).
Now a more complex example: the description of the GP function exp is
(real):real mpexp($1) (mp):mp:prec gexp($1, prec) (gen):gen:prec gexp($1, prec)
When GP2C compiles exp(1), it looks for the "best" rules.
The first rule cannot be used, because there is no way to cast a
small to a real, so it uses the second rule.
This time the result will be
of type mp. The extra part :prec is called a mode. The
mode ‘prec’ states that the action part will use the special ‘prec’
variable that holds the current real precision. This is obvious from
the action part code, but GP2C do not parse the action part so it
needs this mode. Note that the last rule is also valid and has the
same action part so would generate the exact same code. However, the
type of the expression would be less precise.
The description of the GP function matdet is
(gen, ?0):gen det($1) (gen, 1):gen det2($1) (gen, #small):gen $"incorrect flag in matdet" (gen, small):gen det0($1, $2)
We see several new pattern atoms:
Finally, we also see a new action $"…", which causes GP2C to display the error message and abort.
We now give a formal definition of descriptions.
A description is a line-separated list of rules.
A rule is a line of the form
(pattern):type:modelist action
Only the pattern part is mandatory, though most rules also include an action and a type.
A pattern is a comma-separated list of pattern atoms.
The type of a rule is a standard GP2C type.
A modelist is a colon-separated list of modes.
An action is a string (normally a piece of C code) that can include replacement strings. Replacement strings start by a $ and are substituted according to the replacement rules.
A pattern atom is one of the following, where type is any GP2C type, n any small integer, "str" any character string and ctype any C-type. A pattern atom can match an object.