# The variables are explained in the file gap/data.g
# name := number;
IF_maple := 90;

IF_SUBPACKAGE_VERSION[IF_maple] := "dev";


IF_CAS_DESCRIPTION[IF_maple] :=
[ "Maple",
"Maple is a general-purpose commercial computer algebra system",
"http://www.maplesoft.com/" ];


IF_EXEC_NAME[IF_maple] := "maple";
#IF_EXEC_FULL_PATH[IF_maple] := "";
IF_EXEC_OPTIONS[IF_maple] := [ "-t" ];
# With Maple version >= 10 use the following:
# IF_EXEC_OPTIONS[IF_maple] := [ "-t", "-u" ];

IF_QUIT_COMMAND[IF_maple] := ";\nquit;";
IF_DISPLAY_VERSION[IF_maple] := "interface(version);";

# use the following with Maple version >= 6
IF_FIRST_COMMAND[IF_maple] := "interface( echo=0, screenwidth=infinity, errorcursor=false );";
# use the following with Maple version = 5.5
# IF_FIRST_COMMAND[IF_maple] := "interface( echo=0, screenwidth=9999, errorcursor=false );";
# use the following with Maple version < 5.5
# IF_FIRST_COMMAND[IF_maple] := "interface( echo=0, screenwidth=9999 );";


IF_FIRST_PROMPT[IF_maple] := "#-->";
IF_PROMPTS[IF_maple] := [ "\r#-->" ];
IF_FUNC_REMOVE_PROMPT[IF_maple] := function( OUT )
    local p;
    p := PositionSublist( OUT, "Warning" );
    if p <> fail  then
        Print( "#I  Warning in Maple: ", OUT{[ p .. PositionSublist( OUT, "\n", p ) ]} );
    fi;
    p := PositionSublist( OUT, "\n\033[0;1m" );
    if p <> fail  then
        Error( "in Maple: ", OUT{[ p .. PositionSublist( OUT, "\r#-->", p ) ]} );
    fi;
    # return ReplacedString( OUT, IF_PROMPTS[IF_maple][1], "" );
    # below, use ";" instead of "\n", with Maple version < 5.5
    return OUT{[ PositionSublist( OUT, "\n" ) + 1 .. Length( OUT ) - Length( IF_PROMPTS[IF_maple][1] ) -1 ]};
end;

IF_ASSIGN[IF_maple] := ":=";
IF_END_COMMAND[IF_maple] := ";";
IF_IS_THERE_PROMPT[IF_maple] := true;
IF_FUNC_TYPE[IF_maple] := "whattype";
IF_TYPE_IS_QUOTED[IF_maple] := false;

IF_STRING_ARE_QUOTED[IF_maple] := true;
IF_FUNC_STRING[IF_maple] := "proc(obj) convert(obj, string) end proc";
IF_FUNC_DISPLAY[IF_maple] := "";
IF_PROHIBITED_CHARS[IF_maple] := Union( [ 0 .. 31 ], [ 127, 128, 254, 255 ] ); 


  IF_mupad := "2b defined";
IF_Maple_op := function ( cas, obj, name, oper )
    local  nops, i, res, subname, subres, string;

    # Maple types handled by this function: 
    # `*`, `+`, `.`, `..`, `^`, fraction, complex, 
    # list, set, exprseq;

    # MuPAD types handled by this function:
    # DOM_COMPLEX, 

    Info( InfoInterfaces, 2, "IF_Maple_op, arg = ", obj, " ", name, " ", oper, "\n" );

    if ValueOption( "IF_TO_LIST" ) = true  then
        WriteLine( IF_IOLP[cas], Concatenation( name, "_ := [ ", name, " ];" ) );
        PopOptions( );
    else
        WriteLine( IF_IOLP[cas], Concatenation( name, "_ := ", name, ";" ) );
    fi;
    IF_READ_UNTIL_PROMPT( cas );
    name := Concatenation( name , "_" );

    nops := IF_Interface( cas, "nops", name );

    if oper = Add  then
        res := [  ];
    fi;

    for i  in [ 1 .. nops ]  do

        subname := Concatenation( name, String( i ) );
        if cas = IF_maple  then
            string := Concatenation( subname, " := op( ", String( i ), ", ", name, " );" );
        elif cas = IF_mupad  then
            string := Concatenation( subname, " := op( ", name, ", ", String( i ), " );" );
        fi;
        WriteLine( IF_IOLP[cas], string );
        IF_READ_UNTIL_PROMPT( cas );

        subres := IF_GET_CAS_OUTPUT( cas, subname );

        if oper = Add  then
            oper( res, subres );
        elif i = 1  then
            res := subres;
        elif oper = \^ and subres = 1/2  then
            return Sqrt( res );
        else
            res := oper( res, subres );
        fi;
    od;

    Info( InfoInterfaces, 2, "IF_Maple_op, res = ", res, "\n");


    return res;

end;



IF_MAPLE__X := Indeterminate( Rationals, "_X" : new );



IF_DATA_TYPES[IF_maple] := rec(

# whattype basic types


\`\*\` := [
"Arithmetic operators +, -, *, /, ^",
,
,
function( obj, name ) return IF_Maple_op( IF_maple, obj, name, \* ); end
],


\`\+\` := [
"Arithmetic operators +, -, *, /, ^",
,
,
function( obj, name ) return IF_Maple_op( IF_maple, obj, name, \+ ); end
],


\`\.\` := [
"operator for non-commutative or dot product multiplication",
,
,
function( obj, name ) return IF_Maple_op( IF_maple, obj, name, \* ); end
],


\`\.\.\` := [
"Expressions of Type range",
obj -> IsRange( obj ) and IsRangeRep( obj ) and obj[2] - obj[1] = 1,
obj -> Concatenation( String( obj[1] ), " .. ", String( obj[Length( obj )] ) ),
function( obj, name ) 
    return IF_Maple_op( IF_maple, obj, name, function( x, y ) return [ x .. y ]; end ); 
end
],


\`\:\:\` := [],

\`\<\` := [],

\`\<\=\` := [],

\`\<\>\` := [],

\`\=\` := [],


\`\^\` := [
"Arithmetic operators +, -, *, /, ^",
,
,
function( obj, name ) return IF_Maple_op( IF_maple, obj, name, \^ ); end
],


\`and\` := [],

array := [],


float := [
"Floating-point Numbers and Their Constructors",
,
,
IdFunc # Floating-point Numbers are not supported in Gap
],


fraction := [
"Fractions and the Fraction Constructor",
,
,
function( obj, name ) return IF_Maple_op( IF_maple, obj, name, \/ ); end
],


\function := [],

hfarray := [],

indexed := [],


integer := [
"Integers and the Integer Constructor",
IsInt,
String,
Int
],


\`not\` := [],

\`or\` := [],

procedure := [],

series := [],


string := [
"Strings",
IsString and IsStringRep,
IF_ParseGapString,
IF_EvalString
# use the following instead of IF_EvalString, with Maple version < 5.5
# function ( obj, name )
#     return IF_ConvertToGap( IF_maple, obj, "symbol" , name );
# end
],


symbol := [
"Names",
,
,
function( obj, name )
    local  type;

    # polynom
    WriteLine( IF_IOLP[IF_maple], Concatenation( "type( ", name, ", polynom );" ) );
    type := IF_READ_UNTIL_PROMPT( IF_maple );
    if type = "true" and obj = "_X"  then
        return IF_MAPLE__X;
    elif type = "true" and obj{[ 1 .. 2 ]} = "x_" and ForAll( obj{[ 3 .. Length( obj ) ]}, IsDigitChar )  then
        return Indeterminate( Rationals, Int( obj{[ 3 .. Length( obj ) ]} ) );
    fi;

    # boolean
    WriteLine( IF_IOLP[IF_maple], Concatenation( "type( ", name, ", boolean );" ) );
    type := IF_READ_UNTIL_PROMPT( IF_maple );
    if type = "true"  then
        if obj = "true"  then
            return true;
        elif obj = "false"  then
            return false;
        elif obj = "FAIL"  then
            return fail;
        fi;
    fi;

    return obj;

end
],


table := [],

uneval := [],

Array := [],


Matrix := [
"matrices",
obj -> IsMatrix( obj ) and ForAll( obj, x ->
    ForAll( x, y -> IF_Type(IF_maple, y) <> fail ) ),
function( obj )
    local  str, dim, i, j;
    dim := DimensionsMat( obj );
    str := "Matrix( ";
    Append( str, String( dim[1] ) );
    Append( str, ", " );
    Append( str, String( dim[2] ) );
    Append( str, ", [" );
    for i  in [ 1 .. dim[1] ]  do
        Append( str, "\n[" );
        for j  in [ 1 .. dim[2] ]  do
            Append( str, IF_ConvertFromGap( IF_maple, obj[i][j] ) );
            if not j = dim[2]  then
                Append( str, "," );
            fi;
            if j mod 50 = 0  then
                Append( str, "\n" );
            fi;
        od;
        if not i = dim[1]   then
            Append( str, "]," );
        else
            Append( str, "]" );
        fi;
    od;
    Append( str, "] )" );
    return str;
end,
function ( obj, name )
    local  dim, i, ii, mat, subname;
    WriteLine( IF_IOLP[IF_maple], Concatenation( name, "_ := ", name, ";" ) );
    IF_READ_UNTIL_PROMPT( IF_maple );
    name := Concatenation( name , "_" );
    WriteLine( IF_IOLP[IF_maple], Concatenation( "op( 1, ", name, " );" ) );
    dim := IF_READ_UNTIL_PROMPT( IF_maple );
    dim := List( SplitString( dim, ",", " " ), Int );
    mat := [  ];
    for i  in [ 1 .. dim[1] ]  do
        mat[i] := [  ];
        for ii  in [ 1 .. dim[2] ]  do
            subname := Concatenation( name, "elm_" );
            WriteLine( IF_IOLP[IF_maple], 
               Concatenation( subname, " := ", name, "[", String( i ), ",", String( ii ), "];" ) );
            IF_READ_UNTIL_PROMPT( IF_maple );
    
            mat[i][ii] := IF_GET_CAS_OUTPUT( IF_maple, subname );
        od;
    od;
    return mat;
end
],


Vector\[column\] := [],


Vector\[row\] := [
"Vector - construct a Vector",
obj -> IsRowVector( obj ) and ForAll( obj, y -> IF_Type(IF_maple, y) <> fail ),
function( obj )
    local  str, dim, i, j;
    dim := Length( obj );
    str := "Vector[row]( ";
    Append( str, String( dim ) );
    Append( str, ", [" );
    for i  in [ 1 .. dim ]  do
        Append( str, IF_ConvertFromGap( IF_maple, obj[i] ) );
        if not i = dim  then
            Append( str, "," );
        fi;
        if i mod 50 = 0  then
            Append( str, "\n" );
        fi;
    od;
    Append( str, "] )" );
    return str;
end,
function ( obj, name )
    local  dim, i, ii, vec, subname;
    WriteLine( IF_IOLP[IF_maple], Concatenation( name, "_ := ", name, ";" ) );
    IF_READ_UNTIL_PROMPT( IF_maple );
    name := Concatenation( name , "_" );
    WriteLine( IF_IOLP[IF_maple], Concatenation( "op( 1, ", name, " );" ) );
    dim := IF_READ_UNTIL_PROMPT( IF_maple );
    dim := Int( dim );
    vec := [  ];
    for i  in [ 1 .. dim ]  do
            subname := Concatenation( name, "elm_" );
            WriteLine( IF_IOLP[IF_maple], 
               Concatenation( subname, " := ", name, "[", String( i ), "];" ) );
            IF_READ_UNTIL_PROMPT( IF_maple );
    
            vec[i] := IF_GET_CAS_OUTPUT( IF_maple, subname );
    od;
    return vec;
end
],


list := [
"Sets and Lists",
obj -> IsDenseList( obj ) and ForAll( obj, y -> IF_Type(IF_maple, y) <> fail ),
obj -> IF_ParseGapList( IF_maple, obj, "[", "]" ),
function( obj, name ) return IF_Maple_op( IF_maple, obj, name, Add ); end
],


set := [
"Sets and Lists",
obj -> IsDenseList( obj ) and ForAll( obj, y -> IF_Type(IF_maple, y) <> fail ),
obj -> IF_ParseGapList( IF_maple, obj, "{", "}" ),
function( obj, name ) return IF_Maple_op( IF_maple, obj, name, Add ); end
],


exprseq := [
"Expression Sequences",
obj -> IsDenseList( obj ) and ForAll( obj, y -> IF_Type(IF_maple, y) <> fail ),
obj -> IF_ParseGapList( IF_maple, obj, "op(", ")" ),
function( obj, name ) return IF_Maple_op( IF_maple, obj, name, Add : IF_TO_LIST ); end
],



# Other types


boolean := [
"Boolean expressions",
obj -> IsBool( obj ) and ( obj = true or obj = false ),
String,
# see symbol
],


rational := [
"rational",
IsRat,
String,
],


complex := [
"Complex Numbers and the Complex Constructor",
IsGaussRat,
function ( obj )
    local  real, imaginary;
    real := x -> (x + ComplexConjugate( x )) / 2;
    imaginary := x -> (x - ComplexConjugate( x )) * -1 / 2 * E( 4 );
# E := proc(n) description "returns  the primitive <n>-th root of unity"; exp(2*I*Pi/n) end proc
    return Concatenation( "( ", IF_ConvertFromGap( IF_maple, real( obj ) ), 
        " + I*(", IF_ConvertFromGap( IF_maple, imaginary( obj ) ), ") )" );
end,
function ( obj, name )
    local  type;
    WriteLine( IF_IOLP[IF_maple], Concatenation( "type( ", name, ", imaginary );" ) );
    type := IF_READ_UNTIL_PROMPT( IF_maple );
    if type = "true"  then
        return E( 4 ) * IF_Maple_op( IF_maple, obj, name, fail );
    else
        return IF_Maple_op( IF_maple, obj, name, function ( x, y ) return x + E( 4 ) * y; end );
    fi;
end
],


complex\(extended_numeric\) := [
"some type as 'complex', used from Maple 9.5 on",
,
,
function ( obj, name )
    return IF_ConvertToGap( IF_maple, obj, "complex" , name );
end
],


extended_numeric := [
"infinity, -infinity, or undefined",
IsInfinity,
String,
IF_EvalString
],


polynom := [ 
"Polynomials",
IsRationalFunction and IsPolynomial,
function ( pol )
    local  str, mons, k, mon, m, len;
    if IsZero( pol )  then
        return "0";
    fi;
    str := "(";
    mons := ExtRepPolynomialRatFun( pol );
    k := 1;
    len := 0;
    while k <= Length( mons )  do
        if Length( str ) - len >= 500  then
            Append( str, "\n" );
            len := Length( str );
        fi;
        if k > 1  then
            Add( str, '+' );
        fi;
        Add( str, '(' );
        Append( str, IF_ConvertFromGap( IF_maple, mons[k + 1] ) );
        Add( str, ')' );
        mon := mons[k];
        m := 1;
        while m <= Length( mon )  do
            Append( str, "*x_" );
            Append( str, String( mon[m] ) );
            Append( str, "^" );
            Append( str, String( mon[m + 1] ) );
            m := m + 2;
        od;
        k := k + 2;
    od;
    Add( str, ')' );
    return str;
end,
# see symbol
],


ratpoly := [
"rational polynomials (rational functions)",
obj -> IsRationalFunction( obj ) and ForAll( [ NumeratorOfRationalFunction( obj ),
    DenominatorOfRationalFunction( obj ) ], y -> IF_Type(IF_maple, y) <> fail ),
obj -> Concatenation( IF_ConvertFromGap( IF_maple, NumeratorOfRationalFunction( obj ) ), "/",
    IF_ConvertFromGap( IF_maple, DenominatorOfRationalFunction( obj ) ) ),

],


SDMPolynom := [
"Sparse Distributed Multivariate Polynomial",
IsRationalFunction and IsPolynomial,
obj -> Concatenation( "SDMPolynom( ", IF_ConvertFromGap( IF_maple, obj ), ", ", 
        IF_ConvertFromGap( IF_maple, IndeterminatesOfPolynomialRing(DefaultRing(obj)) ), ")" ),
function ( obj, name )
    WriteLine( IF_IOLP[IF_maple], Concatenation( name, "_ := convert( ", name, ", polynom );" ) );
    IF_READ_UNTIL_PROMPT( IF_maple );
    name := Concatenation( name, "_" );
    
    return IF_GET_CAS_OUTPUT( IF_maple, name );
end
]






);

