--- a +++ b/feasible_joint_stiffness/lrslib-062/lrsmp.c @@ -0,0 +1,1123 @@ +/* lrsmp.c library code for lrs extended precision arithmetic */ +/* Version 4.0c, August 26, 2009 */ +/* minor change to check result of fscanf */ +/* Copyright: David Avis 1999, avis@cs.mcgill.ca */ + +/* This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA. + */ + +#ifdef PLRS +#include <sstream> +#include <iostream> +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "lrsmp.h" + +long lrs_digits; /* max permitted no. of digits */ +long lrs_record_digits; /* this is the biggest acheived so far. */ + + +/******************************************************************/ +/* digit overflow is caught by digits_overflow at the end of this */ +/* file, make sure it is either user supplied or uncomment */ +/* the define below */ +/******************************************************************/ + +#define digits_overflow() lrs_default_digits_overflow() + +/*********************************************************/ +/* Initialization and allocation procedures - must use! */ +/******************************************************* */ + +long +lrs_mp_init (long dec_digits, FILE * fpin, FILE * fpout) +/* max number of decimal digits for the computation */ +{ +/* global variables lrs_ifp and lrs_ofp are file pointers for input and output */ + + + lrs_ifp = fpin; + lrs_ofp = fpout; + + lrs_record_digits = 0; + if (dec_digits <= 0) + dec_digits = DEFAULT_DIGITS; + + lrs_digits = DEC2DIG (dec_digits); /* max permitted no. of digits */ + + if (lrs_digits > MAX_DIGITS) + { + #ifdef PLRS + cout<<"Digits must be at most "<<DIG2DEC (MAX_DIGITS)<<endl; + cout<<"Change MAX_DIGITS and recompile"<<endl; + exit(1); + #else + fprintf (lrs_ofp, "\nDigits must be at most %ld\nChange MAX_DIGITS and recompile\n", DIG2DEC (MAX_DIGITS)); + #endif + lrs_digits = MAX_DIGITS; + return FALSE; + } + + return TRUE; + +} + +lrs_mp_t +lrs_alloc_mp_t () + /* dynamic allocation of lrs_mp number */ +{ + lrs_mp_t p; + p=(long *)calloc (lrs_digits+1, sizeof (long)); + return p; +} + +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++) + p[i] = (long int *)CALLOC (1, sizeof (lrs_mp)); + + 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++) + free (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; + long *araw; + int mp_width, row_width; + int i, j; + + mp_width = lrs_digits + 1; + row_width = (n + 1) * mp_width; + + araw = (long int*)calloc ((m + 1) * row_width, sizeof (long)); + a = (lrs_mp_matrix) calloc ((m + 1), sizeof (lrs_mp_vector)); + + for (i = 0; i < m + 1; i++) + { + a[i] = (long int **)calloc ((n + 1), sizeof (lrs_mp *)); + + for (j = 0; j < n + 1; j++) + a[i][j] = (araw + i * row_width + j * mp_width); + } + return a; +} + +void +lrs_clear_mp_matrix (lrs_mp_matrix p, long m, long n) +/* free space allocated to lrs_mp_matrix p */ +{ + long i; + +/* p[0][0] is araw, the actual matrix storage address */ + + free(p[0][0]); + + for (i = 0; i < m + 1; i++) + free (p[i]); + free(p); +} + +/*********************************************************/ +/* Core library functions - depend on mp implementation */ +/******************************************************* */ + +void copy (lrs_mp a, lrs_mp b) /* assigns a=b */ +{ + long i; + for (i = 0; i <= length (b); i++) + a[i] = b[i]; +} + +/********************************************************/ +/* Divide two multiple precision integers (c=a/b). */ +/* a is destroyed and contains the remainder on return. */ +/* From Knuth Vol.2 SemiNumerical Algorithms */ +/* coded by J. Quinn */ +/********************************************************/ +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 (stdout, "divide error"); + exit(1); + } + for (i = lb - 1; i >= 1; i--) + { + cy = (b[i] += cy * BASE) % d1; + b[i] /= d1; + } + } +} +/* end of divint */ + +void +gcd (lrs_mp u, lrs_mp v) /*returns u=gcd(u,v) destroying v */ + /*Euclid's algorithm. Knuth, II, p.320 + modified to avoid copies r=u,u=v,v=r + Switches to single precision when possible for greater speed */ +{ + lrs_mp r; + unsigned long ul, vl; + long i; + static unsigned long maxspval = MAXD; /* Max value for the last digit to guarantee */ + /* fitting into a single long integer. */ + + static long maxsplen; /* Maximum digits for a number that will fit */ + /* into a single long integer. */ + + static long firstime = TRUE; + + if (firstime) /* initialize constants */ + { + for (maxsplen = 2; maxspval >= BASE; maxsplen++) + maxspval /= BASE; + firstime = FALSE; + } + if (mp_greater (v, u)) + goto bigv; +bigu: + if (zero (v)) + return; + if ((i = length (u)) < maxsplen || (i == maxsplen && u[maxsplen - 1] < maxspval)) + goto quickfinish; + divint (u, v, r); + normalize (u); + +bigv: + if (zero (u)) + { + copy (u, v); + return; + } + if ((i = length (v)) < maxsplen || (i == maxsplen && v[maxsplen - 1] < maxspval)) + goto quickfinish; + divint (v, u, r); + normalize (v); + goto bigu; + /* Base 10000 only at the moment */ + /* when u and v are small enough, transfer to single precision integers */ + /* and finish with euclid's algorithm, then transfer back to lrs_mp */ +quickfinish: + ul = vl = 0; + for (i = length (u) - 1; i > 0; i--) + ul = BASE * ul + u[i]; + for (i = length (v) - 1; i > 0; i--) + vl = BASE * vl + v[i]; + if (ul > vl) + goto qv; +qu: + if (!vl) + { + for (i = 1; ul; i++) + { + u[i] = ul % BASE; + ul = ul / BASE; + } + storelength (u, i); + return; + } + ul %= vl; +qv: + if (!ul) + { + for (i = 1; vl; i++) + { + u[i] = vl % BASE; + vl = vl / BASE; + } + storelength (u, i); + return; + } + vl %= ul; + goto qu; +} + +long +compare (lrs_mp a, lrs_mp b) /* a ? b and returns -1,0,1 for <,=,> */ +{ + long i; + + if (a[0] > b[0]) + return 1L; + if (a[0] < b[0]) + return -1L; + + for (i = length (a) - 1; i >= 1; i--) + { + if (a[i] < b[i]) + { + if (sign (a) == POS) + return -1L; + else + return 1L; + } + if (a[i] > b[i]) + { + if (sign (a) == NEG) + return -1L; + else + return 1L; + } + } + return 0L; +} + + +long mp_greater (lrs_mp a, lrs_mp b) /* tests if a > b and returns (TRUE=POS) */ +{ + long i; + + if (a[0] > b[0]) + return (TRUE); + if (a[0] < b[0]) + return (FALSE); + + for (i = length (a) - 1; i >= 1; i--) + { + if (a[i] < b[i]) + { + if (sign (a) == POS) + return (0); + else + return (1); + } + if (a[i] > b[i]) + { + if (sign (a) == NEG) + return (0); + else + return (1); + } + } + return (0); +} +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 +linint (lrs_mp a, long ka, lrs_mp b, long kb) /*compute a*ka+b*kb --> a */ +/***Handbook of Algorithms and Data Structures P.239 ***/ +{ + long i, la, lb; + la = length (a); + lb = length (b); + for (i = 1; i < la; i++) + a[i] *= ka; + if (sign (a) != sign (b)) + kb = (-kb); + if (lb > la) + { + storelength (a, lb); + for (i = la; i < lb; i++) + a[i] = 0; + } + for (i = 1; i < lb; i++) + a[i] += kb * b[i]; + normalize (a); +} +/***end of linint***/ + + +void +mptodouble (lrs_mp a, double *x) /* convert lrs_mp to double */ +{ + long i, la; + double y = 1.0; + + (*x) = 0; + la = length (a); + for (i = 1; i < la; i++) + { + (*x) = (*x) + y * a[i]; + y = y * BASE; + } + if (negative (a)) + (*x)= -(*x); +} + +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); +} +/***end of mulint ***/ + +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 */ + +long +length (lrs_mp a) +{ +/* formerly a macro but conflicts with string length */ + return ((a[0] > 0) ? a[0] : -a[0]); +} + +long +mptoi (lrs_mp a) /* convert lrs_mp to long integer */ +{ + long len = length (a); + if (len == 2) + return sign (a) * a[1]; + if (len == 3) + return sign (a) * (a[1] + BASE * a[2]); + notimpl ("mp to large for conversion to long"); + return 0; /* never executed */ +} + + +#ifdef PLRS +string prat (char name[], lrs_mp Nin, lrs_mp Din) /*reduce and print Nin/Din */ +{ + + + lrs_mp Nt, Dt; + long i; + //create stream to collect output + stringstream ss; + string str; + + ss<<name; + + /* reduce fraction */ + copy (Nt, Nin); + copy (Dt, Din); + reduce (Nt, Dt); + /* pipe output to stream */ + if (sign (Nin) * sign (Din) == NEG) + ss<<"-"; + else + ss<<" "; + + ss<<Nt[length(Nt) -1]; + + for (i = length (Nt) - 2; i >= 1; i--) + ss<<Nt[i]; + if (!(Dt[0] == 2 && Dt[1] == 1)){ + /* rational */ + ss<<"/"; + ss<<Dt[length(Dt) -1]; + for (i = length (Dt) - 2; i >= 1; i--) + ss<<Dt[i]; + } + ss<<" "; + //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 a) /*print the long precision integer a */ +{ + + long i; + //create stream to collect output + stringstream ss; + string str; + + ss<<name; + if (sign (a) == NEG) + ss<<"-"; + else + ss<<" "; + + ss<<a[length(a) -1]; + for (i = length (a) - 2; i >= 1; i--) + ss<<a[i]; + + ss<<" "; + + //pipe stream to single string + str = ss.str(); + return str; +} +#else +void prat (char name[], lrs_mp Nin, lrs_mp Din) /*reduce and print Nin/Din */ +{ + lrs_mp Nt, Dt; + long i; + fprintf (lrs_ofp, "%s", name); + /* reduce fraction */ + copy (Nt, Nin); + copy (Dt, Din); + reduce (Nt, Dt); + /* print out */ + if (sign (Nin) * sign (Din) == NEG) + fprintf (lrs_ofp, "-"); + else + fprintf (lrs_ofp, " "); + fprintf (lrs_ofp, "%lu", Nt[length (Nt) - 1]); + for (i = length (Nt) - 2; i >= 1; i--) + fprintf (lrs_ofp, FORMAT, Nt[i]); + if (!(Dt[0] == 2 && Dt[1] == 1)) /* rational */ + { + fprintf (lrs_ofp, "/"); + fprintf (lrs_ofp, "%lu", Dt[length (Dt) - 1]); + for (i = length (Dt) - 2; i >= 1; i--) + fprintf (lrs_ofp, FORMAT, Dt[i]); + } + fprintf (lrs_ofp, " "); + +} + +void pmp (char name[], lrs_mp a) /*print the long precision integer a */ +{ + + long i; + fprintf (lrs_ofp, "%s", name); + if (sign (a) == NEG) + fprintf (lrs_ofp, "-"); + else + fprintf (lrs_ofp, " "); + fprintf (lrs_ofp, "%lu", a[length (a) - 1]); + for (i = length (a) - 2; i >= 1; i--) + fprintf (lrs_ofp, FORMAT, a[i]); + fprintf (lrs_ofp, " "); +} +#endif + + + +long +readrat (lrs_mp Na, lrs_mp Da) + /* 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 */ +{ + 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); +} + + + +void +addint (lrs_mp a, lrs_mp b, lrs_mp c) /* compute c=a+b */ +{ + copy (c, a); + linint (c, 1, b, 1); +} + +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 +subint (lrs_mp a, lrs_mp b, lrs_mp c) /* compute c=a-b */ + +{ + copy (c, a); + linint (a, 1, b, -1); +} + +void +decint (lrs_mp a, lrs_mp b) /* compute a=a-b */ + +{ + linint (a, 1, b, -1); +} + + +long +myrandom (long num, long nrange) +/* return a random number in range 0..nrange-1 */ + +{ + long i; + i = (num * 401 + 673) % nrange; + return (i); +} + + +long +atos (char s[]) /* convert s to integer */ +{ + long i, j; + j = 0; + for (i = 0; s[i] >= '0' && s[i] <= '9'; ++i) + j = 10 * j + s[i] - '0'; + return (j); +} + +void +stringcpy (char *s, char *t) /*copy t to s pointer version */ +{ + while (((*s++) = (*t++)) != '\0'); +} + + +void +rattodouble (lrs_mp a, lrs_mp b, double *x) /* convert lrs_mp rational to double */ + +{ + double y; + mptodouble (a, &y); + mptodouble (b, x); + *x = y / (*x); +} + + +void +atoaa (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 +lcm (lrs_mp a, lrs_mp b) +/* a = least common multiple of a, b; b is preserved */ +{ + lrs_mp u, v; + copy (u, a); + copy (v, b); + gcd (u, v); + exactdivint (a, u, v); /* v=a/u no remainder*/ + mulint (v, b, a); +} /* end of lcm */ + +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 +reduceint (lrs_mp Na, lrs_mp Da) /* divide Na by Da and return */ +{ + lrs_mp Temp; + copy (Temp, Na); + exactdivint (Temp, Da, Na); +} + +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); +} + + +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 */ +{ + lrs_mp mc, md; + mulint (Na, Nb, mc); + mulint (Nc, Nd, md); + linint (mc, ONE, md, -ONE); + if (positive (mc)) + return (1); + if (negative (mc)) + return (-1); + return (0); +} + + +void +notimpl (char s[]) +{ + fflush (stdout); + fprintf (stderr, "\nAbnormal Termination %s\n", s); + exit (1); +} + +void +getfactorial (lrs_mp factorial, long k) /* compute k factorial in lrs_mp */ +{ + lrs_mp temp; + long i; + itomp (ONE, factorial); + for (i = 2; i <= k; i++) + { + itomp (i, temp); + mulint (temp, factorial, factorial); + } +} /* end of getfactorial */ +/***************************************************************/ +/* Package of routines for rational arithmetic */ +/***************************************************************/ + +void +scalerat (lrs_mp Na, lrs_mp Da, long ka) /* scales rational by ka */ +{ + lrs_mp Nt; + copy (Nt, Na); + itomp (ZERO, Na); + linint (Na, ZERO, Nt, ka); + reduce (Na, Da); +} + +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 c; + mulint (Na, Db, Nc); + mulint (Da, Nb, c); + linint (Nc, ka, c, kb); /* Nc = (ka*Na*Db)+(kb*Da*Nb) */ + mulint (Da, Db, Dc); /* Dc = Da*Db */ + reduce (Nc, Dc); +} + +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 reduces answer by gcd(Nc,Dc) */ +{ + 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 reduces by gcd(Nc,Dc) */ +{ + mulint (Na, Nb, Nc); + mulint (Da, Db, Dc); + reduce (Nc, Dc); +} + +/* End package of routines for rational arithmetic */ + +/***************************************************************/ +/* */ +/* End of package for multiple precision arithmetic */ +/* */ +/***************************************************************/ + + +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; +} + +void +lrs_getdigits (long *a, long *b) +{ +/* send digit information to user */ + *a = DIG2DEC (lrs_digits); + *b = DIG2DEC (lrs_record_digits); + return; +} + +void +lrs_default_digits_overflow () +{ + fprintf (stdout, "\nOverflow at digits=%ld", DIG2DEC (lrs_digits)); + fprintf (stdout, "\nInitialize lrs_mp_init with n > %ldL\n", DIG2DEC (lrs_digits)); + + exit (1); +} + +#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 + + +/* end of lrsmp.c */