# This file, by Marco Costantini, contains:
# * Update to function OMsymTable, according to the current
#   OpenMath CDs (for converting from OpenMath to GAP),
# * OMPut methods (for converting from GAP to OpenMath).


# The content of this file is not exhaustively tested!


Revision.("openmath/gap/new.g") :=
    "@(#)$Id: new.g,v 1.6 2006/01/13 23:01:23 gap Exp $";

#######################################################################
# From OpenMath to Gap

# CDs already in OMsymTable:
#  [ "algnums", "arith1", "cas", "group1", "integer", "linalg1", "list1", "logic1", "nums", 
#    "permgroup", "permut1", "relation1", "set1" ]


OMsymTable_new := [

# official CDs

[ "arith1", [
    [ "lcm", Lcm ],
    [ "gcd", Gcd ],
    [ "unary_minus", x -> -x ],
    [ "minus", x -> x[1] -x[2] ],
    [ "abs", x -> AbsoluteValue(x[1]) ],
  ],
],


[ "calculus1", [
    [ "diff", x -> Derivative(x[1]) ],
  ],
],


[ "complex1", [
    [ "complex_cartesian", x-> OMgapId([OMgap2ARGS(x), x[1]+E(4)*x[2]])[2]],
    [ "real", x-> OMgapId([OMgap1ARGS(x), x -> (x[1] + ComplexConjugate( x[1] )) / 2])[2]],
    [ "imaginary", x-> OMgapId([OMgap1ARGS(x), x -> (x[1] - ComplexConjugate( x[1] )) / 2]* -1/2 *E(4))[2]],
    [ "conjugate", x-> OMgapId([OMgap1ARGS(x), x -> ComplexConjugate( x[1] )])[2]],
  ]
],


[ "fns1", [
    [ "identity", x -> IdFunc(x[1]) ],
  ]
],


[ "integer1", [
    [ "factorof",  x -> IsZero( EuclideanRemainder( x[2], x[1] ) ) ],
    [ "factorial", x -> Factorial( x[1] ) ],
    [ "remainder", x -> EuclideanRemainder( x[1], x[2] ) ],
    [ "quotient", x -> EuclideanQuotient( x[1], x[2] ) ],
  ]
],


[ "interval1", [
    [ "integer_interval", x -> [ x[1] .. x[2] ] ]
  ]
],


[ "linalg1", [
    [ "determinant", x -> DeterminantMat(x[1]) ],
    [ "matrix_selector", x -> x[3][x[1]][x[2]] ],
    [ "transpose", x -> TransposedMat(x[1]) ],
    [ "vector_selector", x -> x[2][x[1]] ],
    [ "vectorproduct", x -> x[1]*x[2] ],
    [ "outerproduct", x -> TransposedMat([x[1]])*[x[2]] ]
  ]
],


[ "linalg2", [
    [ "matrixrow", OMgapMatrixRow],
    [ "vector", OMgapMatrixRow],
    [ "matrix", OMgapMatrix]
  ]
],


[ "logic1", [
    [ "equivalent", x -> x[1] and x[2] or not x[1] and not x[2] ],
    [ "implies", x -> not x[1] or x[2] ],
  ]
],


[ "minmax1", [
    [ "min", x -> Minimum(x[1]) ],
    [ "max", x-> Maximum(x[1]) ]
  ]
],


[ "nums1", [
    [ "rational", OMgapDivide ]
  ]
],


[ "relation3", [
    [ "equivalence_closure", x -> TransitiveClosureBinaryRelation( SymmetricClosureBinaryRelation(
ReflexiveClosureBinaryRelation( x[1] ) ) ) ],
    [ "transitive_closure", x ->TransitiveClosureBinaryRelation( x[1] ) ],
    [ "reflexive_closure", x ->ReflexiveClosureBinaryRelation( x[1] ) ],
    [ "symmetric_closure", x ->SymmetricClosureBinaryRelation( x[1] ) ],
    [ "is_transitive", x ->IsTransitiveBinaryRelation( x[1] ) ],
    [ "is_reflexive", x ->IsReflexiveBinaryRelation( x[1] ) ],
    [ "is_symmetric", x ->IsSymmetricBinaryRelation( x[1] ) ],
    [ "is_equivalence", x ->IsEquivalenceRelation( x[1] ) ],
  ]
],


[ "set1", [
    [ "cartesian_product", Cartesian ],
    [ "size", x -> Size( x[1] ) ],
    [ "suchthat", x->Filtered(x[1],x[2]) ],
    [ "subset", x -> IsSubset( x[2], x[1] ) ],
    [ "notin", x -> not x[1] in x[2] ],
    [ "prsubset", x -> IsSubset( x[2], x[1] ) and not IsEqualSet( x[2], x[1] ) ],
    [ "notsubset", x -> not IsSubset( x[2], x[1] ) ],
    [ "notprsubset", x -> not IsSubset( x[2], x[1] ) or IsEqualSet( x[2], x[1] ) ],
  ]
],


# experimental CDs


[ "permgrp", [
    [ "is_primitive", OMgapIsPrimitive ],
    [ "orbit", OMgapOrbit ],
    [ "stabilizer", OMgapStabilizer ],
    [ "is_transitive", OMgapIsTransitive ]
  ]
],


# pseudo CD "parigp", used for objects from Pari/GP



[ "parigp", [
    [ "t_INTMOD", x -> ZmodnZObj( x[2], x[1] ) ],
    [ "t_PADIC", x -> PadicNumber(PurePadicNumberFamily(x[1], LogInt(x[2], x[1])), x[3]) ],
  ]
],




];




OM_append := function (  )
    local  i, j, found;
    MakeReadWriteGlobal( "OMsymTable" );
    for i  in OMsymTable_new  do
        found := false;
        for j  in OMsymTable  do
            if j[1] = i[1]  then
                Append( j[2], i[2] );
                found := true;
                break;
            fi;
        od;
        if not found  then
            Add( OMsymTable, i );
        fi;
    od;
    MakeReadOnlyGlobal( "OMsymTable" );
end;

OM_append();

Unbind( OM_append );


#######################################################################
# From Gap to OpenMath


InstallMethod(OMPut, "for infinity", true,
[IsOutputStream, IsInfinity],0,
function(stream, x)
        OMWriteLine(stream, ["<OMS cd=\"nums1\" name=\"", x, "\" />"]);
end);




InstallMethod(OMPut, "for a range", true,
[IsOutputStream, IsRange and IsRangeRep],0,
function ( stream, x )

    if not x[2] - x[1] = 1  then
        TryNextMethod();
    fi;

    OMWriteLine( stream, [ "<OMA>" ] );
    OMIndent := OMIndent + 1;
        OMWriteLine( stream, [ "<OMS cd=\"interval1\" name=\"integer_interval\" />" ] );
        OMPut( stream, x[1] );
        OMPut( stream, x[Length( x )] );
    OMIndent := OMIndent - 1;
    OMWriteLine( stream, [ "</OMA>" ] );

end);



#InstallMethod(OMPut, "for a function", true,
#[IsOutputStream, IsFunction],0,
#function ( stream, x )
#    local i, ii;
#    for i  in OMsymTable  do
#        for ii  in i[2]  do
#            if x = ii[2]  then
#                OMWriteLine( stream, [ "<OMS cd=\"", i[1], "\" name=\"", ii[1], "\" />" ] );
#                return;
#            fi;
#        od;
#    od;
#    TryNextMethod();
#end);

