--- a +++ b/feasible_joint_stiffness/lrslib-062/lrsgmp.c @@ -0,0 +1,589 @@ +/* lrsgmp.c library code for lrs extended precision arithmetic */ +/* Version 4.1, April 3, 2001 */ +/* Copyright: David Avis 2001, avis@cs.mcgill.ca */ + +/* For gmp package */ +/* derived from lrslong.c and lrsmp.c */ + +#ifdef PLRS +#include <sstream> +#include <iostream> +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "lrsgmp.h" + +long lrs_digits; /* max permitted no. of digits */ +long lrs_record_digits; /* this is the biggest acheived so far. */ + + +#define MAXINPUT 1000 /*max length of any input rational */ + + +void +lcm (lrs_mp a, lrs_mp b) /* a = least common multiple of a, b; b is preserved */ +{ + lrs_mp temp1,temp2; + lrs_alloc_mp(temp1); lrs_alloc_mp(temp2); + copy (temp1, a); + copy (temp2, b); + gcd (temp1,temp2); + exactdivint (a, temp1, temp2); /* temp2=a/temp1 there is no remainder */ + mulint (temp2, b, a); + lrs_clear_mp(temp1); + lrs_clear_mp(temp2); + +} /* end of lcm */ + + +/***************************************************************/ +/* */ +/* Package of routines for rational arithmetic */ +/* (Built on top of package for multiprecision arithmetic */ +/* */ +/***************************************************************/ + +void +reduce (lrs_mp Na, lrs_mp Da) /* reduces Na/Da by gcd(Na,Da) */ +{ + lrs_mp Nb, Db, Nc, Dc; + lrs_alloc_mp(Nb); lrs_alloc_mp(Db); + lrs_alloc_mp(Nc); lrs_alloc_mp(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); + lrs_clear_mp(Nb); lrs_clear_mp(Db); + lrs_clear_mp(Nc); lrs_clear_mp(Dc); +} + +void +reduceint (lrs_mp Na, lrs_mp Da) /* divide Na by Da and return */ +{ + lrs_mp temp1; + lrs_alloc_mp(temp1); + copy (temp1, Na); + exactdivint (temp1, Da, Na); + lrs_clear_mp(temp1); +} + + +long +comprod (lrs_mp Na, lrs_mp Nb, lrs_mp Nc, lrs_mp Nd) + /* +1 if Na*Nb > Nc*Nd */ + /* -1 if Na*Nb < Nc*Nd */ + /* 0 if Na*Nb = Nc*Nd */ +{ + + long i; + lrs_mp temp1,temp2; + lrs_alloc_mp(temp1); lrs_alloc_mp(temp2); + mulint (Na, Nb, temp1); + mulint (Nc, Nd, temp2); + i=mpz_cmp(temp1,temp2); + lrs_clear_mp(temp1); + lrs_clear_mp(temp2); + if (i > 0) + return (ONE); + else if (i < 0) + return (-ONE); + else + return (ZERO); +} + +void +linrat (lrs_mp Na, lrs_mp Da, long ka, lrs_mp Nb, lrs_mp Db, long kb, lrs_mp Nc, lrs_mp Dc) + + /* computes Nc/Dc = ka*Na/Da +kb* Nb/Db and reduces answer by gcd(Nc,Dc) */ +{ + lrs_mp temp1; + lrs_alloc_mp(temp1); + mulint (Na, Db, Nc); + mulint (Da, Nb, temp1); + linint (Nc, ka, temp1, kb); /* Nc = (ka*Na*Db)+(kb*Da*Nb) */ + mulint (Da, Db, Dc); /* Dc = Da*Db */ + reduce (Nc, Dc); + lrs_clear_mp(temp1); +} + + +void +divrat (lrs_mp Na, lrs_mp Da, lrs_mp Nb, lrs_mp Db, lrs_mp Nc, lrs_mp Dc) + /* computes Nc/Dc = (Na/Da) /( Nb/Db ) and reduce */ +{ + mulint (Na, Db, Nc); + mulint (Da, Nb, Dc); + reduce (Nc, Dc); +} + + +void +mulrat (lrs_mp Na, lrs_mp Da, lrs_mp Nb, lrs_mp Db, lrs_mp Nc, lrs_mp Dc) + /* computes Nc/Dc=(Na/Da)*(Nb/Db) and reduce */ + +{ + mulint (Na, Nb, Nc); + mulint (Da, Db, Dc); + reduce (Nc, Dc); +} + +/***************************************************************/ +/* */ +/* Conversion and I/O functions */ +/* */ +/***************************************************************/ + +void +atomp (const char *s, lrs_mp a) /*convert string to lrs_mp integer */ + /* based on atoi KR p.58 */ +{ + long diff, ten, i, sig; + lrs_mp mpone; + lrs_alloc_mp (mpone); + itomp (ONE, 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); + } + + lrs_clear_mp (mpone); +} /* end of atomp */ + +void +atoaa (const char *in, char *num, char *den) + /* convert rational string in to num/den strings */ +{ + long i, j; + for (i = 0; in[i] != '\0' && in[i] != '/'; i++) + num[i] = in[i]; + num[i] = '\0'; + den[0] = '\0'; + if (in[i] == '/') + { + for (j = 0; in[j + i + 1] != '\0'; j++) + den[j] = in[i + j + 1]; + den[j] = '\0'; + } +} /* end of atoaa */ + + +void +rattodouble (lrs_mp a, lrs_mp b, double *x) /* convert lrs_mp rati + onal to double */ + +{ + double y; + y=mpz_get_d (a); + (*x)=mpz_get_d (b); + (*x) = y / (*x); +} +#ifdef PLRS + +/* read a rational or integer and convert to lrs_mp with base BASE */ +/* returns true if denominator is not one */ +/* returns 999 if premature end of file */ +long plrs_readrat (lrs_mp Na, lrs_mp Da, const char* rat) +{ + char in[MAXINPUT], num[MAXINPUT], den[MAXINPUT]; + strcpy(in, rat); + atoaa (in, num, den); /*convert rational to num/dem strings */ + atomp (num, Na); + if (den[0] == '\0') + { + itomp (1L, Da); + return (FALSE); + } + atomp (den, Da); + return (TRUE); +} + +#endif + +long +readrat (lrs_mp Na, lrs_mp Da) /* read a rational or integer and convert to lrs_mp */ + /* returns true if denominator is not one */ +{ + char in[MAXINPUT], num[MAXINPUT], den[MAXINPUT]; + if(fscanf (lrs_ifp, "%s", in)==EOF) + { + fprintf (lrs_ofp, "\nInvalid input: check you have entered enough data!\n"); + exit(1); + } + + if(!strcmp(in,"end")) /*premature end of input file */ + { + return (999L); + } + + atoaa (in, num, den); /*convert rational to num/dem strings */ + atomp (num, Na); + if (den[0] == '\0') + { + itomp (1L, Da); + return (FALSE); + } + atomp (den, Da); + return (TRUE); +} + +#ifdef PLRS +string prat (char name[], lrs_mp Nin, lrs_mp Din) /*reduce and print Nin/Din */ +{ + + //create stream to collect output + stringstream ss; + string str; + char * buff; + lrs_mp temp1, temp2; + lrs_alloc_mp(temp1); + lrs_alloc_mp(temp2); + + + copy (temp1, Nin); + copy (temp2, Din); + reduce (temp1, temp2); + ss<<name; + if (sign (temp1) != NEG) + ss<<" "; + buff = mpz_get_str(NULL, 10, temp1); + ss<<buff; + free(buff); + if (!one(temp2)){ + buff = mpz_get_str(NULL, 10, temp2); + ss<<"/"<<buff; + free(buff); + } + ss<<" "; + lrs_clear_mp(temp1); + lrs_clear_mp(temp2); + //pipe stream to single string + str = ss.str(); + return str; +} + +char *cprat (char name[], lrs_mp Nin, lrs_mp Din) +{ + char *ret; + unsigned long len; + int i, offset=0; + string s; + const char *cstr; + + s = prat(name,Nin,Din); + cstr = s.c_str(); + len = strlen(cstr); + ret = (char *)malloc(sizeof(char)*(len+1)); + + for (i=0; i+offset<len+1;) + { + if (cstr[i+offset]!=' ') + { + ret[i] = cstr[i+offset]; + i++; + } + else /* skip whitespace */ + offset++; + } + + return ret; +} + +string pmp (char name[], lrs_mp Nt) /*print the long precision integer a */ +{ + + //create stream to collect output + stringstream ss; + string str; + char * buff; + ss<<name; + + if (sign (Nt) != NEG) + ss<<" "; + buff = mpz_get_str(NULL,10,Nt); + ss<<buff<<" "; + free(buff); + + //pipe stream to single string + str = ss.str(); + return str; +} +#else + +void +pmp (char name[], lrs_mp Nt) +{ + fprintf (lrs_ofp, "%s", name); + if (sign (Nt) != NEG) + fprintf (lrs_ofp, " "); + mpz_out_str (lrs_ofp,10,Nt); + fprintf (lrs_ofp, " "); +} + +void +prat (char name[], lrs_mp Nin, lrs_mp Din) + /*print the long precision rational Nt/Dt */ +{ + lrs_mp temp1, temp2; + lrs_alloc_mp(temp1); + lrs_alloc_mp(temp2); + copy (temp1, Nin); + copy (temp2, Din); + reduce (temp1, temp2); + fprintf (lrs_ofp, "%s", name); + if (sign (temp1) != NEG) + fprintf (lrs_ofp, " "); + mpz_out_str (lrs_ofp,10,temp1); + if ( !one(temp2)) + { + fprintf (lrs_ofp, "/"); + mpz_out_str (lrs_ofp,10,temp2); + } + fprintf (lrs_ofp, " "); + lrs_clear_mp(temp1); + lrs_clear_mp(temp2); +} /* prat */ +#endif + + +void +readmp (lrs_mp a) /* read an integer and convert to lrs_mp */ +{ + long in; + if(fscanf (lrs_ifp, "%ld", &in)==EOF) + { + fprintf (lrs_ofp, "\nInvalid integer input"); + exit(1); + + } + itomp (in, a); +} + +/***************************************************************/ +/* */ +/* Memory allocation functions */ +/* */ +/***************************************************************/ + +lrs_mp_vector +lrs_alloc_mp_vector (long n) + /* allocate lrs_mp_vector for n+1 lrs_mp numbers */ +{ + lrs_mp_vector p; + long i; + + p = (lrs_mp_vector) CALLOC ((n + 1), sizeof (lrs_mp )); + for (i = 0; i <= n; i++) + lrs_alloc_mp(p[i]); + + return p; +} + +void +lrs_clear_mp_vector (lrs_mp_vector p, long n) +/* free space allocated to p */ +{ + long i; + for (i=0; i<=n; i++) + lrs_clear_mp (p[i] ); + free (p); +} + +lrs_mp_matrix +lrs_alloc_mp_matrix (long m, long n) +/* allocate lrs_mp_matrix for m+1 x n+1 lrs_mp numbers */ +{ + lrs_mp_matrix a; + int i, j; + + + a = (lrs_mp_matrix) calloc ((m + 1), sizeof (lrs_mp_vector)); + + for (i = 0; i < m + 1; i++) + { + a[i] = (lrs_mp_vector) calloc ((n + 1), sizeof (lrs_mp )); + + for (j = 0; j < n + 1; j++) + lrs_alloc_mp (a[i][j]); + } + return a; +} + +void +lrs_clear_mp_matrix (lrs_mp_matrix p, long m, long n) +/* free space allocated to p */ +{ + long i,j; + for (i = 0; i < m + 1; i++) + { + for (j = 0; j < n + 1; j++) + lrs_clear_mp (p[i][j]); + + free (p[i]); + + } + + free (p); +} + +void +lrs_getdigits (long *a, long *b) +{ +/* send digit information to user */ + *a = ZERO; + *b = ZERO; + return; +} + +void * +xcalloc (long n, long s, long l, char *f) +{ + void *tmp; + + tmp = calloc (n, s); + if (tmp == 0) + { + char buf[200]; + + sprintf (buf, "\n\nFatal error on line %ld of %s", l, f); + perror (buf); + exit (1); + } + return tmp; +} + +long +lrs_mp_init (long dec_digits, FILE * fpin, FILE * fpout) +/* max number of decimal digits for the computation */ +/* long int version */ +{ + lrs_ifp = fpin; + lrs_ofp = fpout; + lrs_record_digits = 0; /* not used for gmp arithmetic */ + lrs_digits = 0; /* not used for gmp arithmetic */ + +#ifndef PLRS + #ifndef LRS_QUIET + printf(" gmp v.%d.%d",__GNU_MP_VERSION,__GNU_MP_VERSION_MINOR); + #endif +#endif + return TRUE; +} + + +void +notimpl (char s[]) +{ + fflush (stdout); + fprintf (stderr, "\nAbnormal Termination %s\n", s); + exit (1); +} + +/***************************************************************/ +/* */ +/* Misc. functions */ +/* */ +/***************************************************************/ + +/* find largest gcd of p[0]..p[n-1] and divide through */ +void +reducearray (lrs_mp_vector p, long n) +{ + lrs_mp divisor, temp1; + long i = 0L; + + while ((i < n) && zero (p[i])) + i++; + if (i == n) + return; + + lrs_alloc_mp (divisor); + lrs_alloc_mp (temp1); + + copy (divisor, p[i]); + storesign (divisor, POS); + i++; + + while (i < n) + { + if (!zero (p[i])) + { + copy (temp1, p[i]); + storesign (temp1, POS); + gcd (divisor, temp1); + } + i++; + } + + for (i = 0; i < n; i++) + if (!zero (p[i])) + reduceint (p[i], divisor); + lrs_clear_mp (divisor); + lrs_clear_mp (temp1); +} + /* end of reducearray */ + + +long +myrandom (long num, long nrange) +/* return a random number in range 0..nrange-1 */ + +{ + long i; + i = (num * 401 + 673) % nrange; + return (i); +} + +void +stringcpy (char *s, char *t) /*copy t to s pointer version */ +{ + while (((*s++) = (*t++)) != '\0'); +} + +void +linint(lrs_mp a, long ka, lrs_mp b, long kb) +/* a=a*ka+b*kb, b unchanged */ +{ + lrs_mp temp1; + lrs_alloc_mp (temp1); +mpz_mul_ui (a,a,labs(ka)); +if (ka < 0) + mpz_neg(a,a); +mpz_mul_ui (temp1,b,labs(kb)); +if (kb < 0) + mpz_neg(temp1,temp1); +mpz_add(a,a,temp1); + lrs_clear_mp (temp1); + +} + + +void +storesign(lrs_mp a, long sa) +{ + if ( (sa)*sign(a) < 0 ) + mpz_neg(a,a); +} +