void reducearray ( lrs_mp_vector p, long n ) /* find largest gcd of p[0]..p[n-1] and divide through */ { lrs_mp divisor; lrs_mp Temp; long i = 0L; while ( ( i < n ) && zero ( p[i] ) ) i++; if ( i == n ) return; copy ( divisor, p[i] ); storesign ( divisor, POS ); i++; while ( i < n ) { if ( !zero ( p[i] ) ) { copy ( Temp, p[i] ); storesign ( Temp, POS ); gcd ( divisor, Temp ); } i++; } /* reduce by divisor */ for ( i = 0; i < n; i++ ) if ( !zero ( p[i] ) ) reduceint ( p[i], divisor ); } /* end of reducearray */
void reduce ( lrs_mp Na, lrs_mp Da ) { /* reduces Na Da by gcd(Na,Da) */ lrs_mp Nb, Db, Nc, Dc; copy ( Nb, Na ); copy ( Db, Da ); storesign ( Nb, POS ); storesign ( Db, POS ); copy ( Nc, Na ); copy ( Dc, Da ); gcd ( Nb, Db ); /* Nb is the gcd(Na,Da) */ exactdivint ( Nc, Nb, Na ); exactdivint ( Dc, Nb, Da ); }
void atomp ( char s[], lrs_mp a ) { /*convert string to lrs_mp integer */ lrs_mp mpone; long diff, ten, i, sig; itomp ( 1L, mpone ); ten = 10L; for ( i = 0; s[i] == ' ' || s[i] == '\n' || s[i] == '\t'; i++ ); /*skip white space */ sig = POS; if ( s[i] == '+' || s[i] == '-' ) /* sign */ sig = ( s[i++] == '+' ) ? POS : NEG; itomp ( 0L, a ); while ( s[i] >= '0' && s[i] <= '9' ) { diff = s[i] - '0'; linint ( a, ten, mpone, diff ); i++; } storesign ( a, sig ); if ( s[i] ) { fprintf ( stderr, "\nIllegal character in number: '%s'\n", s + i ); exit ( 1 ); } } /* end of atomp */
void mulint ( lrs_mp a, lrs_mp b, lrs_mp c ) /* multiply two integers a*b --> c */ /***Handbook of Algorithms and Data Structures, p239 ***/ { long nlength, i, j, la, lb; /*** b and c may coincide ***/ la = length ( a ); lb = length ( b ); nlength = la + lb - 2; if ( nlength > lrs_digits ) digits_overflow(); for ( i = 0; i < la - 2; i++ ) c[lb + i] = 0; for ( i = lb - 1; i > 0; i-- ) { for ( j = 2; j < la; j++ ) if ( ( c[i + j - 1] += b[i] * a[j] ) > MAXD - ( BASE - 1 ) * ( BASE - 1 ) - MAXD / BASE ) { c[i + j - 1] -= ( MAXD / BASE ) * BASE; c[i + j] += MAXD / BASE; } c[i] = b[i] * a[1]; } storelength ( c, nlength ); storesign ( c, sign ( a ) == sign ( b ) ? POS : NEG ); normalize ( c ); }
void normalize ( lrs_mp a ) { long cy, i, la; la = length ( a ); start: cy = 0; for ( i = 1; i < la; i++ ) { cy = ( a[i] += cy ) / BASE; a[i] -= cy * BASE; if ( a[i] < 0 ) { a[i] += BASE; cy--; } } while ( cy > 0 ) { a[i++] = cy % BASE; cy /= BASE; } if ( cy < 0 ) { a[la - 1] += cy * BASE; for ( i = 1; i < la; i++ ) a[i] = ( -a[i] ); storesign ( a, sign ( a ) == POS ? NEG : POS ); goto start; } while ( a[i - 1] == 0 && i > 2 ) i--; if ( i > lrs_record_digits ) { if ( ( lrs_record_digits = i ) > lrs_digits ) digits_overflow(); }; storelength ( a, i ); if ( i == 2 && a[1] == 0 ) storesign ( a, POS ); } /* end of normalize */
void itomp (long in, lrs_mp a) /* convert integer i to multiple precision with base BASE */ { long i; a[0] = 2; /* initialize to zero */ for (i = 1; i < lrs_digits; i++) a[i] = 0; if (in < 0) { storesign (a, NEG); in = in * (-1); } i = 0; while (in != 0) { i++; a[i] = in - BASE * (in / BASE); in = in / BASE; storelength (a, i + 1); } } /* end of itomp */
void divint ( lrs_mp a, lrs_mp b, lrs_mp c ) { /* c=a/b, a contains remainder on return */ long cy, la, lb, lc, d1, s, t, sig; long i, j, qh; /* figure out and save sign, do everything with positive numbers */ sig = sign ( a ) * sign ( b ); la = length ( a ); lb = length ( b ); lc = la - lb + 2; if ( la < lb ) { storelength ( c, TWO ); storesign ( c, POS ); c[1] = 0; normalize ( c ); return; } for ( i = 1; i < lc; i++ ) c[i] = 0; storelength ( c, lc ); storesign ( c, ( sign ( a ) == sign ( b ) ) ? POS : NEG ); /******************************/ /* division by a single word: */ /* do it directly */ /******************************/ if ( lb == 2 ) { cy = 0; t = b[1]; for ( i = la - 1; i > 0; i-- ) { cy = cy * BASE + a[i]; a[i] = 0; cy -= ( c[i] = cy / t ) * t; } a[1] = cy; storesign ( a, ( cy == 0 ) ? POS : sign ( a ) ); storelength ( a, TWO ); /* set sign of c to sig (**mod**) */ storesign ( c, sig ); normalize ( c ); return; } else { /* mp's are actually DIGITS+1 in length, so if length of a or b = */ /* DIGITS, there will still be room after normalization. */ /****************************************************/ /* Step D1 - normalize numbers so b > floor(BASE/2) */ d1 = BASE / ( b[lb - 1] + 1 ); if ( d1 > 1 ) { cy = 0; for ( i = 1; i < la; i++ ) { cy = ( a[i] = a[i] * d1 + cy ) / BASE; a[i] %= BASE; } a[i] = cy; cy = 0; for ( i = 1; i < lb; i++ ) { cy = ( b[i] = b[i] * d1 + cy ) / BASE; b[i] %= BASE; } b[i] = cy; } else { a[la] = 0; /* if la or lb = DIGITS this won't work */ b[lb] = 0; } /*********************************************/ /* Steps D2 & D7 - start and end of the loop */ for ( j = 0; j <= la - lb; j++ ) { /*************************************/ /* Step D3 - determine trial divisor */ if ( a[la - j] == b[lb - 1] ) qh = BASE - 1; else { s = ( a[la - j] * BASE + a[la - j - 1] ); qh = s / b[lb - 1]; while ( qh * b[lb - 2] > ( s - qh * b[lb - 1] ) * BASE + a[la - j - 2] ) qh--; } /*******************************************************/ /* Step D4 - divide through using qh as quotient digit */ cy = 0; for ( i = 1; i <= lb; i++ ) { s = qh * b[i] + cy; a[la - j - lb + i] -= s % BASE; cy = s / BASE; if ( a[la - j - lb + i] < 0 ) { a[la - j - lb + i] += BASE; cy++; } } /*****************************************************/ /* Step D6 - adjust previous step if qh is 1 too big */ if ( cy ) { qh--; cy = 0; for ( i = 1; i <= lb; i++ ) { /* add a back in */ a[la - j - lb + i] += b[i] + cy; cy = a[la - j - lb + i] / BASE; a[la - j - lb + i] %= BASE; } } /***********************************************************************/ /* Step D5 - write final value of qh. Saves calculating array indices */ /* to do it here instead of before D6 */ c[la - lb - j + 1] = qh; } /**********************************************************************/ /* Step D8 - unnormalize a and b to get correct remainder and divisor */ for ( i = lc; c[i - 1] == 0 && i > 2; i-- ); /* strip excess 0's from quotient */ storelength ( c, i ); if ( i == 2 && c[1] == 0 ) storesign ( c, POS ); cy = 0; for ( i = lb - 1; i >= 1; i-- ) { cy = ( a[i] += cy * BASE ) % d1; a[i] /= d1; } for ( i = la; a[i - 1] == 0 && i > 2; i-- ); /* strip excess 0's from quotient */ storelength ( a, i ); if ( i == 2 && a[1] == 0 ) storesign ( a, POS ); if ( cy ) fprintf ( lrs_ofp, "divide error" ); for ( i = lb - 1; i >= 1; i-- ) { cy = ( b[i] += cy * BASE ) % d1; b[i] /= d1; } } }
long lrs_getfirstbasis2 (lrs_dic ** D_p, lrs_dat * Q, lrs_dic * P2orig, lrs_mp_matrix * Lin, long no_output) /* gets first basis, FALSE if none */ /* P may get changed if lin. space Lin found */ /* no_output is TRUE supresses output headers */ { long i, j, k; /* assign local variables to structures */ lrs_mp_matrix A; long *B, *C, *Row, *Col; long *inequality; long *linearity; long hull = Q->hull; long m, d, lastdv, nlinearity, nredundcol; static long ocount=0; m = D->m; d = D->d; lastdv = Q->lastdv; nredundcol = 0L; /* will be set after getabasis */ nlinearity = Q->nlinearity; /* may be reset if new linearity read */ linearity = Q->linearity; A = D->A; B = D->B; C = D->C; Row = D->Row; Col = D->Col; inequality = Q->inequality; /* default is to look for starting cobasis using linearies first, then */ /* filling in from last rows of input as necessary */ /* linearity array is assumed sorted here */ /* note if restart/given start inequality indices already in place */ /* from nlinearity..d-1 */ for (i = 0; i < nlinearity; i++) /* put linearities first in the order */ inequality[i] = linearity[i]; k = 0; /* index for linearity array */ if (Q->givenstart) k = d; else k = nlinearity; for (i = m; i >= 1; i--) { j = 0; while (j < k && inequality[j] != i) j++; /* see if i is in inequality */ if (j == k) inequality[k++] = i; } if (Q->debug) { fprintf (lrs_ofp, "\n*Starting cobasis uses input row order"); for (i = 0; i < m; i++) fprintf (lrs_ofp, " %ld", inequality[i]); } if (!Q->maximize && !Q->minimize) for (j = 0; j <= d; j++) itomp (ZERO, A[0][j]); /* Now we pivot to standard form, and then find a primal feasible basis */ /* Note these steps MUST be done, even if restarting, in order to get */ /* the same index/inequality correspondance we had for the original prob. */ /* The inequality array is used to give the insertion order */ /* and is defaulted to the last d rows when givenstart=FALSE */ if (!getabasis2 (D, Q,P2orig, inequality)) return FALSE; if(Q->debug) { fprintf(lrs_ofp,"\nafter getabasis2"); printA(D, Q); } nredundcol = Q->nredundcol; lastdv = Q->lastdv; d = D->d; /********************************************************************/ /* now we start printing the output file unless no output requested */ /********************************************************************/ if (!no_output || Q->debug) { fprintf (lrs_ofp, "\nV-representation"); /* Print linearity space */ /* Don't print linearity if first column zero in hull computation */ k = 0; if (nredundcol > k) { fprintf (lrs_ofp, "\nlinearity %ld ", nredundcol - k); /*adjust nredundcol for homog. */ for (i = 1; i <= nredundcol - k; i++) fprintf (lrs_ofp, " %ld", i); } /* end print of linearity space */ fprintf (lrs_ofp, "\nbegin"); fprintf (lrs_ofp, "\n***** %ld rational", Q->n); } /* end of if !no_output ....... */ /* Reset up the inequality array to remember which index is which input inequality */ /* inequality[B[i]-lastdv] is row number of the inequality with index B[i] */ /* inequality[C[i]-lastdv] is row number of the inequality with index C[i] */ for (i = 1; i <= m; i++) inequality[i] = i; if (nlinearity > 0) /* some cobasic indices will be removed */ { for (i = 0; i < nlinearity; i++) /* remove input linearity indices */ inequality[linearity[i]] = 0; k = 1; /* counter for linearities */ for (i = 1; i <= m - nlinearity; i++) { while (k <= m && inequality[k] == 0) k++; /* skip zeroes in corr. to linearity */ inequality[i] = inequality[k++]; } } /* end if linearity */ if (Q->debug) { fprintf (lrs_ofp, "\ninequality array initialization:"); for (i = 1; i <= m - nlinearity; i++) fprintf (lrs_ofp, " %ld", inequality[i]); } if (nredundcol > 0) { *Lin = lrs_alloc_mp_matrix (nredundcol, Q->n); for (i = 0; i < nredundcol; i++) { if (!(Q->homogeneous && Q->hull && i == 0)) /* skip redund col 1 for homog. hull */ { lrs_getray (D, Q, Col[0], D->C[0] + i - hull, (*Lin)[i]); /* adjust index for deletions */ } if (!removecobasicindex (D, Q, 0L)) return FALSE; } } /* end if nredundcol > 0 */ if (Q->verbose) { fprintf (lrs_ofp, "\nNumber of pivots for starting dictionary: %ld",Q->count[3]); ocount=Q->count[3]; } /* Do dual pivots to get primal feasibility */ if (!primalfeasible (D, Q)) { if ( Q->verbose ) { fprintf (lrs_ofp, "\nNumber of pivots for feasible solution: %ld",Q->count[3]); fprintf (lrs_ofp, " - No feasible solution"); ocount=Q->count[3]; } return FALSE; } if (Q->verbose) { fprintf (lrs_ofp, "\nNumber of pivots for feasible solution: %ld",Q->count[3]); ocount=Q->count[3]; } /* Now solve LP if objective function was given */ if (Q->maximize || Q->minimize) { Q->unbounded = !lrs_solvelp (D, Q, Q->maximize); /* check to see if objective is dual degenerate */ j = 1; while (j <= d && !zero (A[0][j])) j++; if (j <= d) Q->dualdeg = TRUE; } else /* re-initialize cost row to -det */ { for (j = 1; j <= d; j++) { copy (A[0][j], D->det); storesign (A[0][j], NEG); } itomp (ZERO, A[0][0]); /* zero optimum objective value */ } /* reindex basis to 0..m if necessary */ /* we use the fact that cobases are sorted by index value */ if (Q->debug) printA (D, Q); while (C[0] <= m) { i = C[0]; j = inequality[B[i] - lastdv]; inequality[B[i] - lastdv] = inequality[C[0] - lastdv]; inequality[C[0] - lastdv] = j; C[0] = B[i]; B[i] = i; reorder1 (C, Col, ZERO, d); } if (Q->debug) { fprintf (lrs_ofp, "\n*Inequality numbers for indices %ld .. %ld : ", lastdv + 1, m + d); for (i = 1; i <= m - nlinearity; i++) fprintf (lrs_ofp, " %ld ", inequality[i]); printA (D, Q); } if (Q->restart) { if (Q->debug) fprintf (lrs_ofp, "\nPivoting to restart co-basis"); if (!restartpivots (D, Q)) return FALSE; D->lexflag = lexmin (D, Q, ZERO); /* see if lexmin basis */ if (Q->debug) printA (D, Q); } /* Check to see if necessary to resize */ if (Q->inputd > D->d) *D_p = resize (D, Q); return TRUE; }