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 ; }
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); } } }
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); } } }
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); } }
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); } }
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; }
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); } }
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; }
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; } } } }