Gap package 'if', by Marco Costantini
"The GAP InterFace to other Computer Algebra Systems (CAS)"

Version of 19 March 2006

##### INDEX #####

Index
Introduction
Interfaced CASes
Using OpenMath
Installation
Loading the package
User's manual
Advanced user's manual
Implementation: data types
Implementation: recursive objects
Implementation: incoherent object
If you want to implement
How to interface another CAS
Comparison to the singular package



##### INTRODUCTION #####

The purpose of this package is to allow the Gap user to access functions
of other CASes from within Gap, and to apply these functions to the Gap
objects. With this package, the user keeps working with Gap and, if he
needs a function of another CAS that is not present in Gap, he can use
that function via the interface.

The interface is designed to be modular and extensible, so that new CASes
can easily be added, and each part can be improved, without interference
with other parts.

This interface is oriented towards the kind-of-objects/data-types, and not
to the functions, because in this way it is much more general. The user
can use all the existing functions of the interfaced CAS and the interface
is not bounded to the state of implementation of the CASes: future CASes
functions and user-defined functions will be automatically supported. The
conversion of objects from Gap to an interfaced CAS and from it back to
Gap can be done using some 'ad hoc' functions, or using a standard for
representing mathematical objects, like OpenMath, if this standard is
supported by both Gap and the interfaced CAS.

The interface is planned as a Gap package containing a general engine,
plus several independent plug-ins/(sub)packages (one for each CAS), each
consisting of a Gap-readable description of the CAS characteristics. 

This package will be a generalization of the interface from Gap to
Singular, described at 
http://www-math.science.unitn.it/~costanti/#singular .

At the moment the package provides prototype interfaces to the following
CASes (see below): CoCoA, SINGULAR, PLURAL, KANT/KASH, PARI/GP, Risa/Asir,
MuPAD, Maple, Macaulay 2, Mathematica, Aribas, Yacas.

Now the interfaces to Maple, Pari/GP, and Yacas work, but they are not
exhaustively tested; for the complete implementation of the interfacess
to the other CASes are still missing most of the descriptions relatives
to the conversion of objects from Gap to the interfaced CASes and from
them back to Gap. Now, when these descriptions have not yet been
implemented, the conversion is achieved through the generic Gap
functions `String' and `EvalString'. These functions only work for a
small number of data types: those having the same representation both in
Gap and in the interfaced CAS, for instance for Integers or Rationals. 

I tested the interfaces to all the above CASes mainly using numerical
data types (see the file tst/examples.g for some examples). However, I
don't consider these tests exhaustive, and therefore I can not guarantee
that the interfaces are completely bug-free.

For these reasons, now (19 March 2006) I do not claim that this
package can already be used for useful computations, except probably with
Maple, Pari/GP, and Yacas.

This package has been tested with Linux, I don't know whether it works
or not with Windows.

As this package is still under development, the syntax may change in
future.

For contacts, write to costanti@science.unitn.it .
The latest version of this package is available at 
http://www-math.science.unitn.it/~costanti/#if  or
http://www.gap-system.org/Packages/if.html  .



##### INTERFACED CASES #####

Here is the list of the interfaced CASes. For each of them there is:

* the name, 
* a short description,
* the conventional name used in the function IF_Interface (see below),
* the web page.

The CASes are grouped by mathematical topic (according to my opinion, and
not necessarily to the CASes' authors).


ALGEBRAIC GEOMETRY:

* CoCoA
* COmputations in COmmutative Algebra
* IF_cocoa
* http://cocoa.dima.unige.it/


* Macaulay 2
* a CAS for algebraic geometry research
* IF_macaulay
* http://www.math.uiuc.edu/Macaulay2/


* SINGULAR
* A CAS for Polynomial Computations
* IF_singular	
* http://www.singular.uni-kl.de/


* PLURAL
* A CAS for Non-commutative Polynomial Computations
* IF_plural
* http://www.singular.uni-kl.de/plural/


NUMBER THEORY:

* KANT/KASH
* Computational Algebraic Number Theory / KAnt SHell
* IF_kash
* http://www.math.tu-berlin.de/~kant/kash.html


* PARI/GP (The interface is to the calculator GP, and not to the library
  Pari.)
* PARI/GP is a CAS designed for fast computations in number theory
* IF_pari_gp
* http://pari.math.u-bordeaux.fr/,
  http://www.math.u-psud.fr/~belabas/pari/


* ARIBAS (ARIBAS version at least 1.46 is required)
* ARIBAS is an interactive interpreter for big integer arithmetic and
  multi-precision floating point arithmetic
* IF_aribas
* http://www.mathematik.uni-muenchen.de/~forster/sw/aribas.html


GENERAL PURPOSE:


* Risa/Asir
* Risa is open source CAS under development at Fujitsu Laboratories
* IF_asir
* http://www.asir.org/


* MuPAD
* MuPAD is a mathematical expert system for doing symbolic and exact
  algebraic computations
* IF_mupad
* http://www.mupad.de/, http://www.mupad.com/, http://www.sciface.com/


* Maple
* Maple is a general-purpose commercial computer algebra system
* IF_maple	
* http://www.maplesoft.com/


* Mathematica
* Mathematica is a computer algebra system originally developed by 
  Stephen Wolfram and sold by his company Wolfram Research
* IF_mathematica
* http://www.wolfram.com/products/mathematica/index.html


* Yacas (Yacas version at least 1.0.62 is recommended. This interface
  requires the Gap package 'openmath', see below.)
* YACAS is an easy to use, general purpose Computer Algebra System, a
program for symbolic manipulation of mathematical expressions.
* IF_yacas
* http://yacas.sourceforge.net/


* An interface to Gap itself is also included as example, and for
comparison and debugging purposes (the conventional name is IF_gap).



##### USING OPENMATH #####

If a CAS supports the OpenMath standard (http://www.openmath.org), then
it is possible to use this standard to convert objects from Gap to the
interfaced CAS and vice versa. This requires the OpenMath Gap package,
available at http://www-math.science.unitn.it/~costanti/#openmath .

This package was written by Andrew Solomon some years ago; now I'm the
maintainer, and have updated it: this was necessary in order to extend
the functionality and to fix the bugs, and because both OpenMath and the
package mechanism of GAP have evolved in the meantime. Feel free to
contribute / report bugs / ask for help. For instance, you can help
implementing the new OpenMath Content Dictionaries (CDs).

The OpenMath Gap package requires compilation, in the way explained in
its README file, or in its dvi/ps/pdf manual.

If an interface to a CAS uses OpenMath, then the interface will support
only the types of objects that are supported, in a compatible way, by
the OpenMath implementations of both Gap and the CAS.


The interface to Yacas uses the OpenMath standard to convert objects.


This interface from Gap to itself can use both OpenMath, or directly
`String' and `EvalString'. After loading this package, do

IF_SHALL_GAP_USE_OPENMATH( true );

to use OpenMath, or do

IF_SHALL_GAP_USE_OPENMATH( false );

to use `String' and `EvalString'.


Both for Yacas and Gap, the OpenMath encoding is used only for the
objects passed as arguments, and not for the function in the interfaced
CAS.

The interfaces to all the other CASes don't use OpenMath.

When the 'if' package is loaded, it tries to load also the openmath
package; if the latter not compiled, then appears a warning saying that
"the program `gpipe' is not compiled." In this case, the interfaces that
use OpenMath will not work; however all the other interfaces will work.



##### INSTALLATION #####

You must have installed on your system the CASes that you want to use.
This package doesn't contain the interfaced CASes.

The package is contained in a compressed file; uncompress it preferably in
the directory `pkg` of the Gap distribution; after the uncompressing you
will have a structure like this (the actual structure may differ):

.
|-- CREDITS
|-- PackageInfo.g
|-- README
|-- cases
|   |-- aribas.g
|   |-- asir.g
|   |-- cocoa.g
|   |-- gap.g
|   |-- kash.g
|   |-- maple.g
|   |-- mupad.g
|   |-- pari_gp.g
|   |-- singular.g
|   `-- template.g
|-- doc
|   |-- composition.txt
|   |-- if.xml
|   |-- manual.pdf
|   `-- references.txt
|-- gap
|   |-- data.g
|   |-- interfaces.g
|   `-- parsedata.g
|-- init.g
`-- tst
    `-- examples.g


For every CAS you want to interface, you must specify where the CAS
executable file is located. To do this, open in the directory 'cases' the
file relative to the CAS of your interest, and look for the lines
IF_EXEC_NAME, IF_EXEC_FULL_PATH, IF_EXEC_OPTIONS. Now they contain the
values valid for my system. For instance:

in file cases/asir.g you will find

IF_EXEC_NAME[IF_asir] := "asir";
IF_EXEC_FULL_PATH[IF_asir] := "/home/costanti/asir2000/asir";
IF_EXEC_OPTIONS[IF_asir] := [];

In file cases/kash.g you will find

IF_EXEC_NAME[IF_kash] := "kash";
#IF_EXEC_FULL_PATH[IF_kash] := "";
IF_EXEC_OPTIONS[IF_kash] := [ "-l", "/usr/local/KASH_2.4/lib/"];

You may need to change them, in that case:

IF_EXEC_NAME[...] must be the name of the CAS executable file (the textual
one, not the graphical one: for instance for CoCoA use "cocoa" and not
"xcocoa").

IF_EXEC_FULL_PATH[...] must be the full path name of the executable file
(like for asir in the example above). If IF_EXEC_NAME[...] is in the
system path, then IF_EXEC_FULL_PATH[...] may be simply commented out like
I did for kash (but this doesn't work if the current directory is in the
path, and the current directory contains another directory of name
IF_EXEC_NAME[...]). If IF_EXEC_FULL_PATH[...] is not correctly given, the
interface will try to find the executable file somehow, in the system path
or in the current directory. If this fails, the interface will try to
give an informative error message. The directory separator is always '/',
even under DOS/Windows or MacOS.

IF_EXEC_OPTIONS[...] must specify the possible command line options (or []
if no options are given). For instance if you normally start Kash giving

kash -l /usr/local/KASH_2.4/lib/

then `IF_EXEC_OPTIONS[IF_kash] := [ "-l", "/usr/local/KASH_2.4/lib/"];`
will fit your needs.

Some of the options present in the various IF_EXEC_OPTIONS[...], are
needed by the interface: don't remove them. If you use a reconfiguration
file, you should check that it doesn't contain commands harmful for the
interface, or you must direct the CAS not to read this file, by putting
the appropriate option in IF_EXEC_OPTIONS[...].

For Maple and Yacas, check also the value of IF_FIRST_COMMAND, according
to your version, and to the instructions there.


Instead of modifying the file(s) in the directory `cases`, you may prepare
a file, with the values that work for you. After reading this package, you
will tell Gap to read your file, using the Gap command `Read'. For
instance, when I work on an other computer, I use:

Unbind( IF_EXEC_FULL_PATH[IF_asir] );
IF_EXEC_OPTIONS[IF_kash] := [];
Unbind( IF_EXEC_FULL_PATH[IF_pari_gp] );

(See the Gap documentation about `Unbind'.)

With such a file, you can keep the values that work for you, even if you
get a new version of this package.

The package 'if' doesn't require compilation.



##### LOADING THE PACKAGE #####

You may use this interface both as a Gap 4.4 package, and as files to be
read with `Read` (this was tested with both Gap 4.3 and Gap 4.4). 

To use it as a Gap 4.4 package, the comments in the init.g file must be
in this way:

List( IF_FILES, x -> ReadPackage( "if", x ) );
# for i in IF_FILES do Read( i ); od;

and then you can do `LoadPackage( "if" );` . 

To use it as files to be read with Read, the comments in the init.g file
must be in this way:

# List( IF_FILES, x -> ReadPackage( "if", x ) );
for i in IF_FILES do Read( i ); od;

Then `cd` to the directory containing init.g, and just do
`Read("init.g");`



##### USER'S MANUAL #####

(Almost all the Gap objects provided by this package have a name starting
with "IF_" .)

The normal user needs only the following function:

IF_Interface( conventional_CAS_name, "CAS_function_name", List_of_Gap_objects );

See above for the list of interfaced CASes and the
conventional_CAS_name's.  
"CAS_function_name" is the name of the function in the interfaced CAS, and
is given as a string. 
List_of_Gap_objects is a list of Gap objects, O1, O2, ..., On, that will
be used as arguments of CAS_function_name (it may be empty).


IF_Interface does the following:

a. converts each object O1, O2, ..., On in List_of_Gap_objects into the
   corresponding object P1, P2, ..., Pn, of the interfaced CAS;
b. sends the command "CAS_function_name ( P1, P2, ..., Pn )" to the
   interfaced CAS;
c. gets the output from the interfaced CAS;
d. converts it to the corresponding Gap object, and returns it to the user.

Example 1:

With the code already implemented, the interface can perform, for
instance, calculation like the following from within Gap, using the
function primes, omega, and nextprime, of Pari/Gp.

IF_Interface( IF_pari_gp, "primes", [10] );
IF_Interface( IF_pari_gp, "omega", [360] );
IF_Interface( IF_pari_gp, "nextprime", [119] );

Example 2:

In the following example the greatest common divisor of 1000 and 360 is
calculated using each CAS.

IF_Interface( IF_asir, "igcd", [1000, 360] );
IF_Interface( IF_cocoa, "GCD", [1000, 360] );
IF_Interface( IF_kash, "IntGcd", [1000,360] );
IF_Interface( IF_singular, "gcd", [1000, 360] );
IF_Interface( IF_plural, "gcd", [1000, 360] );
IF_Interface( IF_pari_gp, "gcd", [1000, 360] );
IF_Interface( IF_gap, "GcdInt", [1000, 360] );
IF_Interface( IF_aribas, "gcd", [1000, 360] );
IF_Interface( IF_mupad, "gcd", [1000, 360] );
IF_Interface( IF_maple, "gcd", [1000, 360] );
IF_Interface( IF_macaulay, "gcd", [1000, 360] );
IF_Interface( IF_mathematica, "GCD", [1000, 360] );
IF_Interface( IF_yacas, "Gcd", [1000, 360] );

This second example shows that it is possible to interface many CASes in
the same Gap session.

Example 3:

gap> IF_Interface(IF_mupad, "combinat::partitions::list", [4]);
 [ [ 4 ], [ 3, 1 ], [ 2, 2 ], [ 2, 1, 1 ], [ 1, 1, 1, 1 ] ]
 
gap> IF_Interface(IF_mupad, "combinat::tableaux::list", [[4,2]]);
 [ [ [ 5, 6 ], [ 1, 2, 3, 4 ] ], [ [ 4, 6 ], [ 1, 2, 3, 5 ] ],
   [ [ 3, 6 ], [ 1, 2, 4, 5 ] ], [ [ 2, 6 ], [ 1, 3, 4, 5 ] ],
   [ [ 4, 5 ], [ 1, 2, 3, 6 ] ], [ [ 3, 5 ], [ 1, 2, 4, 6 ] ],
   [ [ 2, 5 ], [ 1, 3, 4, 6 ] ], [ [ 3, 4 ], [ 1, 2, 5, 6 ] ],
   [ [ 2, 4 ], [ 1, 3, 5, 6 ] ] ]
 

Warnings:

1. The interface depends on the user-interface of each CAS: it may not
work if something in the user-interface is modified, for instance the CAS'
prompt, and in this case small changes may be necessary in the interface
to have it working again.


2. At the moment, if you need an interface to Singular, you are
suggested to use the interface provided by the Gap package singular, and
not this package, because now it is not yet completed.


3. Errors may occur on the side of the interfaced CAS, for example with
the following command:

IF_Interface(IF_gap, "Error", [] );

How to handle properly this kind of errors is still, for some CASes, an open
problem. At the moment, in case of errors on the side of the interfaced CAS,
the following is likely to happen (at least under Linux):

* CoCoA, Gap:
The result of the previous computation is returned, without any warning!

* PARI/GP, Risa/Asir, SINGULAR, PLURAL, KANT/KASH:
The result of the previous computation is returned, but an error message
is printed, by the interfaced CAS, in the so-called "standard error".
(Or an error message is printed, by the interfaced CAS, in the so-called
"standard error", and then the interface hangs (press <ctrl>-C).)

* ARIBAS:
The string "error" is returned.

* MuPAD:

Either the interface detects the error message from the CAS, and raises
an error on the Gap side, displaying that message, or the command that
caused the error is returned as a string.

* Maple: 
The interface detects the error message from the CAS, and raises an
error on the Gap side, displaying that message.

* Yacas
Either an error about OpenMath conversion happens, or the result of the
previous computation is returned, without any warning!


4. Usually Gap closes the interfaced CASes when Gap quits, or when the
command IF_CloseInterface (see below) is used. Nevertheless sometimes
(for instance in case of abnormal termination of Gap) an interfaced CAS
keeps running, and it is necessary to kill it by hand. 





##### ADVANCED USER'S MANUAL #####

The commands described here are only needed to interface the CASes at a
low level, or for debugging purposes. Here and below, we will use "IF_xxx"
to mean the generic conventional name of an interfaced CAS.

The following command 

SetInfoLevel( InfoInterfaces, 3 );

tells to Gap to print the input and the output of the interfaced CAS; it
may be useful for debugging purposes. This debugging information is
suppressed by

SetInfoLevel( InfoInterfaces, 0 );


The interface is based on the Gap function InputOutputLocalProcess (see
the Gap documentation about it). The command

IF_StartInterface( IF_xxx );

calls InputOutputLocalProcess to start the slave process; this allows
interaction between Gap and the interfaced CAS, and to send commands,
related to the objects in Gap, to the interfaced CAS.

As IF_Interface calls automatically IF_StartInterface, you need to call
IF_StartInterface only if you want to interact with the interfaced CAS at
lower level with IF_WriteAndRead (see below) before using IF_Interface.

In order to save system resources, the slave process can be closed with

IF_CloseInterface( IF_xxx );


With this interface, you can give any command to the interfaced CAS, using

IF_WriteAndRead( IF_xxx, "command_meaningful_for_IF_xxx" );

The output is returned as a string.



##### IMPLEMENTATION: DATA TYPES #####

Let us have a look at IF_DATA_TYPES[IF_xxx], that is a list of records (it
is still under construction), and contains the rules to convert objects
from Gap to the interfaces CAS, and back.

Its format is the following: for each data type T of the interfaced CAS
there is a record (whose name is also T) in IF_DATA_TYPES[IF_xxx] of (up to)
four elements:

1. a human readable string describing T (at the moment not used, but may be
   useful in future);
2. a Gap function that says, given a Gap object O, whether or not O is (by a
   mathematical point of view) of type T;
3. a Gap function that converts O into a string to be used as command to
   define O in the interfaced CAS;
4. a Gap function that converts a string, received as output from the CAS,
   into the corresponding Gap object; this function may also ask the
   interfaced CAS for more information about the object.

At the moment the elements 1. is present for every type (usually
copied and pasted from the CAS manual), and the others are present only
for the easiest types. For other types I will reuse, when possible, the
code used for interfacing Singular; when not, it will be necessary to
write ad hoc code.

At this stage, if no elements 2., 3., 4. are present for a given type,
then the Gap functions String and IF_EvalString (a variant of EvalString,
see the gap documentation about it), are used for a "raw" conversion 
Gap -> CAS and CAS -> Gap respectively. In this case there is no guarantee
that the conversion will work.

When all the elements 2., 3., 4. will be implemented, the function 
IF_Interface( IF_xxx, command, list_of_arguments );
will do the following:

a. determine for each object O_i in list_of_arguments its type T_i, using
   element 2.;
b. convert each O_i, using element 3. relative to its type T_i, giving,
   say, P_i;
c. type "command ( P_1, P_2, ..., P_n )" to the interfaced CAS;
d. ask the interfaced CAS for the type T_output of its output;
e. get the output;
f. convert it back to Gap using element 4. relative to the type T_output.


In this way, the interface is generic and is applicable to (almost) all
the functions (also to the user-defined ones), it's not specific for a
limited set of functions: if we can convert objects, then we can use any
function. Furthermore, the kind-of-objects/data-types are much less than
the functions.

Some functions will not be supported. For instance, in Singular there is
the function `pause` that waits until a keystroke is pressed; the
interface instead waits for the CAS prompt before sending it any new
keystroke, and so calling `pause` would hang the interface. However, the
unsupported functions like `pause` of Singular are only a few, and are not
mathematically useful.

What are missing now are the elements 2., 3., 4., and some stuff that I
already wrote for Singular, but that must be rewritten for this more
general setting.


It's also possible to give single commands directly to the interfaced
CAS using IF_WriteAndRead as said above: in this way, no conversion is
performed.



##### IMPLEMENTATION: RECURSIVE OBJECTS #####

The conversion of recursive objects is relatively easy to implement: it
has already been implemented in the package singular for the interface
from Gap to Singular. It is possible to use the same criteria to write the
conversion rules for the other CASes.

Let us however consider in detail the conversion of recursive object from
the interfaced CAS to Gap, which is more complex than the one from Gap to
the CAS.

In most CASes there are recursive object. Let us consider for instance a
polynomial P, whose coefficients are matrices M1, M2, ..., over
something else. Then the code to convert P has to take care of the
indeterminates and exponents and, for each sub-object, (in this case M1,
M2, ...) will call the function IF_ConvertToGap (this function is the
file gap/interfaces.g) to convert it. IF_ConvertToGap will call the
function to convert the matrices, and so on. Each of these functions may
need to use IF_WriteAndRead several times.

Also this was already implemented for Singular. Although in Singular most
of the types are not recursive, the lists are. The interface asks for each
element of a list its type, asks to print it again but alone, and converts
it. If an element of a list is another list, then the interface proceeds
recursively.


Another example: if in an interfaced CAS matrices are recursive, it will
be necessary something like the following. Let MP be the matrix in the
CAS, the function to be implemented could be for instance something like:

function (MP)
  ask number_of_rows;
  ask number_of_columns;
  MG:=[];
  for i in [1.. number_of_rows] do
    MG[i] :=[];
    for ii in [1..number_of_columns] do
      type := ask the type of MP[i][ii];
      MG[i][ii] := IF_ConvertToGap(IF_xxx, MP[i][ii], type );
    od;
  od;
  return MG;
end;


For the purpose of asking the interfaced CAS for information about
sub-objects, the functions IF_DATA_TYPES[IF_xxx][...][4] described above,
can take a second argument: a string containing the name of the sub-object
in the interfaced CAS. Something was used for Singular.


With this solution, all the conversions are made on the Gap side, like
what has been done for the Singular interface. Of course, there is the
possibility to write the code in the interfaced CAS that converts the CAS
objects into a description like an XML tree, for instance the OpenMath
encoding, and then it may be simpler for Gap to convert such description
into a Gap object.

If someone is interested in this kind of solution, and willing to
cooperate, I will be happy to evaluate the solution together.



##### IMPLEMENTATION: INCOHERENT OBJECT #####

In some CASes, some objects have a type that doesn't allow to convert them
to Gap objects of the correct mathematical type. Let us call these objects
`incoherent objects`.

For instance, in Pari/Gp, groups have the same type as vectors (because
they are represented internally in Pari/Gp by vectors). So if an output of
Pari/Gp is of type vector, there is no way to know whether it is really a
vector, or a group; so a Pari/Gp group is an incoherent object.
 
In the following example, we calculate directly in Pari/Gp (hence outside
the interface) the Galois group G of a polynomial P, using the function
`galoisinit`. We note that the type T of the output is the type vector,
and then we use G as argument for the function galoisfixedfield.

P = x^2 + 1
G = galoisinit( P )
T = type( G )
Q = galoisfixedfield( G, G.group[2], 2 )

The previous Pari/Gp code produces the following output:

? P = x^2 + 1
%1 = x^2 + 1
? G = galoisinit( P )
%2 = [x^2 + 1, [5, 16, 152587890625], [102662389557, 49925501068]~, [1, 1;
49925501068, 102662389557], 2, [Vecsmall([1, 2]), Vecsmall([2, 1])],
[Vecsmall([2, 1])], Vecsmall([2])]
? T = type( G )
%3 = "t_VEC"
? Q = galoisfixedfield( G, G.group[2], 2 )
%4 = [x, 0, [x^2 + 1]]


Similarly, in Singular, curves are of the type "list" as the lists, see
http://www.singular.uni-kl.de/DEMO_HTML/Examples/Coding/coding_example.html
for some examples.


There are some possibilities to cope with these situations.

A first possibility is to handle the incoherent objects as the other
objects. This way to operate should cause no problems if the user is aware
of the existence of incoherent objects. With reference to the previous
example relative to Pari/Gp, the incoherent objects (groups) are
represented as vectors and, as vectors, may be converted into Gap vectors.
Of course these Gap vectors are meaningless in Gap, and hence should not
be used for Gap computations. However they can be used as arguments for
the following Pari/Gp functions called via the interface: in these cases
they will be converted back to Pari/Gp as vectors, but Pari/Gp will
recognize them as groups. In the previous example, even if converting G in
Gap will give a meaningless vector, this vector can be sent back to
Pari/Gp via IF_Interface, as argument for galoisfixedfield.

A second possibility is bases on the fact that the incoherent objects are
usually not used directly as input or output.  As we have seen in the
previous example, although G is useful for the next computations, is
neither meaningful as a final result for the user, nor it is provided as
the first input. I mean: the input of the whole code is P, the output Q,
and G is not entered, nor read by the user.

So the user might write a macro (user defined) function, say F, in the
interfaced CAS, that encloses the code involving the incoherent objects.
In the previous example, F would be the function sending P into Q. (The
problem of giving F to the interfaced CAS when it is a slave process of
Gap is a solvable problem). Then the user may call F from Gap using the
interface.

Another possibility, if there is only a limited number of kinds of
incoherent objects in the CAS, is to write for each of them the functions
to convert it from Gap to the CAS and vice versa. I mean functions like
`galoisexport` in Pari/Gp.

A further possibility is the following one. The incoherent complex objects
could be implemented in the interfaced CAS as other data types, besides
the already existing simple data types. Of course this is a nontrivial
change, and requires the agreement of several people...



##### IF YOU WANT TO IMPLEMENT #####

You are welcome to cooperate to this work.

Technical documentation about it will be written here.

Comments along the code are still missing. The lines of code are long, I
hope that this is not a problem with your screen.

Are you involved in / using / implementing / aware of OpenMath?


If you modify some files during a Gap session, and if the interface is
installed as a package, you can tell Gap to read again all the files of
the package, with the following command:

IF_RELOAD_FILES();




##### HOW TO INTERFACE ANOTHER CAS #####

In order to be interfaced by this package, a CAS must fulfill the 
"Rule of Composition: Design programs to be connected to other programs."
See the file doc/composition.txt about it.

It is necessary a list of the data types used by the CAS: I mean something
like, for instance (some links may be outdated),
http://www.singular.uni-kl.de/Manual/2-0-5/sing_66.htm#SEC106 ,
http://www.asir.org/manuals/html-eg/man_19.html#SEC19 ,
http://cocoa.dima.unige.it/download/doc/GUI_help/manual/p2c2s6.html .
(If the list is not available, you can ask the CAS' authors to provide it.)

Then it's necessary to have in CAS a function that takes as input any
object of the CAS, and that returns as output its type: I mean something
like, for instance,
http://www.singular.uni-kl.de/Manual/2-0-5/sing_286.htm#SEC326 ,
http://www.asir.org/manuals/html-eg/man_105.html#SEC105 ,
http://cocoa.dima.unige.it/download/doc/GUI_help/commands/cmd271.html .
(If there is no such function, you can ask the CAS' authors to provide it.)


Fill in the file cases/template.g to start to implement the interface to
another CAS.



##### COMPARISON TO THE SINGULAR PACKAGE #####

See the file gap/pkg/singular/gap/singular.g and the page
http://www-math.science.unitn.it/~costanti/gap_code/singular/chap1.html#s3ss12
to know how the interface will look like (but in that case there are
several things specific to Singular).

There are, at the moment, also some differences in the implementation. The
main differences from the package singular are that in the package singular:

* instead of one function as IF_WriteAndRead, there is a low level function 
  SingWriteAndReadUntilDone and a middle level function SingularCommand,
* the code for singular is not yet completely organized in a table like
  IF_DATA_TYPES,
* the Singular the function 'string' is used to display output.



##### ######

I am not involved it any of the interfaced CASes, nor are the CASes'
authors involved in this package.

This software is provided "as is", without any warranty. You can use it
according to the GNU General Public License, see
http://www.gnu.org/copyleft/gpl.html .

By the way, I speak also Italian and German (in case that you prefer to
write me in one of these languages).

Marco Costantini
costanti@science.unitn.it
http://www-math.science.unitn.it/~costanti/

