示例#1
0
文件: testrand.c 项目: GDXN/test
int main(int N, char ** S)
{
	unsigned char	gseed[SEED_TOTAL], * ptr ;
	unsigned char	gdata[TEST_BLOCK] ;
	int istep, ival ;

	if ( read_devrand(gseed, SEED_RAND)) { exit( 1) ; }

	ptr= gseed + SEED_RAND ;
	ival= getpid() ;  if ( ival ) { PACK2(ptr, ival) ; }
	ival= getuid() ;  if ( ival ) { PACK2(ptr, ival) ; }

#ifdef	_POSIX_TIMERS
	{
		struct timespec tspec ;
		if ( ! clock_gettime(CLOCK_REALTIME, &tspec )) { ival= tspec.tv_nsec ;  PACK4(ptr, ival) ; }
	}
#endif

	RAND_seed(gseed, ( ptr - gseed )) ;
	if (! RAND_status())
		{ fprintf(stderr, "RAND not initialized\n") ;  exit( 1) ; }

	if ( ! RAND_bytes(gdata, TEST_BLOCK) )
		{ fprintf(stderr, "RAND bytes failed\n") ;  exit( 1) ; }

	for ( istep= TEST_BLOCK, ptr= gdata ; ( istep -- ) ; ptr ++ )
		{ printf("%02x", * ptr ) ; }
	printf("\n\n") ;

	return 0 ;
}
示例#2
0
void find_commutator (int cp1, int cp2, int cp3, int cp4, int result, struct pcp_vars *pcp)
{
   register int *y = y_address;
   int r;     
   int exp;
   register int i;
   int str = pcp->lused + 1;
   register int p = pcp->p;
   register int lastg = pcp->lastg;

#include "access.h"

   y[str] = 1;
    
   for (i = 1; i <= lastg; ++i) {

      /* compute r and adjust its value mod p */
      r = (y[cp3 + i] + y[cp4 + i]) - (y[cp1 + i] + y[cp2 + i]);
      while (r < 0) r += p;
      while (r >= p) r -= p;

      /* store the exponent of generator i in x */
      y[result + i] = r;

      /* now compute the new u_2 */
      if (y[cp4 + i] != 0) {
	 y[str + 1] = PACK2 (y[cp4 + i], i);
	 collect (-str + 1, cp3, pcp);
	 y[cp3 + i] = 0;
      }

      /* compute the residue mod p */
      exp = y[cp2 + i] + r;
      while (exp < 0) exp += p;
      exp %= p;

      /* now compute the new v_1 */
      if (y[cp2 + i] + r >= p)
	 y[cp2 + i] = p - r;
      if (r != 0) {
	 y[str + 1] = PACK2 (r, i);
	 collect (-str + 1, cp2, pcp);
      }

      /* now compute the new u_1 */
      if (y[cp1 + i] + exp >= p)
	 y[cp2 + i] = p - exp;
      if (exp != 0) {
	 y[str + 1] = PACK2 (exp, i);
	 collect (-str + 1, cp1, pcp);
      }
   }
}
示例#3
0
void invert_generator(int gen, int exp, int cp, struct pcp_vars *pcp)
{
   register int *y = y_address;

   register int i;
   register int inverse;
   register int entry;
   register int lastg = pcp->lastg;
   register int cp1 = pcp->submlg;
   register int p = pcp->p;

#include "access.h"

   /* each call to collect involves a string of length 1;
      reserve two positions below y[pcp->submlg] for this */
   inverse = cp1 - 2;
   y[inverse + 1] = 1;

   /* set up gen^exp as an exponent vector with base address cp1 */
   for (i = 1; i <= lastg; ++i)
      y[cp1 + i] = 0;
   y[cp1 + gen] = exp;

   /* now calculate the inverse, storing the result at cp */
   for (i = gen; i <= lastg; ++i) {
      entry = y[cp1 + i];
      if (entry != 0) {
         y[inverse + 2] = PACK2(p - entry, i);
         collect(-inverse, cp, pcp);
         collect(-inverse, cp1, pcp);
      }
   }
}
示例#4
0
static void test_term_char_packing(void)  {
        uint32_t seqs[][1024] = {
                { -1 },
                { 0, -1 },
                { 'A', '~', -1 },
                { 'A', '~', 0, -1 },
                { 'A', '~', 'a', -1 },
        };
        term_char_t res[] = {
                TERM_CHAR_NULL,
                PACK1(0),
                PACK2('A', '~'),
                PACK3('A', '~', 0),
                PACK3('A', '~', 'a'),
        };
        uint32_t next;
        unsigned int i, j;
        term_char_t c = TERM_CHAR_NULL;

        /*
         * This creates term_char_t objects based on the data in @seqs and
         * compares the result to @res. Only basic packed types are tested, no
         * allocations are done.
         */

        for (i = 0; i < ELEMENTSOF(seqs); ++i) {
                for (j = 0; j < ELEMENTSOF(seqs[i]); ++j) {
                        next = seqs[i][j];
                        if (next == (uint32_t)-1)
                                break;

                        c = term_char_merge(c, next);
                }

                assert_se(!memcmp(&c, &res[i], sizeof(c)));
                c = term_char_free(c);
        }
}
示例#5
0
void jacobi(int c, int b, int a, int ptr, struct pcp_vars *pcp)
{
   register int *y = y_address;

   register int i;
   register int k;
   register int p1;
   register int cp1;
   register int cp2;
   register int unc;
   register int address;
   register int ycol;
   register int commba;
   register int count;
   register int count2;
   register int offset;

   register int lastg = pcp->lastg;
   register int prime = pcp->p;
   register int pm1 = pcp->pm1;
   register int p_power = pcp->ppower;
   register int p_pcomm = pcp->ppcomm;

#include "access.h"

#if defined(GROUP)
   if (is_space_exhausted(2 * lastg + 3, pcp))
      return;
#endif

   /* cp1 and cp2 are the base addresses for the collected
      part of the lhs and of the rhs, respectively */
   cp1 = pcp->lused;
   cp2 = cp1 + lastg;
   unc = cp2 + lastg + 1;

   for (i = 1; i <= lastg; i++)
      y[cp1 + i] = y[cp2 + i] = 0;

   /* calculate the class pcp->cc part of the jacobi relation
      (b^p) a = b^(p - 1) (ba) */

   if (c == b) {
      ycol = y[p_power + b];
      collect(ycol, cp1, pcp);
      collect(a, cp1, pcp);

      if (b != a) {
         y[cp2 + b] = pm1;
         p1 = y[p_pcomm + b];
         commba = y[p1 + a];
         collect(a, cp2, pcp);
         collect(b, cp2, pcp);
         collect(commba, cp2, pcp);
      } else {
         /* we are processing (a^p) a = a (a^p) */
         ycol = y[p_power + a];
         y[cp2 + a] = 1;
         collect(ycol, cp2, pcp);
      }
   } else {
      if (b - a > 0) {
#if defined(GROUP)
         /* calculate the class pcp->cc part of the jacobi relation
            (cb) a = c (ba); set up a as the collected part for lhs */
         y[cp1 + c] = 1;
         collect(b, cp1, pcp);
         collect(a, cp1, pcp);
         y[cp2 + c] = 1;
         collect(a, cp2, pcp);
         collect(b, cp2, pcp);
         p1 = y[p_pcomm + b];
         commba = y[p1 + a];
         collect(commba, cp2, pcp);
#endif
      } else {
         /* calculate the class pcp->cc part of the jacobi relation
            (ca) a^(p - 1) = c (a^p); first collect rhs */
         ycol = y[p_power + a];
         y[cp2 + c] = 1;
         collect(ycol, cp2, pcp);

         /* collect lhs; set up c as collected part */
         y[cp1 + c] = 1;
         collect(a, cp1, pcp);
         y[unc] = 1;
         y[unc + 1] = PACK2(pm1, a);
         collect(-unc + 1, cp1, pcp);
      }
   }

   /* the jacobi collections are completed */

   if ((p1 = ptr) > 0) {
      /* we are filling in the tail on y[p1]; convert the class pcp->cc
         part to string form in y[cp1 + 2 + 1] to y[cp1 + 2 + count]
         where count is the string length */

      count = 0;
      for (i = pcp->ccbeg; i <= lastg; i++) {
         k = y[cp1 + i] - y[cp2 + i];
         if (k != 0) {
            if (k < 0)
               k += prime;
            ++count;
            y[cp1 + 2 + count] = PACK2(k, i);
         }
      }

      if (count > 0) {
         /* y[p1] was trivial to class pcp->cc - 1 so create a new entry */
         if (y[p1] >= 0) {
            y[p1] = -(cp1 + 1);
            y[cp1 + 1] = p1;
            y[cp1 + 2] = count;
            pcp->lused += count + 2;
         } else {
            /* the class pcp->cc part is nontrivial so make room for
               lower class terms */
            address = -y[p1];
            count2 = y[address + 1];

            /* move class pcp->cc part up */
            offset = cp1 + count + 3;
            for (i = 1; i <= count; i++)
               y[offset + count2 - i] = y[offset - i];

            /* copy in lower class terms */
            for (i = 1; i <= count2; i++)
               y[cp1 + 2 + i] = y[address + i + 1];

            /* create new header block */
            y[cp1 + 1] = y[address];
            y[cp1 + 2] = count + count2;

            /* deallocate old entry */
            y[address] = 0;

            /* set up pointer to new entry */
            y[p1] = -(cp1 + 1);
            pcp->lused += count + count2 + 2;
         }
      }
   } else {
      /* we are checking consistency equations */
      echelon(pcp);
      if ((pcp->fullop && pcp->eliminate_flag) || pcp->diagn)
         text(9, c, b, a, 0);
   }
}
示例#6
0
static void test_term_line_ops(void) {
        term_line *l;
        term_attr attr_regular = { };
        term_attr attr_bold = { .bold = true };
        term_attr attr_italic = { .italic = true };

        assert_se(term_line_new(&l) >= 0);
        line_resize(l, 8, NULL, 0);
        assert_se(l->n_cells == 8);

        LINE_ASSERT(l, "| | | | | | | | |", 0);

        term_line_write(l, 4, TERM_CHAR_NULL, 0, NULL, TERM_AGE_NULL, 0);
        LINE_ASSERT(l, "| | | | | | | | |", 5);

        term_line_write(l, 1, PACK1('A'), 1, NULL, TERM_AGE_NULL, 0);
        LINE_ASSERT(l, "| |A| | | | | | |", 5);

        term_line_write(l, 8, PACK2('A', 'B'), 1, NULL, TERM_AGE_NULL, 0);
        LINE_ASSERT(l, "| |A| | | | | | |", 5);

        term_line_write(l, 7, PACK2('A', 'B'), 1, &attr_regular, 10, 0);
        LINE_ASSERT(l, "| |A| | | | | | 10 AB |", 8);

        term_line_write(l, 7, PACK2('A', 'B'), 1, &attr_bold, 10, 0);
        LINE_ASSERT(l, "| |A| | | | | | 10 *AB* |", 8);

        term_line_reset(l, NULL, TERM_AGE_NULL);

        LINE_ASSERT(l, "|   |   |          |          |          |   |   |   |", 0);
        line_set(l, 2, "*wxyz* 8", 0);
        line_set(l, 3, "/wxyz/ 8", 0);
        LINE_ASSERT(l, "|   |   | *wxyz* 8 | /wxyz/ 8 |          |   |   |   |", 4);
        line_set(l, 2, "*abc* 9", true);
        LINE_ASSERT(l, "|   |   | *abc* 9  | *wxyz* 9 | /wxyz/ 9 | 9 | 9 | 9 |", 5);
        line_set(l, 7, "*abc* 10", true);
        LINE_ASSERT(l, "|   |   | *abc* 9  | *wxyz* 9 | /wxyz/ 9 | 9 | 9 | *abc* 10 |", 8);

        term_line_erase(l, 6, 1, NULL, 11, 0);
        LINE_ASSERT(l, "|   |   | *abc* 9  | *wxyz* 9 | /wxyz/ 9 | 9 | 11 | *abc* 10 |", 8);
        term_line_erase(l, 6, 2, &attr_italic, 12, 0);
        LINE_ASSERT(l, "|   |   | *abc* 9  | *wxyz* 9 | /wxyz/ 9 | 9 | 12 // | 12 // |", 6);
        term_line_erase(l, 7, 2, &attr_regular, 13, 0);
        LINE_ASSERT(l, "|   |   | *abc* 9  | *wxyz* 9 | /wxyz/ 9 | 9 | 12 // | 13 |", 6);
        term_line_delete(l, 1, 3, &attr_bold, 14);
        LINE_ASSERT(l, "|   | /wxyz/ 14 | 14 | 14 // | 14 | 14 ** | 14 ** | 14 ** |", 3);
        term_line_insert(l, 2, 2, &attr_regular, 15);
        LINE_ASSERT(l, "|   | /wxyz/ 14 | 15 | 15 | 15 | 15 // | 15 | 15 ** |", 5);

        assert_se(!term_line_free(l));
}

int main(int argc, char *argv[]) {
        test_term_char_misc();
        test_term_char_packing();
        test_term_char_allocating();

        test_term_line_misc();
        test_term_line_ops();

        return 0;
}
示例#7
0
static void test_term_char_allocating(void) {
        uint32_t seqs[][1024] = {
                { 0, -1 },
                { 'A', '~', -1 },
                { 'A', '~', 0, -1 },
                { 'A', '~', 'a', -1 },
                { 'A', '~', 'a', 'b', 'c', 'd', -1 },
                { 'A', '~', 'a', 'b', 'c', 'd', 0, '^', -1 },
                /* exceeding implementation-defined soft-limit of 64 */
                { 'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd',
                  'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd',
                  'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd',
                  'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd',
                  'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd',
                  'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd',
                  'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd',
                  'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd', -1 },
        };
        term_char_t res[] = {
                PACK1(0),
                PACK2('A', '~'),
                PACK3('A', '~', 0),
                PACK3('A', '~', 'a'),
                TERM_CHAR_NULL,                 /* allocated */
                TERM_CHAR_NULL,                 /* allocated */
                TERM_CHAR_NULL,                 /* allocated */
        };
        uint32_t str[][1024] = {
                { 0, -1 },
                { 'A', '~', -1 },
                { 'A', '~', 0, -1 },
                { 'A', '~', 'a', -1 },
                { 'A', '~', 'a', 'b', 'c', 'd', -1 },
                { 'A', '~', 'a', 'b', 'c', 'd', 0, '^', -1 },
                { 'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd',
                  'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd',
                  'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd',
                  'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd',
                  'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd',
                  'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd',
                  'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd',
                  'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd', -1 },
        };
        size_t n;
        uint32_t next;
        unsigned int i, j;
        const uint32_t *t;

        /*
         * This builds term_char_t objects based on the data in @seqs. It
         * compares the result to @res for packed chars, otherwise it requires
         * them to be allocated.
         * After that, we resolve the UCS-4 string and compare it to the
         * expected strings in @str.
         */

        for (i = 0; i < ELEMENTSOF(seqs); ++i) {
                _term_char_free_ term_char_t c = TERM_CHAR_NULL;

                for (j = 0; j < ELEMENTSOF(seqs[i]); ++j) {
                        next = seqs[i][j];
                        if (next == (uint32_t)-1)
                                break;

                        c = term_char_merge(c, next);
                }

                /* we use TERM_CHAR_NULL as marker for allocated chars here */
                if (term_char_is_null(res[i]))
                        assert_se(term_char_is_allocated(c));
                else
                        assert_se(!memcmp(&c, &res[i], sizeof(c)));

                t = term_char_resolve(c, &n, NULL);
                for (j = 0; j < ELEMENTSOF(str[i]); ++j) {
                        next = str[i][j];
                        if (next == (uint32_t)-1)
                                break;

                        assert_se(t[j] == next);
                }

                assert_se(n == j);
        }
}
示例#8
0
int echelon(struct pcp_vars *pcp)
{
   register int *y = y_address;

   register int i;
   register int j;
   register int k;
   register int p1;
   register int exp;
   register int redgen = 0;
   register int count = 0;
   register int factor;
   register int bound;
   register int offset;
   register int temp;
   register int value;
   register int free;

   register Logical trivial;
   register Logical first;

   register int p = pcp->p;
   register int pm1 = pcp->pm1;

#include "access.h"

   pcp->redgen = 0;
   pcp->eliminate_flag = FALSE;

   /* check that the relation is homogeneous of class pcp->cc */
   if (pcp->cc != 1) {
      offset = pcp->lused - 1;
      temp = pcp->lastg;
      for (i = 2, bound = pcp->ccbeg; i <= bound; i++) {
         if (y[offset + i] != y[offset + temp + i]) {
            text(6, pcp->cc, 0, 0, 0);
            pcp->eliminate_flag = TRUE;
            return -1;
         }
      }
   }

   /* compute quotient of the relations and store quotient as an exponent
      vector in y[pcp->lused + pcp->ccbeg] to y[pcp->lused + pcp->lastg] */
   k = 0;
   offset = pcp->lused;
   for (i = pcp->ccbeg, bound = pcp->lastg; i <= bound; i++) {
      y[offset + i] -= y[offset + bound + i];
      if ((j = y[offset + i])) {
         if (j < 0)
            y[offset + i] += p;
         k = i;
      }
   }

   if (k <= 0)
      return -1;

   /* print out the quotient of the relations */
   if (pcp->diagn) {
      /* a call to compact is not permitted at this point */
      if (pcp->lused + 4 * pcp->lastg + 2 < pcp->structure) {
         /* first copy relevant entries to new position in y */
         free = pcp->lused + 2 * pcp->lastg + 1;
         for (i = 1; i < pcp->ccbeg; ++i)
            y[free + i] = 0;
         for (i = pcp->ccbeg; i <= pcp->lastg; ++i)
            y[free + i] = y[pcp->lused + i];
         setup_word_to_print(
             "quotient relation", free, free + pcp->lastg + 1, pcp);
      }
   }

   first = TRUE;

   while (first || --k >= pcp->ccbeg) {
      /* does generator k occur in the unechelonised relation? */
      if (!first && y[pcp->lused + k] <= 0)
         continue;

      /* yes */
      first = FALSE;
      exp = y[pcp->lused + k];
      if ((i = y[pcp->structure + k]) <= 0) {
         if (i < 0) {
            /* generator k was previously redundant, so eliminate it */
            p1 = -y[pcp->structure + k];
            count = y[p1 + 1];
            offset = pcp->lused;
            for (i = 1; i <= count; i++) {
               value = y[p1 + i + 1];
               j = FIELD2(value);
               /* integer overflow can occur here; see comments in collect */
               y[offset + j] = (y[offset + j] + exp * FIELD1(value)) % p;
            }
         }
         y[pcp->lused + k] = 0;
      } else {
         /* generator k was previously irredundant; have we already
            found a generator to eliminate using this relation? */
         if (redgen > 0) {
            /* yes, so multiply this term by the appropriate factor
               and note that the value of redgen is not trivial */
            trivial = FALSE;
            /* integer overflow can occur here; see comments in collect */
            y[pcp->lused + k] = (y[pcp->lused + k] * factor) % p;
         } else {
            /* no, we will eliminate k using this relation */
            redgen = k;
            trivial = TRUE;

            /* we want to compute the value of k so we will multiply the
               rest of the relation by the appropriate factor;
               integer overflow can occur here; see comments in collect */
            factor = pm1 * invert_modp(exp, p);

/* we carry out this mod computation to reduce possibility
   of integer overflow */
#if defined(CAREFUL)
            factor = factor % p;
#endif
            y[pcp->lused + k] = 0;
         }
      }
   }

   if (redgen <= 0)
      return -1;
   else
      pcp->redgen = redgen;

   /* the relation is nontrivial; redgen is either trivial or redundant */

   if (trivial) {
      /* mark redgen as trivial */
      y[pcp->structure + redgen] = 0;

      if (pcp->fullop)
         text(3, redgen, 0, 0, 0);

      complete_echelon(1, redgen, pcp);
   } else {
      /* redgen has value in exponent form in y[pcp->lused + pcp->ccbeg]
         to y[pcp->lused + redgen(-1)] */
      count = 0;
      offset = pcp->lused;
      for (i = pcp->ccbeg; i <= redgen; i++)
         if (y[offset + i] > 0) {
            count++;
            y[offset + count] = PACK2(y[offset + i], i);
         }
      offset = pcp->lused + count + 1;
      for (i = 1; i <= count; i++)
         y[offset + 2 - i] = y[offset - i];

      /* set up the relation for redgen */
      y[pcp->lused + 1] = pcp->structure + redgen;
      y[pcp->lused + 2] = count;
      y[pcp->structure + redgen] = -(pcp->lused + 1);

      pcp->lused += count + 2;

      if (pcp->fullop)
         text(4, redgen, 0, 0, 0);

      complete_echelon(0, redgen, pcp);
   }

   pcp->eliminate_flag = TRUE;
   if (redgen < pcp->first_pseudo)
      pcp->newgen--;
   if (pcp->newgen != 0 || pcp->multiplicator)
      return count;

   /* group is completed because all actual generators are redundant,
      so it is not necessary to continue calculation of this class */
   pcp->complete = 1;
   last_class(pcp);

   if (pcp->fullop || pcp->diagn)
      text(5, pcp->cc, p, pcp->lastg, 0);

   return -1;
}
示例#9
0
void complete_echelon(Logical trivial, int redgen, struct pcp_vars *pcp)
{
   register int *y = y_address;

   int k;
   int i, j, jj, exp;
   int p1;
   int factor;
   int count, count1, count2;
   int predg;
   int offset;
   int temp;
   int value;
   int bound;
   int l;
   int p = pcp->p;

#include "access.h"

   if (trivial) {
      /* delete all occurrences of redgen from other equations */
      for (k = redgen + 1, bound = pcp->lastg; k <= bound; k++) {
         if (y[pcp->structure + k] >= 0)
            continue;
         p1 = -y[pcp->structure + k];
         count = y[p1 + 1];
         for (j = 1; j <= count; j++)
            if ((temp = FIELD2(y[p1 + j + 1])) >= redgen)
               break;
         if (j > count || temp > redgen)
            continue;

         /* redgen occurs in this relation, so eliminate it;
            is redgen in the last word? */
         count1 = count - 1;

         if (j < count) {
            /* no, so pack up relation */
            for (jj = j; jj <= count1; jj++)
               y[p1 + jj + 1] = y[p1 + jj + 2];
         }

         if (j < count || (j >= count && count1 > 0)) {
            /* deallocate last word and fix count in header block */
            y[p1 + count + 1] = -1;
            y[p1 + 1] = count1;
            continue;
         }

         /* old relation is to be eliminated (it was 1 word long) */
         y[p1] = 0;
         y[pcp->structure + k] = 0;
      }
   } else {
      p1 = -y[pcp->structure + redgen];
      count = y[p1 + 1];

      /* eliminate all occurrences of redgen from the other relations
         by substituting its value */
      for (k = redgen + 1, bound = pcp->lastg; k <= bound; k++) {
         if (y[pcp->structure + k] >= 0)
            continue;
         if (is_space_exhausted(pcp->lastg + 1, pcp))
            return;
         p1 = -y[pcp->structure + k];
         count1 = y[p1 + 1];
         for (j = 1; j <= count1; j++)
            if ((temp = FIELD2(y[p1 + j + 1])) >= redgen)
               break;
         if (j > count1 || temp > redgen)
            continue;

         /* redgen occurs in this relation, so eliminate it */
         factor = FIELD1(y[p1 + j + 1]);
         predg = -y[pcp->structure + redgen];

         /* merge old relation with factor * (new relation), deleting redgen;
            old relation is longer than new relation since it contains redgen */

         /* commence merge */
         count2 = 0;
         offset = pcp->lused + 2;
         for (i = 1, l = 1;;) {
            temp = FIELD2(y[p1 + i + 1]) - FIELD2(y[predg + l + 1]);
            if (temp < 0) {
               count2++;
               y[offset + count2] = y[p1 + i + 1];
               i++;
            } else if (temp > 0) {
               count2++;
               /* integer overflow can occur here; see comments in collect */
               value = y[predg + l + 1];
               y[offset + count2] =
                   PACK2((factor * FIELD1(value)) % p, FIELD2(value));
               if (++l > count)
                  break;
            } else {
               /* integer overflow can occur here; see comments in collect */
               value = y[p1 + i + 1];
               exp = (FIELD1(value) + factor * FIELD1(y[predg + l + 1])) % p;
               if (exp > 0) {
                  count2++;
                  y[offset + count2] = PACK2(exp, FIELD2(value));
               }
               i++;
               if (++l > count)
                  break;
            }
         }

         /* all of the value of redgen has been merged in;
            copy in the remainder of the old relation with redgen deleted */
         offset = pcp->lused + 2;
         for (jj = i; jj <= count1; jj++)
            if (jj != j) {
               count2++;
               y[offset + count2] = y[p1 + jj + 1];
            }

         /* new relation is now in y[lused + 2 + 1] to y[lused + 2 + count2] */

         /* new relation indicates generator k is trivial; deallocate old */
         if (count2 <= 0) {
            y[p1] = 0;
            y[pcp->structure + k] = 0;
            continue;
         }

         /* new relation is nontrivial */

         if (count2 < count1) {
            /* new relation is shorter than old; copy in new relation */
            for (i = 1; i <= count2; i++)
               y[p1 + i + 1] = y[pcp->lused + 2 + i];

            /* reset count field for new relation */
            y[p1 + 1] = count2;

            /* deallocate rest of old relation */
            if (count1 == count2 + 1)
               y[p1 + count2 + 2] = -1;
            else {
               y[p1 + count2 + 2] = 0;
               y[p1 + count2 + 3] = count1 - count2 - 2;
            }
         } else if (count1 == count2) {
            /* new relation has same length as old; overwrite old relation */
            offset = pcp->lused + 2;
            for (i = 1; i <= count2; i++)
               y[p1 + i + 1] = y[offset + i];
         } else {
            /* new relation is longer than old; deallocate old relation */
            y[p1] = 0;

            /* set up pointer to new relation and header block */
            y[pcp->structure + k] = -(pcp->lused + 1);
            y[pcp->lused + 1] = pcp->structure + k;
            y[pcp->lused + 2] = count2;
            pcp->lused += count2 + 2;
         }
      }
   }
}