/* Last edited on 2012-12-20 05:29:10 by stolfilocal */ uint64_t logsys_urandom(int n); /* Generates a random unsigned integer with {n} bits, i.e. in the range {0..2^n - 1}. */ uint64_t logsys_urandom(int n) { uint64_t res = 0; int k; for (k = 0; k < 2; k++) { uint32_t lo = (uint32_t)random(); uint32_t hi = (uint32_t)random(); uint32_t mask = ((ONE64 << n) - 1u); uint32_t rnd = ((lo >> 3) ^ (hi << 13)) & mask; res = (res << 32) | rnd; } return res; } /* from logsys_try_to_simplify_equation */ /* Build a new op for the relevant arguments only: */ logsys_op_t op_new = 0; int NX = (1 << n_new); /* Number of assignments for {n_new} args. */ assert (NX <= logsys_NX_MAX); uint32_t X; for (X = 0; X < NX; X++) { /* Compute the equivalent assignment in the old args: */ uint32_t Y = 0; j_new = 0; for (j_old = 0; j_old < n_old; j_old++) { if (relevant[j_old]) { if ((X & (1 << j_old)) != 0) { Y = Y | (1 << j_new); } j_new++; } } assert(j_new == n_new); if ((eq->op & (ONE64 << Y)) != 0) { op_new = op_new | (ONE64 << X); } } eq->op = op_new; /* from logsys_condense_and_split: */ /* Re-sort the equations by increasing arity if needed: */ logsys_sort_equations(S); } /* At this point {S->eq} is the first equation in order of increasing arity. We scan every equation {fq}, beginning with the first equation with arity greater than 1 and proceeding in order of increasing arity until {S->eq->preq}, looking for simplifications. Either we improve the system and set {sys_changed} to true; or we fail and set {exhausted} to true. */ if (debug) { logsys_print_equation(stderr, " basis {eq} = ", S->eq, "\n"); } logsys_eq_t *fq = S->eq; /* Next pivot equation. */ while ((fq != S->eq->preq) && (fq->n < 2)) { fq = fq->nxeq; } bool_t sys_changed = FALSE; /* For this iteration, until we make some change. */ bool_t exhausted = (fq->n < 2); /* Set to true if we have scanned all multi-ary pivots with no change. */ while ((! sys_changed) && (! exhausted)) { if (debug) { logsys_print_equation(stderr, " pivot {fq} = ", fq, "\n"); } /* Try to combine {fq} with all equations that share variables with it: */ sys_changed = logsys_try_to_combine_with_others(S->eq, fq); if (sys_changed) { /* The pointer {fq} may be invalid now: */ fq = NULL; } else { /* We scanned all equations that share variables with {fq} with no change: */ if (debug) { fprintf(stderr, " failed to split or merge {fq}\n"); } if (fq == S->eq->preq) { exhausted = TRUE; } else { fq = fq->nxeq; } } if (debug) { fprintf(stderr, " sys_changed = %c exhausted = %c\n", "01"[sys_changed], "01"[exhausted]); } /* From logsolve.c */ uint32_t x = logsolve_pick_factor(nx, 0); uint32_t y = logsolve_pick_factor(ny, x); uint32_t logsolve_pick_factor(int n, uint32_t avoid); /* Picks a good {n}-bit factor for testing the multiplier, other than {avoid}. */ uint32_t logsolve_pick_factor(int n, uint32_t avoid) { assert(n <= 31); uint32_t fmask = (ONE64 << (uint64_t)n) + ALL64; uint32_t d, f; do { do { f = fmask & uint64_random(); } while (f == avoid); d = (uint32_t)floor(sqrt((double)f)); while ((d > 1) && (f % d != 0)) { d--; } } while (d > 1); return f; } /* from logsys_sort_H4.c */ auto void update_dist(void); /* Assumes {dist} was consistent except that {dist[vix[nroots-1]]} has just been set to zero. Updates {dist[0..nvok-1]} and sorts {vix[nroots..nvok-1]} by increasing distance */ void update_dist(void) { /* Now scan vars, update distances and sort them: */ int nscan = nroots-1; assert(dist[vix[nscan]] == 0); /* Assume it has just been set to 0. */ while (nscan < nvok) { /* Get next pivot variable {ua} from {vix[nscan]}: */ logsys_va_t *ua = va[vix[nscan]]; assert(ua->id == vix[nscan]); /* Enumerate equations that use {ua}: */ logsys_eq_t *eq = ua->use; if (eq != NULL) { do { int j = logsys_find_arg(eq, ua); /* Enumerate the other variables of {eq}: */ int k; for (k = 0; k < eq->n; k++) { if (k != j) { logsys_va_t *ub = eq->arg[k].va; /* Decide the length of the arc from {ua} to {ub}: */ double dab = 1.0; /* For now. */ double dbnew = dist[ua->id] + dab; /* Update {ub}'s distance: */ if (dist[ub->id] > dbnew) { dist[ub->id] = dbnew; } } } eq = eq->arg[j].nxeq; } while (eq != ua->use); } /* Got one more scanned: */ nscan++; /* Make sure that {vix[nscan]} is the smallest of {vix[nscan..nvok-1]}: */ /* Bubble sort pass to bring the minimum to {vix[nscan]}: */ /* !!! Shoudl use a heap !!! */ int i = nvok - 1; while (i > nscan) { int j = i - 1; double di = dist[vix[i]]; double dj = dist[vix[j]]; if (di < dj) { /* Swap: */ int tmp = vix[i]; vix[i] = vix[j]; vix[j] = tmp; } i = j; } } /* Now all vars must be sorted by increasing distance from {va[vix[0..nroots-1]]}. */ if (debug) { int ifar = vix[nvok-1]; logsys_print_variable_id(stderr, " farthest variable is v", ifar, 4, NULL); fprintf(stderr, " distance = %9.6f\n", dist[ifar]); } }