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

IF_pari_gp := 60;


##############################################################################
# Administrative data


IF_SUBPACKAGE_VERSION[IF_pari_gp] := "dev";

IF_CAS_DESCRIPTION[IF_pari_gp] :=
[ "PARI/GP",
"PARI/GP is a computer algebra system designed for fast computations in number theory",
"http://pari.math.u-bordeaux.fr/", "http://www.math.u-psud.fr/~belabas/pari/"];


##############################################################################
# Low level data


IF_EXEC_NAME[IF_pari_gp] := "gp";
IF_EXEC_FULL_PATH[IF_pari_gp] := "/home/costanti/marco/CASes/pari-2.2.7.alpha/gp";
IF_EXEC_OPTIONS[IF_pari_gp] := [ "-f", "-q"  ]; 
# change it to [ "-q" ] if you want to use your .gprc, and if there are in it no command that disturb
# the interface. If you change your prompt, you will need to change IF_PROMPTS[IF_pari_gp] accordingly.


IF_QUIT_COMMAND[IF_pari_gp] := ";quit;";
IF_DISPLAY_VERSION[IF_pari_gp] := "\v";


IF_FIRST_COMMAND[IF_pari_gp] := "\\o0";

IF_FIRST_PROMPT[IF_pari_gp] := "? ";
IF_PROMPTS[IF_pari_gp] :=[ "\n? ", "? " ]; # also "? "
IF_FUNC_REMOVE_PROMPT[IF_pari_gp] := OUT -> OUT{[ 1 .. Length( OUT ) - Length( IF_PROMPTS[IF_pari_gp][1] ) ]};
IF_IS_THERE_PROMPT[IF_pari_gp] := true;


##############################################################################
# High level data


IF_ASSIGN[IF_pari_gp] := "=";
IF_END_COMMAND[IF_pari_gp] := "";
IF_END_COMMAND_NO_OUTPUT[IF_pari_gp] := ";";
IF_FUNC_TYPE[IF_pari_gp] := "type";
IF_TYPE_IS_QUOTED[IF_pari_gp] := true;

IF_FUNC_DISPLAY[IF_pari_gp] := "";
# IF_FUNC_DISPLAY_OPENMATH[IF_pari_gp] := "om_convert_print";

IF_STRING_ARE_QUOTED[IF_pari_gp] := true;
IF_FUNC_STRING[IF_pari_gp] := "Str";
IF_PROHIBITED_CHARS[IF_pari_gp] := [ 127, 255 ];


##############################################################################
# data types data


# See user manual, paragraphs "1.2 The PARI types.", "2.3 Input formats for the PARI types.", 
# and "4.5 Implementation of the PARI types.".

# From the manual:
#    Let us now describe the types. As explained above, they are built recursively from basic types
# which are as follows. We use the letter T to designate any type; the symbolic names correspond to
# the internal representations of the types.


IF_DATA_TYPES[IF_pari_gp] := rec(


t_INT := [         # Z
"Integers (with arbitrary precision)",
IsInt,
String,
Int
],



t_REAL := [        # R
"Real numbers (with arbitrary precision)",
,
,
IdFunc
],



t_INTMOD := [      # Z/nZ
"Integermods (integers modulo n)",
IsZmodnZObj,
obj -> Concatenation( "Mod( ", String( obj![1] ), ", ", String( DataType( TypeObj( obj ) ) ), " )" ),
function ( obj )
    local  p;
    p := Position( obj, ',' );
    return ZmodnZObj( Int( obj{[ 5 .. p - 1 ]} ), Int( obj{[ p + 2 .. Length( obj ) - 1 ]} ) );
end 
# function( obj, name )
#    return IF_Maple_op( IF_pari_gp, obj, name, function ( x, y ) return ZmodnZObj( y, x ); end );
# end
],



t_FRAC := [        # Q
"Rational numbers (in irreducible form)",
IsRat,
String,
Rat
# function( obj, name ) return IF_Maple_op( IF_pari_gp, obj, name, \/ ); end
],



t_FRACN := [       # Q
"Rational numbers (not necessarily in irreducible form)",
IsRat,
String,
Rat 
# function( obj, name ) return IF_Maple_op( IF_pari_gp, obj, name, \/ ); end
],



t_COMPLEX := [     # T [i]
"Complex numbers",
IsGaussRat,
function ( obj )
    local  real, imaginary;
    real := x -> (x + ComplexConjugate( x )) / 2;
    imaginary := x -> (x - ComplexConjugate( x )) * -1 / 2 * E( 4 );
    return Concatenation( "( ", IF_ConvertFromGap( IF_pari_gp, real( obj ) ),
        " + I*(", IF_ConvertFromGap( IF_pari_gp, imaginary( obj ) ), ") )" );
end,
function( obj, name )
    return IF_Maple_op( IF_pari_gp, obj, name, function ( x, y ) return x + E( 4 ) * y; end ); 
end
],



t_PADIC := [       # Qp
"p-adic numbers",
IsPurePadicNumber,
obj -> Concatenation( "(", String( obj![2] ), " + O(", String( FamilyObj(obj)!.prime ), "^", 
String( FamilyObj(obj)!.precision ), "))" ),
function( obj, name )
    local res;
    res := IF_Maple_op( IF_pari_gp, obj, name, Add );
    return PadicNumber(PurePadicNumberFamily(res[1],LogInt(res[2],res[1])), res[3]);
end
],



t_QUAD := [        # Q[w]
"Quadratic Numbers (where [Z[w] : Z] = 2)", ],



t_POLMOD := [      # T [X]/P (X)T [X]
"Polmods (polynomials modulo P )", ],



t_POL := [         # T [X]
"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, "" );
            len := Length( str );
        fi;
        if k > 1  then
            Add( str, '+' );
        fi;
        Add( str, '(' );
        Append( str, IF_ConvertFromGap( IF_pari_gp, 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,
function( obj, name )
    local  variable, coeffs;

    variable := IF_LowLevelInterface( IF_pari_gp, "", "variable", name );

    if Length( variable ) > 2 and variable{[ 1 .. 2 ]} = "x_" and 
      ForAll( variable{[ 3 .. Length( variable ) ]}, IsDigitChar )  then
        variable := Indeterminate( Rationals, Int( variable{[ 3 .. Length( variable ) ]} ) );
    else
        variable := Indeterminate( Rationals, variable : old := true );
    fi;

    coeffs := IF_Maple_op( IF_pari_gp, obj, name, Add );
    return Sum( [ 1 .. Length( coeffs ) ], x -> coeffs[x] * variable ^ (x - 1) );
end
],



t_SER := [         # T ((X))
"Power series (finite Laurent series)", ],



t_RFRAC := [       # T (X)
"Rational functions (in irreducible form)",
obj -> IsRationalFunction( obj ) and ForAll( [ NumeratorOfRationalFunction( obj ),
    DenominatorOfRationalFunction( obj ) ], y -> IF_Type(IF_pari_gp, y) <> fail ),
obj -> Concatenation( IF_ConvertFromGap( IF_pari_gp, NumeratorOfRationalFunction( obj ) ), "/",
    IF_ConvertFromGap( IF_pari_gp, DenominatorOfRationalFunction( obj ) ) ),
function( obj, name ) return IF_Maple_op( IF_pari_gp, obj, name, \/ ); end
],



t_RFRACN := [      # T (X)
"Rational functions (not necessarily in irreducible form)",
obj -> IsRationalFunction( obj ) and ForAll( [ NumeratorOfRationalFunction( obj ),
    DenominatorOfRationalFunction( obj ) ], y -> IF_Type(IF_pari_gp, y) <> fail ),
obj -> Concatenation( IF_ConvertFromGap( IF_pari_gp, NumeratorOfRationalFunction( obj ) ), "/",
    IF_ConvertFromGap( IF_pari_gp, DenominatorOfRationalFunction( obj ) ) ),
function( obj, name ) return IF_Maple_op( IF_pari_gp, obj, name, \/ ); end
],



t_VEC := [         # T n
"Row (i.e. horizontal) vectors",
obj -> IsRowVector( obj ) and ForAll( obj, y -> IF_Type(IF_pari_gp, y) <> fail ),
obj -> IF_ParseGapList( IF_pari_gp, obj, "[", "]" ),
function( obj, name ) return IF_Maple_op( IF_pari_gp, obj, name, Add ); end
],



t_COL := [         # T n
"Column (i.e. vertical) vectors", ],



t_MAT := [         # Mm,n(T )
"Matrices",
obj -> IsMatrix( obj ) and ForAll( obj, x ->
    ForAll( x, y -> IF_Type(IF_pari_gp, y) <> fail ) ),
function( obj )
    local  str, dim, i, j;
    dim := DimensionsMat( obj );
    str := "Mat([ ";
    for i  in [ 1 .. dim[1] ]  do
        for j  in [ 1 .. dim[2] ]  do
            Append( str, IF_ConvertFromGap( IF_pari_gp, obj[i][j] ) );
            if not j = dim[2]  then
                Append( str, "," );
            fi;
            if j mod 50 = 0  then
                Append( str, "" );
            fi;
        od;
        if not i = dim[1]   then
            Append( str, ";" );
        fi;
    od;
    Append( str, "])" );
    return str;
end,
function ( obj, name )
    local  dim, i, mat, subname;

    dim := Int( IF_LowLevelInterface( IF_pari_gp, "", "length", Concatenation( name, "~") ) );
    mat := [  ];

    for i  in [ 1 .. dim ]  do
        subname := Concatenation( name, "_elm" );
        IF_LowLevelInterface( IF_pari_gp, subname, "", Concatenation( name, "[", String(i), ",]" ) );
        mat[i] := IF_GetCasOutput( IF_pari_gp, subname );
    od;
    return mat;
end
],



t_STR := [         #
"Character strings",
IsString and IsStringRep,
IF_ParseGapString, # it doesn't work for ASCII codes 0..31, 127, 255
obj -> obj{[ 2 .. Length( obj ) - 1 ]}, # it doesn't work for ASCII codes 0..31
],



t_LIST := [        # T n
"Lists",
obj -> IsDenseList( obj ) and ForAll( obj, y -> IF_Type(IF_pari_gp, y) <> fail ),
obj -> IF_ParseGapList( IF_pari_gp, obj, "List([", "])" ),
function( obj, name ) return IF_Maple_op( IF_pari_gp, obj, name, Add ); end
]


);

