
unprotect('galois');

# Copyright 1987 R. Sommeling; all rights reserved
#                                                           April 25, 1987
# Modifications to allow calculations over Q(t):
# Copyright 1992 T. Mattman; all rights reserved
#                                                          February 15, 1992


# Input:  A polynomial f in x, the indeterminate x and a non-negative
#         integer r.
# Output: A primitive polynomial of degree binomial(n,r) in x whose roots are
#         the products of r distinct roots of f.

rsetpol := proc(f,x,r)
local a,b,g,h,hj,i,j,k,n,rb,s,s2;
options `Copyright 1987 by Ron Sommeling`;
    if not type(x,name) then
        ERROR(`second argument should be a variable`)
    fi;
    g := normal(f);
    if not type(g,polynom(rational)) then
        ERROR(`first argument should be a polynomial`)
    fi;
    if not type(r,integer) or (r < 0) then
        ERROR(`third argument should be a natural number`)
    fi;
    g := expand(g);
    g := expand(g/lcoeff(g,x));
    n := degree(g,x);
    if r = 0 then x-1
    elif r = 1 then g
    elif r = n then x-(-1)^n*coeff(g,x,0)
    elif n < r then 1
    else
        b := binomial(n,r);
        rb := r*b;
        h := array(1 .. r);
        a := array(0 .. n,['coeff(g,x,n-i)' $ ('i' = 0 .. n)]);
        s := a_to_s(op(a),n,rb);
        s2 := array(1 .. b);
        for i to b do
            for j to r do
                hj := s[i*j];
                for k to j-1 do  hj := normal(hj+h[k]*s[i*(j-k)]) od;
                h[j] := -hj/j
            od;
            s2[i] := (-1)^r*h[r]
        od;
        a := s_to_a(op(s2),b);
        i := 'i';
        g := sum(a[b-i]*x^i,i = 0 .. b);
        normal(g/content(g,x))
    fi
end:

# Input:  A polynomial f in x and the indeterminate x.
# Output: A primitive polynomial of degree n(n-1) in x whose roots are
#         xi + 2 xj, where xi and xj are distinct roots of f.

twoseqpol := proc(f,x)
local a,d,g,i,j,n,s,s2,si;
options `Copyright 1987 by Ron Sommeling`;
    if not type(x,name) then
        ERROR(`second argument should be a variable`)
    fi;
    g := normal(f);
    if not type(g,polynom(rational)) then
        ERROR(`first argument should be a polynomial`)
    fi;
    g := expand(g);
    g := expand(g/lcoeff(g,x));
    n := degree(g,x);
    d := n*(n-1);
    s2 := array(1 .. d);
    a := array(0 .. n,['coeff(g,x,n-i)' $ ('i' = 0 .. n)]);
    s := a_to_s(op(a),n,d);
    for i to d do
        si := 0;
        for j from 0 to i do
            si := normal(si+2^j*binomial(i,j)*(s[j]*s[i-j]-s[i]))
        od;
        s2[i] := si
    od;
    a := s_to_a(op(s2),d);
    i := 'i';
    g := sum(a[d-i]*x^i,i = 0 .. d);
    normal(g/content(g,x))
end:

# Input:  An array a(0..n) of the coefficients of a monic polynomial f of
#         degree n (so a[0]=1), an integer n and an integer m.
# Output: The powersums x1^i + ... + xn^i for i from 0 to m, where the
#         xi s are the roots of f.

a_to_s := proc(a,n,m)
local s,i,j,n2,si;
options `Copyright 1987 by Ron Sommeling`;
    s := array(0 .. m);
    s[0] := n;
    for i to m do
        if n < i then si := -a[n]*s[i-n]; n2 := n-1
        else si := -i*a[i]; n2 := i-1
        fi;
        for j to n2 do  si := normal(si-a[j]*s[i-j]) od;
        s[i] := si
    od;
    RETURN(op(s))
end:

# Input:  An array s(1..m-1) of the powersums of a monic polynomial f of
#         degree m and an integer m.
# Output: The coefficients of f.

s_to_a := proc(s,m)
local a,ai,i,j;
options `Copyright 1987 by Ron Sommeling`;
    a := array(0 .. m,[1]);
    for i to m do
        ai := s[i];
        for j to i-1 do  ai := normal(ai+a[j]*s[i-j]) od;
        a[i] := -ai/i
    od;
    RETURN(op(a))
end:

# Copyright 1987 R. Sommeling; all rights reserved
#
# Input:  An univariate polynomial f in x with integer coefficients,
#         the indeterminate x, a prime p such that p doesn't divide the
#         leading coefficient of f and f is squarefree mod p.
# Output: A sequence of non-increasing integers which are the degrees of
#         the factors of f mod p. To compute these degrees it is not
#         necessary to compute the actual factors of f mod p.
#                                                           April 25, 1987

cyclepattern := proc(f,x,p)
local a,i,n;
options `Copyright 1987 by Ron Sommeling`;
    a := modp1(ConvertIn(f,x),p);
    a := modp1(UNormal(a),p);
    a := modp1(DistDeg(a),p);
    n := nops(a);
    a := ['a[n-i]' $ (i = 0 .. n-1)];
    a := map(proc(L,p)
             local i,j;
                 i := modp1(Degree(L[1]),p);
                 j := L[2];
                 if j = 0 then NULL else j $ iquo(i,j) fi
             end                                 ,a,p);
    op(a)
end:

# Copyright 1987 R. Sommeling; all rights reserved
#
# The array "groups" contains all transitive groups of degree up to 7.
#
# groups[n, 0] = set of all transitive groups of degree n which are
#                contained in the alternating group of degree n.
# groups[n, 1] = set of all transitive groups of degree n which are not
#                contained in the alternating group of degree n.
#
# A group is represented by a list of 3 or more elements:
# - The first element is a string which is the name of the group as
#   given in [1].
# - The second element is the order of the group.
# - The third element is a set of generators of the group (up to conjugacy).
#   A generator is a string which is the disjoint cycle representation of
#   the generator.
# - The fourth element (for groups of degree 4 up to 7) is a list of zeros
#   and ones indicating whether a cycle type occurs in the group (see [1]).
#   0 = cycle type doesn't occur; 1 = cycle type occurs.
#   The cycle type are ordered lexicographically starting with 2 1 1 ... 1
#   (a 2-cycle) and ending with n (an n-cycle).
# - The fifth up to the one but last element are sorted lists of the
#   orbit-length partition of 2-sets, 3-sets, etc. (see [2]).
# - The last element (for groups of degree 4 up to 7) is a sorted list of
#   the orbit-length partition of 2-sequences (see [2]).
#
# Example: One of the elements in the set "groups[6, 1]" is:
#
#          [`S4/Z4`, 24, {`(1 2)(3 4)(5 6)`, `(1 2 3)(4 5 6)`},
#            [0, 1, 1, 0, 0, 1, 1, 0, 0, 0],
#              [3, 12], [8, 12], [6, 24]]
#
# This means that this is a transitive group of degree 6 which is not
# contained in the A6 (the alternating group of order 6).
# The name of the group is "S4/Z4", its order is 24 and it is generated
# by (1 2)(3 4)(5 6) and (1 2 3)(4 5 6) (up to conjugacy).
# Only the following cycle types appear in the group:
#
#                       1 1 1 1 1 1
#                       2 2 1 1
#                       2 2 2
#                       3 3
#                       4 1 1
#
# The orbit-length partition of 2-sets is 3, 12.
# The orbit-length partition of 3-sets is 8, 12.
# The orbit-length partition of 2-sequences is 6, 24.
#
# References:
# [1] G. Butler & J. McKay, The transitive permutation groups of degree up
#     to eleven, Comm. Alg. 11 (1983), pp. 863-911.
# [2] L.H. Soicher & J. McKay, Computing Galois groups over the rationals,
#     Number Theory 20 (1985), pp. 273-281.
# [3] J. McKay & E. Regener, Actions of permutation groups on r-sets,
#     Comm. Alg. 13 (1985), pp.619-630.
#                                                           April 25, 1987

groups := array(1..8, 0..1, [

[{[`+Id`,1,{}]},{}],
[{},{[`S2`,2,{`(12)`}]}],
[{[`+A3`,3,{`(123)`}]},
{[`S3`,6,{`(123)`,`(12)`}]}],

[{[`+V4`,4,{`(12)(34)`,`(13)(24)`},
[0,1,0,0],
[2,2,2],[4,4,4]],
[`+A4`,12,{`(123)`,`(12)(34)`},
[0,1,1,0],
[6],[12]]},

{[`Z4`,4,{`(1234)`},
[0,1,0,1],
[2,4],[4,4,4]],
[`D4`,8,{`(1234)`,`(13)`},
[1,1,0,1],
[2,4],[4,8]],
[`S4`,24,{`(1234)`,`(12)`},
[1,1,1,1],
[6],[12]]}],

[{[`+Z5`,5,{`(12345)`},
[0,0,0,0,0,1],
[5,5],[5,5,5,5]],
[`+D5`,10,{`(12345)`,`(25)(34)`},
[0,1,0,0,0,1],
[5,5],[10,10]],
[`+A5`,60,{`(12345)`,`(123)`},
[0,1,1,0,0,1],
[10],[20]]},

{[`F20`,20,{`(12345)`,`(2354)`},
[0,1,0,0,1,1],
[10],[20]],
[`S5`,120,{`(12345)`,`(12)`},
[1,1,1,1,1,1],
[10],[20]]}],

[{[`+A4`,12,{`(135)(246)`,`(12)(56)`},
[0,1,0,0,0,1,0,0,0,0],
[3,12],[4,4,6,6],[6,12,12]],
[`+S4/V4`,24,{`(135)(246)`,`(16)(25)`},
[0,1,0,0,0,1,0,1,0,0],
[3,12],[4,4,12],[6,24]],
[`+3^2.4`,36,{`(123)`,`(1524)(36)`},
[0,1,0,1,0,1,0,1,0,0],
[6,9],[2,18],[12,18]],
[`+PSL2(5)`,60,{`(12345)`,`(16)(25)`},
[0,1,0,0,0,1,0,0,1,0],
[15],[10,10],[30]],
[`+A6`,360,{`(12345)`,`(456)`},
[0,1,0,1,0,1,0,1,1,0],
[15],[20],[30]]},

{[`Z6`,6,{`(123456)`},
[0,0,1,0,0,1,0,0,0,1],
[3,6,6],[2,6,6,6],[6,6,6,6,6]],
[`S3`,6,{`(15)(24)(36)`,`(16)(25)(34)`},
[0,0,1,0,0,1,0,0,0,0],
[3,3,3,6],[2,6,6,6],[6,6,6,6,6]],
[`D6`,12,{`(123456)`,`(26)(35)`},
[0,1,1,0,0,1,0,0,0,1],
[3,6,6],[2,6,12],[6,12,12]],
[`3.S3`,18,{`(123)`,`(14)(25)(36)`},
[0,0,1,1,0,1,0,0,0,1],
[6,9],[2,18],[6,6,18]],
[`2.A4`,24,{`(135)(246)`,`(12)`},
[1,1,1,0,0,1,0,0,0,1],
[3,12],[6,6,8],[6,12,12]],
[`S4/Z4`,24,{`(12)(34)(56)`,`(123)(456)`},
[0,1,1,0,0,1,1,0,0,0],
[3,12],[8,12],[6,24]],
[`3^2.2^2`,36,{`(123456)`,`(13)(24)`},
[0,1,1,1,0,1,0,0,0,1],
[6,9],[2,18],[12,18]],
[`2.S4`,48,{`(1234)`,`(15)(36)`},
[1,1,1,0,0,1,1,1,0,1],
[3,12],[8,12],[6,24]],
[`3^2.D4`,72,{`(123456)`,`(13)`},
[1,1,1,1,1,1,0,1,0,1],
[6,9],[2,18],[12,18]],
[`PGL2(5)`,120,{`(12345)`,`(16)(23)(45)`},
[0,1,1,0,0,1,1,0,1,1],
[15],[20],[30]],
[`S6`,720,{`(123456)`,`(12)`},
[1,1,1,1,1,1,1,1,1,1],
[15],[20],[30]]}],

[{[`+Z7`,7,{`(1234567)`},
[0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[7,7,7],[7,7,7,7,7],[7,7,7,7,7,7]],
[`+F21`,21,{`(1234567)`,`(235)`},
[0,0,0,0,0,0,1,0,0,0,0,0,0,1],
[21],[7,7,21],[21,21]],
[`+PSL3(2)`,168,{`(1234567)`,`(23)(47)`},
[0,1,0,0,0,0,1,0,1,0,0,0,0,1],
[21],[7,28],[42]],
[`+A7`,2520,{`(1234567)`,`(123)`},
[0,1,0,1,0,1,1,0,1,0,1,0,0,1],
[21],[35],[42]]},

{[`D7`,14,{`(1234567)`,`(27)(36)(45)`},
[0,0,1,0,0,0,0,0,0,0,0,0,0,1],
[7,7,7],[7,7,7,14],[14,14,14]],
[`F42`,42,{`(1234567)`,`(243756)`},
[0,0,1,0,0,0,1,0,0,0,0,0,1,1],
[21],[14,21],[42]],
[`S7`,5040,{`(1234567)`,`(12)`},
[1,1,1,1,1,1,1,1,1,1,1,1,1,1],
[21],[35],[42]]}],

[{[`+T2:2.4`,8,{`(1357)(2468)`,`(16)(25)(38)(47)`},
[0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0],
[4,4,4,8,8],[8,8,8,8,8,8,8],
[2,2,2,4,4,8,8,8,8,8,8,8],[8,8,8,8,8,8,8]],
[`+T3:2^3`,8,{`(15)(26)(37)(48)`,`(17)(28)(35)(46)`,
`(16)(25)(38)(47)`},
[0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[4,4,4,4,4,4,4],[8,8,8,8,8,8,8],
[2,2,2,2,2,2,2,8,8,8,8,8,8,8],
[8,8,8,8,8,8,8]],
[`+T4:D4`,8,{`(1357)(2468)`,`(18)(27)(36)(45)`},
[0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0],
[4,4,4,4,4,8],[8,8,8,8,8,8,8],
[2,2,2,4,4,4,4,8,8,8,8,8,8],
[8,8,8,8,8,8,8]],
[`+T5:Q8`,8,{`(1625)(4837)`,`(1728)(3546)`},
[0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0],
[4,8,8,8],[8,8,8,8,8,8,8],
[2,2,2,8,8,8,8,8,8,8,8],
[8,8,8,8,8,8,8]],
[`+T9`,16,{`(1357)(2468)`,`(17)(28)(35)(46)`,
`(16)(25)(38)(47)`},
[0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0],
[4,4,4,8,8],[8,8,8,16,16],
[2,2,2,4,4,8,8,8,16,16],
[8,8,8,16,16]],
[`+T10`,16,{`(1357)(2468)`,`(16)(25)(37)(48)`},
[0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0],
[4,4,4,16],[8,8,8,16,16],
[2,4,4,4,8,8,8,16,16],
[8,8,8,16,16]],
[`+T11`,16,{`(1625)(4837)`,`(15)(26)(37)(48)`,
`(13)(24)(58)(67)`},
[0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0],
[4,8,8,8],[8,8,8,16,16],
[2,2,2,8,8,8,8,16,16],
[8,8,8,16,16]],
[`+T12:SL(2,3)`,24,{`(1728)(3546)`,`(357)(468)`},
[0,0,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,1,0,0],
[4,24],[8,24,24],[6,8,8,24,24],[8,24,24]],
[`+T13:2.A4`,24,{`(16)(25)(38)(47)`,`(357)(468)`},
[0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0],
[4,12,12],[8,24,24],[2,6,6,8,24,24],[8,24,24]],
[`+T14:S4`,24,{`(357)(468)`,`(14)(23)(56)(78)`},
[0,0,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0],
[4,12,12],[8,24,24],[2,6,6,8,12,12,24],
[8,24,24]],
[`+T18`,32,{`(1357)(2468)`,`(17)(28)(35)(46)`,
`(16)(25)(37)(48)`},
[0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0],
[4,4,4,16],[8,16,16,16],[2,4,4,4,8,8,8,32],
[8,8,8,32]],
[`+T19`,32,{`(1357)(2468)`,`(17)(28)(36)(45)`},
[0,1,0,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0],
[4,8,16],[8,16,32],[2,4,8,8,16,32],
[8,16,32]],
[`+T20`,32,{`(1357)(2468)`,`(12)(78)`},
[0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0],
[4,8,16],[8,8,8,32],[2,4,8,8,16,16,16],
[8,16,16,16]],
[`+T22`,32,{`(1625)(4837)`,`(15)(26)(37)(48)`,
`(16)(25)(37)(48)`,`(17)(28)(35)(46)`},
[0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0],
[4,8,8,8],[8,8,8,32],[2,2,2,8,8,16,16,16],
[8,16,16,16]],
[`+T24:2.S4`,48,{`(16)(25)(38)(47)`,`(357)(468)`,
`(13)(24)`},
[0,1,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,1,0,0],
[4,12,12],[8,24,24],[2,6,6,8,24,24],[8,24,24]],
[`+T25:2^3.7`,56,{`(1234567)`,`(18)(24)(37)(56)`},
[0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0],
[28],[56],[14,56],[56]],
[`+T29`,64,{`(1357)(2468)`,`(17)(28)(35)(46)`,
`(17)(28)(36)(45)`},
[0,1,0,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0],
[4,8,16],[8,16,32],[2,4,8,8,16,32],[8,16,32]],
[`+T32`,96,{`(17)(28)(35)(46)`,`(16)(25)(37)(48)`,
`(357)(468)`},
[0,1,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,1,0,0],
[4,24],[24,32],[6,8,8,48],[8,48]],
[`+T33`,96,{`(1735)(2846)`,`(243)(687)`},
[0,1,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,1,0,0],
[12,16],[8,48],[2,12,24,32],[24,32]],
[`+T34`,96,{`(14)(23)`,`(243)(687)`,
`(18)(25)(36)(47)`},
[0,1,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0],
[12,16],[8,48],[2,12,12,12,32],[24,32]],
[`+T36:2^3.(7.3)`,168,{`(1234567)`,`(18)(24)(37)(56)`,
`(235)(476)`},
[0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1,0],
[28],[56],[14,56],[56]],
[`+T37:L(2,7)`,168,{`(1234567)`,`(235)(476)`,
`(18)(27)(34)(56)`},
[0,0,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0],
[28],[56],[14,14,42],[56]],
[`+T39`,192,{`(16)(25)(37)(48)`,`(357)(468)`,
`(13)(24)`},
[0,1,0,1,0,0,0,1,0,0,1,0,0,1,0,0,0,0,1,0,0],
[4,24],[24,32],[6,8,8,48],[8,48]],
[`+T41`,192,{`(1735)(2846)`,`(243)(687)`,
`(18)(25)(36)(47)`},
[0,1,0,1,0,0,0,1,0,0,1,0,0,1,0,0,0,0,1,0,0],
[12,16],[8,48],[2,12,24,32],[24,32]],
[`+T42`,288,{`(13)(24)`,`(687)`,
`(15)(26)(37)(48)`},
[0,1,0,1,1,0,1,1,0,0,0,0,0,1,0,0,0,0,1,0,0],
[12,16],[8,48],[2,32,36],[24,32]],
[`+T45`,576,{`(13)(24)`,`(687)`,
`(15)(26)(37)(48)`,`(18)(25)(36)(47)`},
[0,1,0,1,1,0,1,1,0,0,1,0,0,1,0,0,0,0,1,0,0],
[12,16],[8,48],[2,32,36],[24,32]],
[`+T48:2^3.L(3,2)`,1344,{`(1234567)`,`(23)(47)`,
`(18)(24)(37)(56)`},
[0,1,0,1,0,0,0,1,0,0,1,0,0,1,0,0,0,0,1,1,0],
[28],[56],[14,56],[56]],
[`+T49:A8`,20160,{`(1234567)`,`(687)`},
[0,1,0,1,1,0,1,1,0,0,1,0,0,1,1,0,1,0,1,1,0],
[28],[56],[70],[56]]},

{[`T1:8`,8,{`(14682357)`},
[0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1],
[4,8,8,8],[8,8,8,8,8,8,8],
[2,4,8,8,8,8,8,8,8,8],
[8,8,8,8,8,8,8]],
[`T6`,16,{`(14682357)`,`(17)(28)(36)(45)`},
[0,0,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1],
[4,8,8,8],[8,8,8,16,16],
[2,4,8,8,8,8,16,16],[8,16,16,16]],
[`T7`,16,{`(14682357)`,`(34)(78)`},
[0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1],
[4,8,16],[8,8,8,16,16],
[2,4,8,8,16,16,16],[8,8,8,16,16]],
[`T8`,16,{`(14682357)`,`(16)(25)(34)`},
[0,0,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1],
[4,8,16],[8,8,8,16,16],
[2,4,8,8,16,16,16],[8,16,16,16]],
[`T15`,32,{`(14682357)`,`(16)(25)(34)`,
`(34)(78)`},
[0,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1],
[4,8,16],[8,16,16,16],
[2,4,8,8,16,32],[8,16,32]],
[`T16`,32,{`(14682357)`,`(15)(26)(37)(48)`},
[0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1],
[4,8,16],[8,8,8,32],[2,4,16,16,16,16],
[8,16,16,16]],
[`T17`,32,{`(14682357)`,`(17)(28)(35)(46)`},
[0,1,0,1,0,0,0,0,0,1,0,1,0,1,0,0,0,0,0,0,1],
[4,8,16],[8,16,32],[2,4,16,16,32],
[8,8,8,32]],
[`T21`,32,{`(1625)(37)(48)`,`(17)(28)(35)(46)`},
[0,1,0,1,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0],
[4,8,8,8],[8,8,8,32],[2,2,2,16,16,16,16],
[8,16,16,16]],
[`T23`,48,{`(357)(468)`,`(13)(24)(78)`},
[0,0,1,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,1,0,1],
[4,24],[8,24,24],[6,16,24,24],[8,48]],
[`T26`,64,{`(14682357)`,`(16)(25)(34)`,
`(15)(26)(37)(48)`},
[0,1,1,1,0,0,0,0,0,1,0,1,0,1,0,0,0,0,0,0,1],
[4,8,16],[8,16,32],[2,4,16,16,32],
[8,16,32]],
[`T27`,64,{`(14682357)`,`(12)`},
[1,1,1,1,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,1],
[4,8,16],[8,8,8,32],[2,4,16,16,16,16],
[8,16,16,16]],
[`T28`,64,{`(14682357)`,`(15)(26)`},
[0,1,0,1,0,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,1],
[4,8,16],[8,16,32],[2,4,16,16,32],
[8,16,32]],
[`T30`,64,{`(1357)(2468)`,`(12)(78)`,
`(15)(26)(34)`},
[0,1,1,1,0,0,0,0,0,1,0,1,0,1,0,0,0,0,0,0,0],
[4,8,16],[8,16,32],[2,4,16,16,32],
[8,16,32]],
[`T31`,64,{`(1625)(37)(48)`,`(17)(28)(35)(46)`,
`(12)`},
[1,1,1,1,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0],
[4,8,8,8],[8,8,8,32],[2,2,2,16,16,16,16],
[8,16,16,16]],
[`T35`,128,{`(14682357)`,`(16)(25)(34)`,
`(12)`},
[1,1,1,1,0,0,0,0,0,1,1,1,0,1,0,0,0,0,0,0,1],
[4,8,16],[8,16,32],[2,4,16,16,32],
[8,16,32]],
[`T38`,192,{`(34)`,`(17)(28)(35)(46)`,
`(357)(468)`},
[1,1,1,1,0,0,0,1,1,0,0,1,0,1,0,0,0,1,1,0,0],
[4,24],[24,32],[6,16,48],[8,48]],
[`T40`,192,{`(16)(25)(37)(48)`,`(357)(468)`,
`(13)(24)`},
[0,1,1,1,0,0,0,1,0,1,0,1,0,1,0,0,0,0,1,0,1],
[4,24],[24,32],[6,16,48],[8,48]],
[`T43:PGL(2,7)`,336,{`(1234567)`,`(243756)`,
`(18)(27)(34)(56)`},
[0,0,1,1,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0,1,1],
[28],[56],[28,42],[56]],
[`T44`,384,{`(12)`,`(1357)(2468)`,
`(13)(24)`},
[1,1,1,1,0,0,0,1,1,1,1,1,0,1,0,0,0,1,1,0,1],
[4,24],[24,32],[6,16,48],[8,48]],
[`T46`,576,{`(13)(24)`,`(687)`,
`(1625)(37)(48)`},
[0,1,0,1,1,0,1,1,0,0,1,1,0,1,0,0,0,0,0,0,1],
[12,16],[8,48],[2,32,36],[24,32]],
[`T47`,1152,{`(14)`,`(12)`,
`(15)(26)(37)(48)`},
[1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,0,0,0,1,0,1],
[12,16],[8,48],[2,32,36],[24,32]],
[`T50:S8`,40320,{`(12345678)`,`(12)`},
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
[28],[56],[70],[56]]}]]):

# Copyright 1987 R. Sommeling; all rights reserved
#                                                           April 25, 1987
# Modifications to allow calculations over Q(t):
# Copyright 1992 T. Mattman; all rights reserved
#                                                          February 15, 1992

# Input:  An irreducible polynomial f in the indeterminant x of degree
#         up to 7 and the indeterminant x. The coefficients may be either
#         rational (in which case the second argument is optional) or
#         in some transcendental extension, Q(t1,t2,t3,...,tn), of the
#         rationals.
# Output: A sequence of three elements. The first is the name of the Galois
#         group of f, the second is its order and the third is a set of
#         generators of the group (up to conjugacy).
#
# Main reference:
#
#    L.H. Soicher & J. McKay, Computing Galois groups over the rationals,
#    Number Theory 20 (1985), pp. 273-281.

galois := proc(f)
local a,D,decidable,e,equal,g,gdpol,grp,h,i,lc,minelm,n,n2,
    orbitpart,orbittype,p,part,possible,R,ratpol,rm,rsets,
    shape,sol,stable,t,ti,tn,x,sqdiscrim;
options remember,`Copyright 1987 by Ron Sommeling`,
        `Modifications for Q(t) case, Copyright 1992 by T. Mattman`;
    g := normal(f,expanded);
    t := indets(g);
    if t = {} then
        if 0 < printlevel then
            print(`The galois group of `(f));
            print(` is `)
        fi;
        RETURN(`Id`,1,{})
    fi;

# Check that arguments have the right form.
    if not type(g,polynom(rational)) then
        ERROR(`not a polynomial of the right form`)
    fi;
    ratpol := true;
    if nargs > 1 then
        x := args[2];
        if not type(x,name) then
            ERROR(`second argument must be an indeterminant`)
        fi;
        t := t minus {x};
        if t <> {} then
            for ti in t do
                if not type(ti,name) then
                    ERROR(ti, `is an invalid indeterminant`)
                fi
            od;
            tn := nops(t);
            ratpol := false
        fi;
        if degree(g,x) <= 1 then
            if 0 < printlevel then
                print(`The galois group of `(f));
                print(` is `)
            fi;
            RETURN(`Id`,1,{})
        fi
    else
        if (1 < nops(t)) then
            ERROR(`indicate polynomial indeterminant as 2nd argument`)
        fi;
        if not type(t[1],name) then
            ERROR(t[1], `is an invalid indeterminant`)
        fi;
        x := t[1]
    fi;
    n := degree(g,x);
    n2 := iquo(n,2);
    if 7 < n then ERROR(`the degree of the polynomial should be < 8`) fi;
    g := primpart(g,x);
    if type(factor(g),{`*`,`^`}) then
        ERROR(`the polynomial is reducible`)
    fi;
    if 1 < printlevel then lprint(`Computing the Galois group of `,g) fi;

# Check whether the discriminant is a square. The discriminant is a square
# iff the Galois group contains only even permutations.
    lc := lcoeff(g,x);
    D := discrim(g,x);
    sqdiscrim := issquare(D);
    if 1 < printlevel then
        if not sqdiscrim then lprint('D' = D,`(nonsquare)`)
        elif D = 1 then lprint('D' = D)
        else lprint(`D = `(simplify(D^(1/2),sqrt))^2)
        fi
    fi;
    if sqdiscrim then possible := groups[n,0]
    else possible := groups[n,1]
    fi;
    if nops(possible) = 1 then
        if 0 < printlevel then
            print(`The galois group of `(f));
            print(` is `)
        fi;
        RETURN(possible[1][1 .. 3])
    fi;
    if 1 < printlevel then lprint(`Possible groups:`,short(possible)) fi;

# Find the shapes of some elements in the Galois group by computing the
# degrees of the factors of f mod P for some maximal ideals P. The
# maximal ideals of Z(t1,...,tn)[x] are of the form (t1-a1,...,tn-an,p)
# where the ai and p are integers, p being prime.
# See Lang, Algebra (1984).
# We compute these shapes until one of the following holds:
# 1. There is only one possible Galois group left. (Is always An or Sn)
# 2. The set of possible Galois groups hasn't changed by computing the last
#    (n+1) shapes AND the set of possible Galois groups contains an element
#    whose set of possible shapes is minimal w.r.t. set inclusion.
#    This group is assigned to the variable "minelm".
    part := initpart(n);
    p := 1;
    if ratpol then
        h := g
    else
        for i to tn do
            a[i] := 1
        od;
        ti := 1
    fi;
    stable := 0;
    minelm := findminelm(possible);
    while stable < n+1 do
        p := nextprime(p);
        if (lc mod p = 0) or (D mod p = 0) then next fi;
        if not ratpol then
            gdpol := false;
            for i to n+1 while not gdpol do
                h := normal(subs((t['i'] = a['i']) $ 'i'=1..tn, g), expanded);
                h := h/icontent(h);
                if ((lcoeff(h,x) mod p = 0) or (discrim(h,x) mod p = 0))
                        or not irreduc(h) then
                    a[ti] := a[ti] + 1;
                    ti := (ti mod tn) + 1
                else
                    gdpol := true
                fi
            od;
            if not gdpol then
                next
            fi
        fi;
        shape := cyclepattern(h,x,p);
        if 1 < printlevel then lprint('p' = p,`gives shape`,shape) fi;
        e := encode(part,shape);
        rm := {};
        if 0 < e then
            for i to nops(possible) do
                grp := possible[i];
                if grp[4][e] = 0 then rm := rm union {grp} fi
            od
        fi;
        if rm <> {} then
            possible := possible minus rm;
            if 1 < printlevel then
                lprint(`Removing`,short(rm));
                lprint(`Possible groups left:`,short(possible))
            fi;
            if nops(possible) = 1 then
                if 0 < printlevel then
                    print(`The galois group of `(f));
                    print(` is `)
                fi;
                RETURN(possible[1][1 .. 3])
            fi;
            minelm := findminelm(possible);
            stable := 0
        elif minelm <> false then stable := stable+1
        fi
    od;
    if 1 < printlevel then lprint(`The Galois group is probably`,minelm[1])
    fi;

# Find out what is the best thing to do now: looking at 2-sequences or at
# r-sets for some r>1. We distinguish 3 cases:
# 1. The group "minelm" found in the previous step is still in the list of
#    possible groups AND there is a (r-set or 2-sequence) resolvent such
#    that by factoring this resolvent we can decide whether the Galois group
#    is "minelm" or not. In this case we take the resolvent of the lowest
#    degree with this property.
# 2. Otherwise, if there is a resolvent such that by factoring this resolvent
#    we can always reduce the set of possible groups, then take the resolvent
#    of the lowest degree with this property.
# 3. Otherwise, we are in one of the 4 special cases. See the description of
#    the functions "special5" and "special6".
    do
        decidable := false;
        for orbittype to n2 do
            equal := 0;
            if minelm = false then orbitpart := possible[1][orbittype+4]
            else orbitpart := minelm[orbittype+4]
            fi;
            for i to nops(possible) do
                if possible[i][orbittype+4] = orbitpart then equal := equal+1
                fi
            od;
            if (equal = 1) and (minelm <> false) then
                decidable := orbittype; break
            fi;
            if (decidable = false) and (equal < nops(possible)) then
                decidable := orbittype
            fi
        od;
        if decidable <> false then rsets := evalb(decidable < n2)
        elif degree(g,x) = 5 then
            sol := special5(g,x,D,possible,ratpol);
            if 0 < printlevel then
                print(`The galois group of `(f));
                print(` is `)
            fi;
            RETURN(sol)
        else
            sol := special6(g,x,sqfreepart(D,ratpol),possible);
            if 0 < printlevel then
                print(`The galois group of `(f));
                print(` is `)
            fi;
            RETURN(sol)
        fi;
        if 1 < printlevel then
            if rsets then
                lprint(cat(
                `Using the orbit-length partition of `,decidable+1,`-sets.`
                ))
            else lprint(`Using the orbit-length partition of 2-sequences.`)
            fi
        fi;

# Construct the (r-set or 2-sequence) polynomial. If it is not squarefree
# then apply suitable Tschirnhaus transformations to f until the resolvent
# is squarefree. Then factor the resolvent and use the degrees of the factors
# to reduce the set of possible groups.
        h := g;
        do
            if 1 < printlevel then
                lprint(`Calculating a resolvent polynomial...`)
            fi;
            if rsets then R := rsetpol(h,x,decidable+1)
            else R := twoseqpol(h,x)
            fi;
            if issqfree(R,x) then break
            elif rsets then h := expand(subs(x = x+1,h))
            else h := numer(subs(x = 1/(x+1),h))
            fi
        od;
        if 1 < printlevel then
            lprint(`Factoring the resolvent polynomial...`)
        fi;
        orbitpart := degrees(factor(R),x);
        if 1 < printlevel then
            lprint(`Orbit-length partition is`,orbitpart)
        fi;
        orbitpart := [orbitpart];
        rm := {};
        for i to nops(possible) do
            grp := possible[i];
            if grp[decidable+4] <> orbitpart then rm := rm union {grp} fi
        od;
        possible := possible minus rm;
        if 1 < printlevel then
            lprint('Removing',short(rm));
            lprint(`Possible groups left:`,short(possible))
        fi;
        if nops(possible) = 1 then
            if 0 < printlevel then
                print(`The galois group of `(f));
                print(` is `)
            fi;
            RETURN(possible[1][1 .. 3])
        fi;
        if not member(minelm,possible) then minelm := false fi
    od
end:
protect(galois);

short := proc(grps)
options `Copyright 1987 by Ron Sommeling`;
    map(proc(grp) grp[1] end,grps)
end:

issqfree := proc(f,x)
options `Copyright 1987 by Ron Sommeling`;
    degree(gcd(f,diff(f,x)),x) = 0
end:

# Input:  An integer n.
# Output: The integer m such that n = k^2 m, where all prime factors of k are
#         smaller than 2000 and all prime factors of m smaller than 2000
#         appear with multiplicity 1.
# We don't compute the complete squarefree part, because that could take a
# very long time if n is big. Note that 510510 is the product of the primes
# up to 17 while the big number used in this procedure is the product of the
# primes from 19 to 1999.

isqfreepart := proc(n)
local m1,m2,m;
options `Copyright 1987 by Ron Sommeling`;
    m := n;
    m2 := 2;
    while (1 < m2) and (1 < m) do
        m1 := m/igcd(m,510510); m2 := igcd(m1,510510); m := m/m2^2
    od;
    m2 := 2;
    while (1 < m2) and (1 < m) do
        m1 := m/igcd(m,
5668344243265471819408349879264900561344506260438297113121754471676061\
2560791973390670744989333350841745309402061968741709452975735415298674\
9560019905142897690259093457210799603632782717922065955901830529319296\
1167931511458206100875119670995542639325967180196434319724253387877603\
6716818371965880567092149001036019530948612161197976056057227524736840\
1870162331444571403713689995433289772675349111069849906442564926271706\
4250647347752986985165434242366290330943902166943407887478097884195588\
7151142775136584305953026725917860957221689991171352057774946363103279\
4081865124575338024762333449029062271815188481933090660812302255777593\
0961309507305546661753623302876891787345038544171957581961149093965350\
7058614796835748370471316444340873208399321825992890475512470915258564\
3599469820961428065196995970020581366019108556944629640933475067617
        );
        m2 := igcd(m1,
5668344243265471819408349879264900561344506260438297113121754471676061\
2560791973390670744989333350841745309402061968741709452975735415298674\
9560019905142897690259093457210799603632782717922065955901830529319296\
1167931511458206100875119670995542639325967180196434319724253387877603\
6716818371965880567092149001036019530948612161197976056057227524736840\
1870162331444571403713689995433289772675349111069849906442564926271706\
4250647347752986985165434242366290330943902166943407887478097884195588\
7151142775136584305953026725917860957221689991171352057774946363103279\
4081865124575338024762333449029062271815188481933090660812302255777593\
0961309507305546661753623302876891787345038544171957581961149093965350\
7058614796835748370471316444340873208399321825992890475512470915258564\
3599469820961428065196995970020581366019108556944629640933475067617
        );
        m := m/m2^2
    od;
    m
end:

# Input:  An integer n.
# Output: An array part(0..n,0..n) needed for the encoding of shapes up to
#         degree n.
#         part[i,j] = number of shapes of degree i with all elements <= j.

initpart := proc(n)
local i,j,part;
options `Copyright 1987 by Ron Sommeling`;
    part := array(0 .. n,0 .. n);
    part[0,0] := 1;
    for i to n do
        part[i,0] := 0;
        for j to i do  part[i,j] := part[i,j-1]+part[i-j,min(i-j,j)] od
    od;
    op(part)
end:

# Input:  The partition array as described above and a sequence of integers
#         representing a shape.
# Output: The number of shapes of the same degree which are smaller than the
#         given one w.r.t. the lexicographical ordering.

encode := proc(part)
local e,i,n;
options `Copyright 1987 by Ron Sommeling`;
    n := sum(args[i],i = 2 .. nargs);
    e := 0;
    for i from 2 to nargs do  e := e+part[n,args[i]-1]; n := n-args[i] od;
    e
end:

# Input:  A set of groups.
# Output: If there is a group in the set whose set of possible shapes is
#         minimal w.r.t. set inclusion, then this element, otherwise false.

findminelm := proc(grps)
local i,j,m,n,s,t;
options `Copyright 1987 by Ron Sommeling`;
    n := nops(grps);
    s := grps[1][4];
    m := nops(s);
    for i from 2 to n do
        t := grps[i][4]; s := [(s[j]*t[j]) $ (j = 1 .. m)]
    od;
    for i to n do  if grps[i][4] = s then RETURN(grps[i]) fi od;
    false
end:

# Input:  A polynomial in x in factored form and the indeterminate x.
# Output: The sequence of the degrees of the factors in non-decreasing order.
#
# Modified to deal with repeated factors and possible initial factor
# indicating sign:  Copyright 1992 T. Mattman

degrees := proc(factored,x)
local degs, sgn;
options `Copyright 1987 by Ron Sommeling`,
        `Modifications Copyright 1992 by T. Mattman`;
    if not type(factored,{`*`,`^`}) then
        degree(factored,x)
    elif type(factored,`^`) then
        degree(op(1,factored),x) $ op(2,factored)
    else
        if type(op(1,factored),negative) then
            sgn := -1
        else
            sgn := 1
        fi;
        degs := map(degrees,convert(sgn*factored,list),x);
        degs := sort(degs,numeric);
        op(degs)
    fi
end:

# Case distinction between F20 and S5. We factor a resolvent of degree 6
# derived from a resolvent of S5/D5 as suggested by J. Buhler.

special5 := proc(g,x,D,possible,ratpol)
local a2,a4,a6,c,cx4,d,Dn,e,f,grp,h,h2,k,lc,q,R;
options `Copyright 1987 by Ron Sommeling`;
    h := g;
    do
        if 2 < printlevel then lprint(`Calculating a S5/F20 resolvent...`)
        fi;
        lc := lcoeff(h,x);
        cx4 := coeff(h,x,4);
        Dn := sqfreepart(D,ratpol);
        divide(D,Dn,'q');
        k := lc^6*sqrt(q);
        if (cx4 mod 5) = 0 then
            h2 := expand(lc^4*subs(x = (x-(cx4/5))/lc,h))
        else
            h2 := expand(3125*lc^4*subs(x = 1/5*(x-cx4)/lc,h));
            k := 9765625*k
        fi;
        c := coeff(h2,x,3);
        d := 2*coeff(h2,x,2);
        e := 4*coeff(h2,x,1);
        f := 4*coeff(h2,x,0);
        a2 := -5*e-3*c^2;
        a4 := -50*d*f+15*e^2-2*c^2*e+4*c*d^2+3*c^4;
        a6 := 250*c*f^2-50*d*e*f-10*c^2*d*f+5*e^3-11*c^2*e^2+14*c*d^2*e+7*c^4*e
            -4*d^4-4*c^3*d^2-c^6;
        R := x^6+a2*Dn*x^4+a4*Dn^2*x^2-32*k*Dn^3*x+a6*Dn^3;
        if issqfree(R,x) then break else h := numer(subs(x = 1/(x+1),h)) fi
    od;
    if 1 < printlevel then lprint(`Factoring this S5/F20 resolvent...`) fi;
    if type(factor(R),`*`) then
        grp := `F20`;
        if 1 < printlevel then
            lprint(`Reducible, so the Galois group is`,grp)
        fi
    else
        grp := `S5`;
        if 1 < printlevel then
            lprint(`Irreducible, so the Galois group is`,grp)
        fi
    fi;
    if possible[1][1] = grp then possible[1][1 .. 3]
    else possible[2][1 .. 3]
    fi
end:

# Case distinction between S4/Z4 and 2.S4, between 3^2.2^2 and 3^2.D4
# and between PGL2(5) and S6.
# In all cases first the 3-set resolvent is computed and factored, then one
# of its factors g is taken (of degree resp. 12, 2, 20) and a polynomial is
# constructed whose roots are xi + sqrt(D) and xi - sqrt(D), where xi is a
# root of g and D is the discriminant of f. Reducibility of this polynomial
# determines the Galois group.

special6 := proc(f,x,D,possible)
local degs,factored,g,i,gd,grp,grps,h,R,y;
options `Copyright 1987 by Ron Sommeling`;
    grps := short(possible);
    h := f;
    do
        if 2 < printlevel then
            lprint(`Calculating a resolvent polynomial...`)
        fi;
        R := rsetpol(h,x,3);
        if issqfree(h,x) then break else h := expand(subs(x = x+1,h)) fi
    od;
    if grps = {`S4/Z4`,`2.S4`} then
        if 2 < printlevel then
            lprint(`Factoring the resolvent polynomial...`)
        fi;
        factored := factor(R);
        if degree(op(1,factored),x) = 12 then g := op(1,factored)
        else g := op(2,factored)
        fi;
        grp := `S4/Z4`
    elif grps = {`3^2.2^2`,`3^2.D4`} then
        if 2 < printlevel then
            lprint(`Factoring the resolvent polynomial...`)
        fi;
        factored := factor(R);
        if degree(op(1,factored),x) = 2 then g := op(1,factored)
        else g := op(2,factored)
        fi;
        grp := `3^2.2^2`
    elif grps = {`PGL2(5)`,`S6`} then g := R; grp := `PGL2(5)`
    fi;
    for i do
        if 2 < printlevel then
            lprint(`Constructing a special resolvent polynomial...`)
        fi;
        gd := resultant(subs(x = x-y,g),y^2-i^2*D,y);
        gd := normal(gd/content(gd,x));
        if issqfree(gd,x) then break fi
    od;
    if 2 < printlevel then
        lprint(`Factoring the special resolvent polynomial...`)
    fi;
    degs := degrees(factor(gd),x);
    if 1 < nops([degs]) then
        if 2 < printlevel then
            lprint(`Reducible - orbit lengths`,degs);
            lprint(`so the Galois group is`,grp)
        fi;
        if possible[1][1] = grp then possible[1][1 .. 3]
        else possible[2][1 .. 3]
        fi
    else
        if 1 < printlevel then
            lprint(`Irreducible, so the Galois group is`,op(1,grps minus {grp})
                )
        fi;
        if possible[1][1] = grp then possible[2][1 .. 3]
        else possible[1][1 .. 3]
        fi
    fi
end:

# Copyright 1992 T. Mattman; all rights reserved
#                                                            February 15, 1992

# Input:  An expression, n, and a boolean flag, ratint, indicating
#         whether n is an integer or not.
# Output: The square free part of n. The square free part of the integer
#         part of n is determined by isqfreepart; it may not be the complete
#         square free part as that may take too long to calculate.

sqfreepart := proc(n,ratint)
local i,icn,o,pp,sfp;
options `Copyright 1992 by T. Mattman`;
    if ratint then RETURN(isqfreepart(n)) fi;
    icn := icontent(n);
    sfp := isqfreepart(icn);
    pp := factor(n/icn);
    if not type(pp,{`^`,`*`}) then
        sfp := sfp*pp
    elif type(pp, `^`) then
        if type(op(2,pp), odd) then
            sfp := sfp*op(1,pp)
        fi
    else
        for i to nops(pp) do
            o := op(i,pp);
            if type(o, `^`) then
                if type(op(2,o), odd) then
                    sfp := sfp*op(1,o)
                fi
            else
                sfp := sfp*o
            fi
        od
    fi;
    sfp
end:

# Copyright 1992 T. Mattman; all rights reserved
#                                                            February 15, 1992

# Input:  An expression N.
# Output: True if N is a square, false otherwise.

macro( issqr = readlib(issqr) ):
issquare := proc(N)
local i,n,o,pp,s;
    if type(N, integer) then RETURN(issqr(N)) fi;
    n := icontent(N);
    if not issqr(n) then RETURN(false) fi;
    pp := N/n;
    s := simplify(pp^(1/2),sqrt);
    if not type(s,{`^`,`*`}) then
        true
    elif type(s, `^`) then
        type(op(2,s), integer)
    else
        for i to nops(s) do
            o := op(i,s);
            if type(o, `^`) and not type(op(2,o), integer) then
                RETURN(false)
            fi
        od;
        true
    fi
end:


`help/text/galois` := TEXT(
`FUNCTION: galois - compute the Galois group of an irreducible polynomial`,
`   `,
`CALLING SEQUENCES:`,
`   galois( f );`,
`   galois( f, x );`,
`   `,
`PARAMETERS:`,
`   f - an irreducible polynomial with coefficients in Q[t1,t2,...,tm]`,
`   up to degree 7 in the main variable,`,
`   x - main variable (optional if polynomial is univariate).`,
`   `,
`SYNOPSIS:   `,
`- The galois function computes the Galois group of f in Q[t1,t2,...,tm][x]`,
`  This routine is an updated version of the original routine which was`,
`  only for univariate polynomials over Q.`,
`   `,
`- The galois function returns an expression sequence of three elements.  The`,
`  first is the name of the Galois group (with + if even), the second is its`,
`  order and the third is a set of generators of the group.)( A string`,
`  represents the shape (disjoint cycle structure) of each generator.`,
`   `,
`- The first argument is tested for irreducibility and degree within range.`,
`  An error is given if it is not of the right form.`,
`   `,
`- The galois procedure can print out details of how the Galois group is`,
`  computed.  To do this type`,
`  printlevel := 2; before calling galois. To see all of the details type`,
`  printlevel := 3; before invoking galois.`,
`   `,
`EXAMPLES:   `,
`> galois(x^4+x+1);`,
`   `,
`                           S4, 24, {(1 2), (1 2 3 4)}`,
`   `,
`> galois(t^5-5*t+12);`,
`   `,
`                       +D5, 10, {(2 5)(3 4), (1 2 3 4 5)}`,
`   `,
`> galois(x^5+2);`,
`   `,
`                       F20, 20, {(2 3 5 4), (1 2 3 4 5)}`,
`   `,
`> galois(x^4-10*t*x^2+t^2,x);`,
`   `,
`                          +V4, 4, {(12)(34), (13)(24)}`,
`   `,
`> galois(x^4-10*t*x^2+t,x);`,
`   `,
`                             D4, 8, {(1234), (13)}`,
`   `,
`> galois(x^7+4*x^5-3*x^2+5);`,
`   `,
`                       S7, 5040, {(1 2), (1 2 3 4 5 6 7)}`,
`   `,
`SEE ALSO:  group, GF`
):


# Reminder for MBM only not to comment this out for loading.
save special5, special6, issquare, sqfreepart, a_to_s, short, rsetpol,
      issqfree, initpart, encode, degrees, findminelm, isqfreepart, galois,
      twoseqpol, groups, cyclepattern, s_to_a, `help/text/galois`,

`galois.m`;
quit
