Previous Home Contents Next

Chapter 18: Using Aldor with AXIOM

18.1 Using Aldor from within AXIOM

18.2 Summary of changes for conversion to Aldor

18.3 Conversion example: two packages

18.4 Conversion example: a domain

18.5 Language changes for AXIOM version 2

18.6 Changes for version 2 regarding types and the library

18.7 Using the AXIOM-to-Aldor translator

18.8 Changes made ot the interpreter language

18.9 Using free functions with AXIOM

18.10 Efficiency

18.11 Details of system commands

18.12 Using Aldor outside AXIOM for AXIOM

18.13 Fine print

Aldor programs can provide new domains, categories and packages for use in AXIOM. These are fully interoperable with existing code in the AXIOM library which was compiled with the old (pre-version 2.0) system compiler. Aldor domains may be passed to AXIOM constructors and vice-versa, and Aldor programs can refer to anything in the AXIOM library.

In this chapter we describe how to use the Aldor compiler to extend the AXIOM library, and how to use these extensions interactively within AXIOM. We describe how to convert a file written for the old AXIOM system compiler to one written in Aldor. We also note some of the changes made to the AXIOM library for version 2.0 and contrast some features of the AXIOM and Aldor base libraries.

18.1 : Using Aldor from withing AXIOM

This section describes how to create and use Aldor programs within the AXIOM environment. These are the basic steps involved:

  1. Create a file with the Aldor program you wish to use. This file should have a name ending in .as so it will be recognized as Aldor source code. For example, a suitable file name might be
  2. Compile the source code using the )compile command. For instance,
  3. If the compilation was not successful, edit the source code and recompile.
  4. Once a compilation is successful, the program is immediately accessible in the AXIOM session. It may now be tested and, if necessary, modified and recompiled.

Figure 18.1: "" -- Extending the AXIOM library

#include ""

MatrixSymmetry(R:Field): with

        symmetricPart : Matrix R -> Matrix R
                ++ `symmetricPart(M)' returns a symmetric
                ++ matrix `S', computed as `(M + transpose M)/2'.
                ++ The difference `M - S' is antisymmetric.

        antisymmetricPart : Matrix R -> Matrix R
                ++ `antisymmetricPart(M)' returns an antisymmetric
                ++ matrix `A', computed as `(M - transpose M)/2'.
                ++ The difference `M - A' is symmetric.
== add
        import from R, Integer

        symmetricPart(m: Matrix R): Matrix R ==
                mt := transpose m
                inv(2::R) * (m + mt)

        antisymmetricPart(m: Matrix R): Matrix R ==
                mt := transpose m
                inv(2::R) * (m - mt)

Note that you need not exit and re-enter AXIOM every time you need to edit your code. If possible, have an editing window available so that you can switch back and forth between AXIOM and the editor while you debug.

There are several differences between the Aldor language and the language used in AXIOM Version 1. See section 18.2 for a summary of the differences which are likely to affect AXIOM-style programs.

figure 18.1 shows a simple Aldor program using the AXIOM library. This program illustrates an important point:

When you write source code that is intended to make use of or extend the AXIOM library you should include in your program the line:

instead of:

The commands to compile and use this program from an AXIOM session are shown in Figure 18.2.

Figure 18.2: Compiling and using an Aldor program within AXIOM

% axiom

Startin the Axiom Computer Algebra System
AIX Version 3.2 for IBM Risc System/6000

(1) -> )compile

   Compiling AXIOM source code from file /home/smwatt/ using
      A# compiler and options
         -O -Fasy -Fao -Flsp -laxiom -Mno-ALDOR_W_WillObsolete -DAxiom
      Use the system command )set axiomxl args to change these options.
   Compiling Lisp ource code from file ./matops.lsp
   Issuing )library command for matops
   Reading /home/smwatt/matops.asy
   MatrixSymmetry is now explicitly exposed in frame frame0
   MatrixSymmetry will be automatically loaded when needed from

(1) ->m := matrix[[1/2,1/3],[1/4,1/5]]

        +1  1+
        |-  -|
        |2  3|
   (1)  |    |
        |1  1|
        |-  -|
        +4  5+
                                        Type: Matrix Fraction Integer
(2) ->s := symmetricPart m

        +1   7 +
        |-   --|
        |2   24|
   (2)  |      |
        |7   1 |
        |--  - |
        +24  5 +
                                        Type: Matrix Fraction Integer
(3) ->a := antisymmetricPart m

        +      1 +
        | 0    --|
        |      24|
   (3)  |        |
        |  1     |
        |- --  0 |
        +  24    +
                                        Type: Matrix Fraction Integer
(4) -> )quit

It is possible to use compiled Aldor code in subsequent AXIOM sessions. To do this, use the )library system command which updates the databases in your AXIOM session and ensures that your code is automatically loaded when it is needed. Continuing our example above, the compiled form of could be used within AXIOM by issuing:

If necessary, you can qualify the filename with a directory, as in

These steps are shown for the program in figure 18.3

Figure 18.3: A precompiled Aldor program in a later AXIOM session

% axiom

Starting the Axiom Computer Algebra System
AIX Version 3.2 for IBM Risc System/6000

(1) -> )library matops

   Reading /home/smwatt/matops.asy
   MatrixSymmetry is now explicitly exposed in frame frame0
   MatrixSymmetry will be automatically loaded when needed from 

(1) ->m := matrix[[1,2],[3,4]]

       +1  2+
  (1)  |    |
       +3  4+
                                                 Type: Matrix Integer
(2) ->symmetricPart m

       +   5+
       |1  -|
       |   2|
  (2)  |    |
       |5   |
       |-  4|
       +2   +
                                        Type: Matrix Fraction Integer
(3) -> )quit

A number of input files giving examples of using Aldor with AXIOM are distributed with version 2.0 of the AXIOM system. These files are located in the ``input'' directory and may be listed, on Unix, using the command

These files show how to compile, load and use Aldor code. These input files can be run using the )read system command as follows:

Chapter 23 contains a more significant example of a package written in Aldor to extend the AXIOM library. This program computes Hilbert functions for monomial ideals (see section 23.21).

There are several ways to learn about what is in the AXIOM library but the best way is probably to use the HyperDoc Browser. The Browser is described within the AXIOM system documentation.

Several things happen ``under the covers'' in the above basic steps. Section 18.11 describes what is going on in more detail and gives more information about the options which are available.

18.2 : Summary of changes for conversion to Aldor

We summarize the differences which are you are likely to encounter when converting a file written for the old AXIOM library compiler to Aldor. For more details, please see section 18.5 and section 18.6.

This section is intended for people who have used the AXIOM Version 1 library compiler. Here, we do not touch upon any aspects of Aldor which have no counterpart in the old language. For this, please refer to part II.

18.3 : Conversion example: two packages

Here is an example of a small package from the AXIOM library source file pdecomp.spad:

To convert this to an Aldor file, we only need to change ``^''Equals to ``~''Equals and to add declarations to the inner function compose. In addition, the )abbreviate command is not supported by the Aldor compiler. Finally, we must place the lines

at the start of the file.

Here is the converted code:

Now we will begin converting the second package in pdecomp.spad:

The variable i on line 17 was intended to be a AXIOMTypeNonNegativeInteger, so we declare it and that brings NNI into scope. On line 18, the AXIOMFundivide returns a record type. By again declaring fr to be a record type, we cause this type to be imported and this makes the record extraction operations available.

Because untagged unions are no longer supported, we convert AXIOMTypeUnion(UP, "failed") to AXIOMTypeUnion(value1:UP, failed:'failed'), allowing us to create union values using [ ] and extract them using .value1.

Here is a conversion of the preceding code to Aldor:

Note the use of [ ] to create union values in lines 24 and 26.

18.4 : Conversion example: a domain

Here is an example of how to convert a domain from AXIOM to Aldor. It is a piece of the definition of AXIOMTypeQuaternion from quat.spad:

In order to translate this to Aldor, the following changes must be made:

Here is the converted code:

Note that the default variable declarations are introduced by the keyword default, and that each function definition must have its arguments and return type declared.

18.5 : Language changes for AXIOM version 2

A source of possible confusion is that there are now three similar but different programming languages associated with AXIOM:

The old system compiler language is now considered obsolete and the AXIOM library is actively being translated into the Aldor language. The old system compiler and its language will only be supported for as long as it takes to perform this translation.

The language supported by the Aldor compiler is more general and consistent than that supported by the old AXIOM compiler. Over ten years of experience with the older language helped us produce a tighter, more powerful, and more elegant programming language.

For those who know these languages, the difference between the old AXIOM language and Aldor is similar to the difference between MAC Lisp and Scheme: the syntaxes are very similar, but the semantics of the new language are more uniform.

This section discusses in more detail the language-related items of section 18.2. It covers those language aspects necessary to convert programs for the old AXIOM compiler to programs in Aldor.

The Aldor compiler uses % to refer to the domain or category being defined while the AXIOM compiler used $ before Version 2. The AXIOM compiler present in Version 2 also uses %.

A sequence is a series of expressions evaluated in the order in which they appear, except as modified by control expressions such as break, break return, return iterate, and by iterate if-then-else constructions. if The value of a sequence is the value of the expression last evaluated in that sequence.

A sequence can be constructed in two ways:

  1. the expressions can be separated by semicolons and the resulting expression surrounded by parentheses or braces ({ and }), or
  2. the expressions can be written on succeeding lines with each line indented the same number of spaces. A sequence entered in this form is called a pile.

Almost all of the AXIOM library written for the old compiler uses piling to create sequences. The Aldor compiler does not use piling unless you include the By default, the compiler uses the semicolon/braces method for creating sequences. This is code written using piling:

This is the same code written using braces and semicolons. Indentation has no effect here, other than to make the code easier to read.

The Aldor language uses the default keyword instead of default add when defining category defaults. Here is a sample using default:

Here is the same sample as it would have been written for the old compiler (translating the ``$'' to ``%''):

In fact, the Aldor compiler allows multiple default statements:

The default keyword can also now be used to set default type declarations for function parameters. However, be warned that in some AXIOM code defaults are omitted.

Macro definitions in the Aldor language can be written with a macro/== form or with ==>:

Only the second form is supported by the old compiler. Macros can also now be parameterized:

Aldor introduces several new keywords or extended uses for existing keywords. Please read the sections in this document about the following terms and keywords:

default, generate, define, import, export, yield, extend
default generate define import export yield extend

Chapters 11, 12, and 13 of the book AXIOM: The Scientific Computation System by Jenks and Sutor are now largely obsolete. Use the information in this Aldor document for writing and compiling domain and category constructors.

Comments that document constructors and operations are now created in a slightly different way. If a line starts with three or more plus signs (``++'') then the comment belongs to the declaration or definition following the comments. If a line starts with just two plus signs then the comment belongs to the preceding declaration or definition. (This allows documentation comments to follow the semicolon.)

The first comment block is associated with AXIOMTypeString whereas the second block is associated with AXIOMFunnew. These comments can be viewed, for example, from within the HyperDoc Browser.

To ease the chore of upgrading your .spad files (old .as files (Aldor compiler), the )compile command has been given a )translate option. This invokes a special version of the old compiler which parses and analyzes your old code and produces augmented code using the new syntax. Please be aware that the translation is not necessarily one hundred percent complete or correct. You should attempt to compile the output with the Aldor compiler and make any necessary corrections. Please see section 18.7 for an example and more information.

Also, if you have any private .spad files (that is, library files that were not shipped with AXIOM), you will need to recompile them with the old system compiler to use them with this version of AXIOM. For example, if you wrote the file regress.spad, then you should issue )compile regress.spad before trying to use it.

18.6 : Changes for version 2 regarding types and the library

The biggest difference you will find in converting files to Aldor is that you must be very explicit about which types are imported into the compilation scope. The old AXIOM compiler would automatically import types as it encountered them during the compilation process. The Aldor compiler will only import types appearing in declarations or in explicit import statements. In the previous example the only type in scope during the compilation of compose was the type UP. In fact not even AXIOMTypeInteger is automatically brought into scope. In Aldor, types are brought into scope only by explicit import statements or by appearing on the right hand side of import declarations.

Untagged unions are not supported by Aldor, thus all unions must be converted to tagged unions. This means that Union(Integer, Float) needs to become something like AXIOMTypeUnion(i:Integer, f:Float). The case statement requires the tag as its first argument, case thus you write x case i instead of x case Integer. Converting to and from tagged unions is essentially the same as with AXIOMTypeRecord types. To create a union value from one of its branches, you wrap the value in square brackets, thus [3.3] converts the float value ``3.3'' to a union value. Similarly, if x has type AXIOMTypeUnion(i:Integer, f:Float), x.i converts x to an Integer value taking a runtime error if x was in the other branch of the union (for more information on unions in Aldor see part II). Partial functions in old AXIOM were often declared as returning AXIOMTypeUnion(%, "failed"); by convention this is represented in Aldor as AXIOMTypeUnion(value1:%, failed: 'failed') (recall that 'failed' is syntactic shorthand for AXIOMTypeEnumeration(failed)).

The old AXIOM type AXIOMTypeVoid is obsolete in Aldor. Instead of declaring that a function returns AXIOMTypeVoid to indicate that its values are never used, you can declare that the function returns zero values using (). For example:


The SmallFloat domain has been renamed AXIOMTypeDoubleFloat and SmallInteger has been renamed AXIOMTypeSingleInteger. The new abbreviations are AXIOMTypeDFLOAT and AXIOMTypeSINT, respectively. We have defined the macro SF, the old abbreviation for SmallFloat, to expand to AXIOMTypeDoubleFloat, and modified the documentation and input file examples to use the new names and abbreviations. You should do the same in any private AXIOM files you have.

The AXIOMTypeBasicType category has been added near the root of the AXIOM category hierarchy for compatibility with Aldor. As now implemented, AXIOMTypeBasicType declares the ``=='' and ``1#1~''Equals operations for testing equality and inequality respectively, and a AXIOMFunFromsampleBasicType operation for obtaining a sample member of a domain. The AXIOMTypeSetCategory category has changed since some of its operations have been moved to AXIOMTypeBasicCategory. It now also contains a AXIOMFunFromhashSetCategory operation for computing a hash code for an object, and a AXIOMFunFromlatexSetCategory operation for obtaining a LATEX representation of an object in a string.

18.7 : Using the AXIOM-to-Aldor translator

Version 2.0 of AXIOM contains an experimental translator that helps you to convert files from AXIOM to Aldor. This translator is still under development and is known to be incomplete, but can often provide a useful first approximation for the converted file. By convention, files with file extension .spad are intended for the old compiler, while files with file extension .as are processed by Aldor. The translator modifies the old compiler so that while compiling the source .spad file, it generates an equivalent .as file. To invoke the translator you add the )translate option to your )compile command.

The code produced by the translator does not use #pile: instead of being indentation sensitive it explicitly uses ; and {}. During the translation process - comments are currently dropped, so they need to be added by hand later. Note that ++ comments which are intended to precede the object they describe need +++ in Aldor. Here is some .spad source code which is a simplified version of fmod.spad

This was translated using the command:
)compile fmod2.spad )translate

The following is an edited version of the result of the translation:

For this particular example very few hand edits were required: in the definition of recip, the call to explode was added to convert the record output of extendedEuclidean to a tuple for tuple assignment, and a per was inserted in the next to last line. In general the translator will make most necessary syntactic changes, and will try to add the necessary import lines. It currently needs some help in converting union references and sometimes omits or adds extraneous rep and per calls.

18.8 : Changes made to the interpreter language

The leave keyword has been replaced by the break keyword for compatibility with the Aldor language.

Curly braces are no longer used to create sets. Instead, use AXIOMFunset followed by a bracketed expression: for example,

Curly braces are now used to enclose compound expressions, such as sequences.

18.9 : Using free functios with AXIOM

A free function is a function defined at the top level in an Aldor source file, in other words the function definition is not contained within any domain or category.

Before AXIOM Version 2.0, library functions had to come from domains (or packages), but this is no longer the case. Whenever you use )library directly or indirectly (for example, by using )compile), the AXIOM databases are updated with knowledge of all constructors and free functions. After that, free functions participate fully in function selection within the AXIOM intepreter, and can also be passed to other functions, for example AXIOMFunmap. Note that they cannot be package-called since they do not come from a domain. You may need to more fully qualify the types of their arguments via declarations or coercions to get the exact operation you intend.

18.10 : Efficiency

The Aldor compiler's runtime efficiency is, in part, due to the inlining of functions at the point of their call. In order to do this, it must be able to find suitable code in an object file. Unfortunately the old AXIOM compiler does not produce compatible files, so it is not possible to inline old compiler code.

This is particularly important for domains such as AXIOMTypeNonNegativeInteger, AXIOMTypeInteger, and AXIOMTypeList: typical code spends much of its time manipulating objects of these types. The Aldor runtime therefore extends certain important domains with operations which are identical in name and function to their AXIOM counterparts, but can be found by the Aldor compiler because they are redefined by Aldor source code.

The files that implement this extension process are and axext_l.l which should be in the $ALDORROOT/samples/libax0 directory. The idea is that Aldor provides a mechanism for extending existing domains into objects which have more functionality -- we use this to change (in this case, make more efficient) the existing operations.

This is done for the low level datatypes, such as integers, floats and some aggregate types (currently AXIOMTypeList and AXIOMTypeVector). Algebraic datatypes such as polynomials and expressions have not been extended in this way.

A subset of the Integer extension is shown below: extend

This will ensure that whenever the Aldor compiler finds a call to +, and it wishes to inline the call, a call to the FOAM builtin BIntPlus will be generated, rather than a much more expensive call to an AXIOM-defined function.

Similarly, it is possible to define extensions in terms of functions (or macros) imported from Foreign(Lisp). The Lisp function should be defined in an auxilliary lisp file, which may be compiled and loaded into the AXIOM system.

This course of redefining AXIOM operations should be a last resort used in order to gain efficiency, because any changes to the representation of a domain must be reflected in both the AXIOM library, and in the Aldor and Lisp code which defines the extension.

18.11 : Details of system commands

In this section we describe in detail three AXIOM system commands that are useful when compiling Aldor files within AXIOM:

We've already seen examples of the last two commands in the previous section.

The )compile system command acts as a front-end to both the Aldor compiler and the old AXIOM system compiler. In what follows we shall only describe the options as they pertain to Aldor; see the AXIOM system command documentation for additional information regarding the old system compiler.

The first thing )compile does is look for a source code filename among its arguments. Thus the following commands:

all invoke )compiler on the file /u/jones/apps/ if the current AXIOM working directory is /u/jones/apps. (Recall that you can set the working directory via the )cd command. If you don't set it explicitly, it is the directory from which you started AXIOM.)

This is frequently all you need to do to compile your file. This simple command:

  1. Invokes the Aldor compiler to produce Lisp output.
  2. Calls the Lisp compiler if the Aldor compilation was successful.
  3. Uses the )library command to tell AXIOM about the contents of your compiled file and arrange to have those contents loaded on demand.

Should you not want the )library command automatically invoked, call )compile with the )nolibrary option. For example,

The general description of Aldor command line arguments is in chapter 27. The default options used by the )compile command can be viewed and set using the )set axiomxl args AXIOM system command. The current defaults are

These options mean:

To supplement these default arguments, use the )moreargs option on )compile. For example,

uses the default arguments and appends the -v (verbose) argument flag. The additional argument specification must be enclosed in double quotes.

To completely replace these default arguments for a particular use of )compile, use the )onlyargs option. For example,

only uses the -v (verbose) and -O (optimize) arguments. The argument specification must be enclosed in double quotes. In this example, Lisp code is not produced and so the compilation output will not be available to AXIOM.

To completely replace the default arguments for all calls to )compile within your AXIOM session, use )set axiomxl args. For example, to use the above arguments for all compilations, issue

Make sure you include the necessary -l and -Y arguments along with those needed for Lisp file creation. As above, the argument specification must be enclosed in double quotes.

By default, the )library system command exposes all domains and categories it processes. This means that the AXIOM intepreter will consider those domains and categories when it is trying to resolve a reference to a function. Sometimes domains and categories should not be exposed. For example, a domain may just be used privately by another domain and may not be meant for top-level use. The )library command should still be used though, so that the code will be loaded on demand. In this case, you should use the )nolibrary option on )compile and the )noexpose option in the )library command. For example,

Once you have established your own collection of compiled code, you may find it handy to use the )dir option on the )library command. This causes )library to process all compiled code in the specified directory. For example,

You must give an explicit directory after )dir, even if you want all compiled code in the current working directory processed, i.e.

The )compile command works with several file extensions. We saw above what happens when it is invoked on a file with extension .as. A .ao file is a portable binary compiled version of a .as file, and )compile simply passes the .ao file on to Aldor. The generated Lisp file is compiled and )library is automatically called, just as if you had specified a .as file.

A .al file is an archive file containing .ao files. The   archive is created (on Unix systems) with the ar program. When )compile is given a .al file, it creates a directory whose name is based on that of the archive. For example, if you issue

the directory mylib.axldir is created. All members of the archive are unarchived into the directory and )compile is called on each .ao file found. It is your responsibility to remove the directory and its contents, if you choose to do so.

A .lsp file is a Lisp source file, presumably, in our context, generated by Aldor when called with the -Flsp option. When )compile is used with a .lsp file, the Lisp file is compiled and )library is called. You must also have a .asy file present, generated from the same source file.  

Finally, when called with a file having the extension .spad, the )compile command invokes the old AXIOM system compiler.

18.12 : Using Aldor outside AXIOM for AXIOM

Section 18.11 discusses what really happens when you invoke the )compile system command from within AXIOM. If you invoke Aldor manually from the operating system prompt (or from a front-end windowed application), you must use the proper options so that all files needed by AXIOM are generated. You must include the options

-O -Fasy -Fao -Flsp -laxiom -DAxiom
in your final compilation before use by AXIOM. In addition, the files must be created into a writable directory that you then intend to access via the AXIOM )cd or )library )dir system commands.

Note that you cannot test the execution of your code except by starting AXIOM and then loading and executing the compiled version. There are several reasons why you might want to develop your code outside AXIOM:

  1. AXIOM may not be available on the machine on which you have Aldor installed.
  2. You do not want to incur the paging delays of having AXIOM loaded and then invoking Aldor.

Now we look at these options and discuss which ones you might want to leave out in the early stages of developing your code.

This flag indicates that full optimization be performed on generated code. You need not use this in the early stages of development since you will not actually be executing your code. Optimization is also time consuming.
The presence of this flag causes a .asy file to be generated. This file contains symbolic information about your code that was gathered and generated during compilation. The file is needed by AXIOM and can be used by library browsers.
Always include this flag. It causes Aldor to create a portable binary data .ao file from your file. This is needed by AXIOM and during the compilation of other files that depend on the contents of the current file.
A Lisp file is created when you specify this option. Omit it until you are ready to load your code into AXIOM.
This is required. It tells Aldor to look in the library for data about AXIOM constructors.
Not required, but useful. The Aldor libraries contain a terminating error condition that tests if the global assertion Axiom is true. This prevents you accidentally using   the Aldor libraries when you intended to use the AXIOM libraries.

Since compilation of large files can take some time, you may decide to include more and more of the ``optional'' arguments as your work proceeds, just in case the next compile is that lucky one where everything works!

When you are ready to test and use your code within AXIOM, start up AXIOM and then )cd to the directory containing your compiled code. Invoke )compile on each .lsp file you wish to use. The Lisp compiler will be invoked and the )library command will be called automatically unless you specify )nolibrary on )compile.

18.13 : Fine Print

At present, code from the AXIOM library will only run inside an AXIOM workspace. Consequentely Aldor programs extending the AXIOM library will only run inside AXIOM. For a later version, it is planned that the entire AXIOM library will be translated into Aldor, at which point it should be possible to call it from C, Fortran, or any other environment in which Aldor operates.

You must choose whether you wish to use the stand-alone Aldor library ( + libaldor) or whether you wish to use the AXIOM library ( + libaxiom). It is possible to use them both together, but some types exist in both libraries but have slightly different meanings, so using them together is quite tricky.

The AXIOM and Aldor libraries contain many constructors with the same names. Unfortunately, the like-named constructors often export different operations, complicating the translation of a program written for the Aldor library to one written for AXIOM. It is beyond the scope of this document to do a detailed comparison of the libraries.

We suggest you compare the exports of the constructors if you intend to start a project using the Aldor library and then shift to the AXIOM library, or vice versa. For example, look at AXIOMTypeComplex in the file in the Aldor library source directories and compare it to the definition in gaussian.spad in the AXIOM source ``algebra'' directory (this directory is probably $AXIOM/../../src/algebra on a Unix machine.)

When you compile a .as file within AXIOM, the -DAxiom global assertion is automatically added to the Aldor command line. The Aldor libraries will cause compilation to terminate when they are processed if this assertion is present. This gives you some measure of protection against trying to use Aldor libraries within AXIOM.

Previous Home Contents Next