#include "pq_defs.h"
#include "pcp_vars.h"
#include "pga_vars.h"
#include "constants.h"
#include "pq_functions.h"
#define COMBINATION 100

/* the automorphism group is insoluble -- 
   first, compute the orbits of the allowable subgroups under
   the action of the insoluble subgroup of the relevent general 
   linear group; then compute the orbits under the action of the 
   the soluble group generated by the central automorphisms */

void combined_computation (auts, a, b, c, perms, orbit_length, pga, pcp)
int ***auts;
int **a;
int **b;
char **c;
int **perms;
int **orbit_length;
struct pga_vars *pga;
struct pcp_vars *pcp;
{
   int *insoluble_length;
   int offset;
   int *temp;
   int **copy_perms;
   struct pga_vars copy_pga;
   int nmr_soluble;
   int i, j, rep;

   nmr_soluble = find_soluble_auts (auts, pga, pcp);
   if (nmr_soluble == 0) return;

#if defined (DEBUG)
   printf ("The number of soluble generators is %d\n", nmr_soluble);
   printf ("First, list the orbits with true lengths:\n");
   orbit_summary (*orbit_length, pga);
#endif 

   /* how many non-trivial soluble automorphisms are there? */
   for (i = 1, offset = 0; i <= nmr_soluble; ++i)
      if (pga->map[i] != 0) 
         ++offset;

   /* if there are non-trivial soluble automorphisms, compute 
      orbits under action of insoluble subgroup of relevant GL;
      otherwise, it is not necessary to do so since the orbits
      are the same as under the whole automorphism group which
      we have already computed */

   if (offset != 0) {
      copy_pga = *pga;
      copy_pga.soluble = FALSE;

      /* set up copy_perms to point to the insoluble permutations */
      copy_perms = perms + offset;
      copy_pga.m = copy_pga.nmr_of_perms = pga->m - nmr_soluble;

      /* free some space allocated in earlier complete orbit computation */
      free_vector (*a, 1);

      /* now carry out the insoluble computation */
      orbit_option (COMBINATION, copy_perms, a, b, c, &insoluble_length, 
                    &copy_pga);

#if defined (DEBUG)
      printf ("Now completed insoluble portion:\n");
      orbit_summary (insoluble_length, copy_pga);
#endif 

      /* for each orbit representative, find the length of its
         insoluble orbit and store this length in orbit_length; 
	 this is required for the insoluble stabiliser computation */

      for (i = 1; i <= pga->nmr_orbits; ++i) {
         rep = pga->rep[i];
         for (j = 1; j <= copy_pga.nmr_orbits && rep != copy_pga.rep[j]; ++j) 
            ;
         (*orbit_length)[i] = insoluble_length[j];
      }

#if defined (DEBUG)
      printf ("Now list orbits with the revised orbit lengths:\n");
      orbit_summary (*orbit_length, pga);
#endif 

      /* free space allocated for insoluble orbit computation */
      free_vector (*a, 1);
      free_vector (insoluble_length, 1);
      free_vector (copy_pga.rep, 1);
   }

   /* now compute the orbits under the soluble automorphisms */
   copy_pga = *pga;
   copy_pga.soluble = TRUE;
   copy_pga.m = nmr_soluble;
   copy_pga.nmr_of_perms = offset;
   orbit_option (COMBINATION, perms, a, b, c, &temp, &copy_pga);

#if defined (DEBUG)
   printf ("Now completed soluble portion:\n");
#endif 

   /* set the flag to indicate that this is a combined computation */
   pga->combined = TRUE;
}

/* find the number of central generators of the automorphism group -- 
   do this by finding the last automorphism group generator which is 
   not an element of the appropriate general linear group */

int find_soluble_auts (auts, pga, pcp)
int ***auts;
struct pga_vars *pga;
struct pcp_vars *pcp;
{
#include "define_y.h"

   register int i, j, k;
   int nmr_of_exponents, nmr_of_generators; 

   nmr_of_exponents = y[pcp->clend + pcp->cc - 1];
   nmr_of_generators = y[pcp->clend + 1];

   for (i = pga->m; i >= 1; --i)  
      for (j = 1; j <= nmr_of_generators; ++j)  
         for (k = nmr_of_generators + 1; k <= nmr_of_exponents; ++k)  
            if (auts[i][j][k] != 0)
               return i;
   return 0;
}
