#############################################################################
##
#A  rational.g                  GAP library                  Martin Schoenert
##
#A  @(#)$Id: rational.g,v 3.8 1994/04/13 08:27:19 sam Rel $
##
#Y  Copyright 1990-1992,  Lehrstuhl D fuer Mathematik,  RWTH Aachen,  Germany
##
##  This file contains  those  functions  that  mainly  deal  with rationals.
##
#H  $Log: rational.g,v $
#H  Revision 3.8  1994/04/13  08:27:19  sam
#H  introduced 'OperationsRecord'
#H
#H  Revision 3.7  1994/02/16  14:42:31  fceller
#H  changed 'FastPolynomial' slightly
#H
#H  Revision 3.6  1993/02/12  11:59:52  martin
#H  added 'RationalOps.FastPolynomial'
#H
#H  Revision 3.5  1992/12/16  19:47:27  martin
#H  replaced quoted record names with escaped ones
#H
#H  Revision 3.4  1992/11/16  12:23:44  fceller
#H  added Laurent polynomials
#H
#H  Revision 3.3  1992/06/17  07:06:04  fceller
#H  moved '<somedomain>.operations.Polynomial' function to "<somedomain>.g"
#H
#H  Revision 3.2  1992/06/01  07:48:16  fceller
#H  added read of "polyrat.g"
#H
#H  Revision 3.1  1992/02/06  11:47:31  martin
#H  removed 'InverseMod' and added 'QuotientMod'
#H
#H  Revision 3.0  1991/12/27  15:00:00  martin
#H  initial revision under RCS
##


#############################################################################
##
#F  Rationals . . . . . . . . . . . . . . . . . . . . . .  field of rationals
#F  RationalsOps  . . . . . . . . . . . . operations record for the rationals
##
RationalsOps := OperationsRecord( "RationalsOps", FieldOps );

Rationals := rec(
    isDomain                    := true,
    isField                     := true,
    isCyclotomicField           := true,

    char                        := 0,
    generators                  := [ 1 ],
    zero                        := 0,
    one                         := 1,
    name                        := "Rationals",

    size                        := "infinity",
    isFinite                    := false,
    degree                      := 1,

    field                       := 0,
    dimension                   := 1,
    base                        := [ 1 ],
    automorphisms               := [ e -> e ],

    operations                  := RationalsOps
);


#############################################################################
##
#F  RationalsOps.Field(<elms>)  . . . . . . field generated by some rationals
##
RationalsOps.Field := function ( elms )
    return Rationals;
end;


#############################################################################
##
#F  RationalsOps.DefaultField(<elms>) . . . . default field of some rationals
##
RationalsOps.DefaultField := function ( elms )
    return Rationals;
end;


#############################################################################
##
#F  RationalsOps.\in(<x>,<Rationals>)  . . . . membership test for rationals
##
RationalsOps.\in := function ( x, Rationals )
    return IsRat( x );
end;


#############################################################################
##
#F  RationalsOps.Random(<Rationals>)  . . . . . . . . . . . . random rational
##
RationalsOps.Random := function ( Rationals )
    local    num, den;
    num := Random( Integers );
    repeat
        den := Random( Integers );
    until den <> 0;
    return num / den;
end;


#############################################################################
##
#F  RationalOps.Conjugates(<Rationals>,<x>) . . . .  conjugates of a rational
##
RationalsOps.Conjugates := function ( Rationals, x )
    return [ x ];
end;


#############################################################################
##
#F  RationalsOps.AsGroup(<Rationals>) . . . rationals as multiplicative group
##
RationalsOps.AsGroup := function ( Rationals )
    Error("the multiplicative group of Q is not finitely generated");
end;


#############################################################################
##
#F  RationalsOps.AsAdditiveGroup(<Rationals>) . . rationals as additive group
##
RationalsOps.AsAdditiveGroup := function ( Rationals )
    Error("the additive group of Q is not finitely generated");
end;


#############################################################################
##
#F  RationalsOps.AsRing(<Rationals>)  . . . . . .  view the rationals as ring
##
#N  23-Oct-91 martin this should be 'FieldOps.AsRing'
##
RationalsAsRingOps := OperationsRecord( "RationalsAsRingOps", RingOps );

RationalsAsRingOps.\in := RationalsOps.\in;

RationalsAsRingOps.Random := RationalsOps.Random;

RationalsAsRingOps.Quotient := function ( R, r, s )
    return r/s;
end;

RationalsAsRingOps.IsUnit := function ( R, r )
    return r <> R.zero;
end;

RationalsAsRingOps.Units := function ( R )
    return AsGroup( R.field );
end;

RationalsAsRingOps.IsAssociated := function ( R, r, s )
    return (r = R.zero) = (s = R.zero);
end;

RationalsAsRingOps.StandardAssociate := function ( R, r )
    if r = R.zero  then
        return R.zero;
    else
        return R.one;
    fi;
end;

RationalsOps.AsRing := function ( Rationals )

    return rec(
        isDomain                := true,
        isRing                  := true,

        zero                    := 0,
        one                     := 1,

        isFinite                := false,
        size                    := "infinity",
        isCommutativeRing       := true,
        isIntegralRing          := true,
        field                   := Rationals,

        operations              := RationalsAsRingOps
    );
end;


#############################################################################
##
#F  RationalsOps.PolynomialRing( <R> )  . . . . . . . .  full polynomial ring
##
RationalsOps.PolynomialRing := function( R )
    return RationalsPolynomials;
end;


#############################################################################
##
#F  RationalsOps.Polynomial( <R>, <coeffs>, <val> ) . . . polynomial over <R>
##
RationalsOps.Polynomial := function( R, coeffs, val )

    # normalize <coeffs>
    coeffs := Copy(coeffs);
    val    := val + NormalizeCoeffs(coeffs);
    if 0 = Length(coeffs)  then val := 0;  fi;

    # return polynomial
    if val < 0  then
        return rec( coefficients := coeffs,
    	    	    baseRing     := R,
    	    	    isPolynomial := true,
		    valuation    := val,
    	    	    domain       := LaurentPolynomials,
    	    	    operations   := RationalsPolynomialOps );
    else
        return rec( coefficients := coeffs,
    	    	    baseRing     := R,
    	    	    isPolynomial := true,
		    valuation    := val,
    	    	    domain       := RationalsPolynomials,
    	    	    operations   := RationalsPolynomialOps );
    fi;

end;


#############################################################################
##
#F  RationalsOps.FastPolynomial( <R>, <coeffs>, <val> ) . polynomial over <R>
##
##  This function will *not* copy <coeffs> and thus destroy <coeffs>.
##
RationalsOps.FastPolynomial := function( R, coeffs, val )

    # normalize <coeffs>
    val := val + NormalizeCoeffs(coeffs);
    if 0 = Length(coeffs)  then val := 0;  fi;

    # return polynomial
    if val < 0  then
        return rec( coefficients := coeffs,
    	    	    baseRing     := R,
    	    	    isPolynomial := true,
		    valuation    := val,
    	    	    domain       := LaurentPolynomials,
    	    	    operations   := RationalsPolynomialOps );
    else
        return rec( coefficients := coeffs,
    	    	    baseRing     := R,
    	    	    isPolynomial := true,
		    valuation    := val,
    	    	    domain       := RationalsPolynomials,
    	    	    operations   := RationalsPolynomialOps );
    fi;

end;
