3 /***********************************************************************
4 * This code is part of GLPK (GNU Linear Programming Kit).
6 * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
7 * 2009, 2010 Andrew Makhorin, Department for Applied Informatics,
8 * Moscow Aviation Institute, Moscow, Russia. All rights reserved.
9 * E-mail: <mao@gnu.org>.
11 * GLPK is free software: you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
16 * GLPK is distributed in the hope that it will be useful, but WITHOUT
17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
19 * License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with GLPK. If not, see <http://www.gnu.org/licenses/>.
23 ***********************************************************************/
30 #ifdef HAVE_GMP /* use GNU MP bignum library */
32 int gmp_pool_count(void) { return 0; }
34 void gmp_free_mem(void) { return; }
36 #else /* use GLPK bignum module */
38 static DMP *gmp_pool = NULL;
39 static int gmp_size = 0;
40 static unsigned short *gmp_work = NULL;
42 void *gmp_get_atom(int size)
43 { if (gmp_pool == NULL)
44 gmp_pool = dmp_create_pool();
45 return dmp_get_atom(gmp_pool, size);
48 void gmp_free_atom(void *ptr, int size)
49 { xassert(gmp_pool != NULL);
50 dmp_free_atom(gmp_pool, ptr, size);
54 int gmp_pool_count(void)
55 { if (gmp_pool == NULL)
58 return dmp_in_use(gmp_pool).lo;
61 unsigned short *gmp_get_work(int size)
65 { xassert(gmp_work == NULL);
69 { xassert(gmp_work != NULL);
72 while (gmp_size < size) gmp_size += gmp_size;
73 gmp_work = xcalloc(gmp_size, sizeof(unsigned short));
78 void gmp_free_mem(void)
79 { if (gmp_pool != NULL) dmp_delete_pool(gmp_pool);
80 if (gmp_work != NULL) xfree(gmp_work);
87 /*====================================================================*/
90 { /* initialize x, and set its value to 0 */
92 x = gmp_get_atom(sizeof(struct mpz));
98 void mpz_clear(mpz_t x)
99 { /* free the space occupied by x */
101 xassert(x->ptr == NULL);
102 /* free the number descriptor */
103 gmp_free_atom(x, sizeof(struct mpz));
107 void mpz_set(mpz_t z, mpz_t x)
108 { /* set the value of z from x */
109 struct mpz_seg *e, *ee, *es;
113 xassert(z->ptr == NULL);
114 for (e = x->ptr, es = NULL; e != NULL; e = e->next)
115 { ee = gmp_get_atom(sizeof(struct mpz_seg));
116 memcpy(ee->d, e->d, 12);
128 void mpz_set_si(mpz_t x, int val)
129 { /* set the value of x to val */
131 /* free existing segments, if any */
132 while (x->ptr != NULL)
135 gmp_free_atom(e, sizeof(struct mpz_seg));
137 /* assign new value */
138 if (val == 0x80000000)
139 { /* long format is needed */
141 x->ptr = e = gmp_get_atom(sizeof(struct mpz_seg));
147 { /* short format is enough */
153 double mpz_get_d(mpz_t x)
154 { /* convert x to a double, truncating if necessary */
159 val = (double)x->val;
161 { xassert(x->val != 0);
164 for (e = x->ptr; e != NULL; e = e->next)
165 { for (j = 0; j <= 5; j++)
166 { val += deg * (double)((int)e->d[j]);
170 if (x->val < 0) val = - val;
175 double mpz_get_d_2exp(int *exp, mpz_t x)
176 { /* convert x to a double, truncating if necessary (i.e. rounding
177 towards zero), and returning the exponent separately;
178 the return value is in the range 0.5 <= |d| < 1 and the
179 exponent is stored to *exp; d*2^exp is the (truncated) x value;
180 if x is zero, the return is 0.0 and 0 is stored to *exp;
181 this is similar to the standard C frexp function */
186 val = (double)x->val, n = 0;
188 { xassert(x->val != 0);
190 for (e = x->ptr; e != NULL; e = e->next)
191 { for (j = 0; j <= 5; j++)
192 { val += (double)((int)e->d[j]);
193 val /= 65536.0, n += 16;
196 if (x->val < 0) val = - val;
198 val = frexp(val, &n1);
203 void mpz_swap(mpz_t x, mpz_t y)
204 { /* swap the values x and y efficiently */
207 val = x->val, ptr = x->ptr;
208 x->val = y->val, x->ptr = y->ptr;
209 y->val = val, y->ptr = ptr;
213 static void normalize(mpz_t x)
214 { /* normalize integer x that includes removing non-significant
215 (leading) zeros and converting to short format, if possible */
216 struct mpz_seg *es, *e;
217 /* if the integer is in short format, it remains unchanged */
219 { xassert(x->val != 0x80000000);
222 xassert(x->val == +1 || x->val == -1);
223 /* find the last (most significant) non-zero segment */
225 for (e = x->ptr; e != NULL; e = e->next)
226 { if (e->d[0] || e->d[1] || e->d[2] ||
227 e->d[3] || e->d[4] || e->d[5]) es = e;
229 /* if all segments contain zeros, the integer is zero */
234 /* remove non-significant (leading) zero segments */
235 while (es->next != NULL)
238 gmp_free_atom(e, sizeof(struct mpz_seg));
240 /* convert the integer to short format, if possible */
242 if (e->next == NULL && e->d[1] <= 0x7FFF &&
243 !e->d[2] && !e->d[3] && !e->d[4] && !e->d[5])
245 val = (int)e->d[0] + ((int)e->d[1] << 16);
246 if (x->val < 0) val = - val;
252 void mpz_add(mpz_t z, mpz_t x, mpz_t y)
253 { /* set z to x + y */
254 static struct mpz_seg zero = { { 0, 0, 0, 0, 0, 0 }, NULL };
255 struct mpz_seg dumx, dumy, *ex, *ey, *ez, *es, *ee;
258 /* if [x] = 0 then [z] = [y] */
260 { xassert(x->ptr == NULL);
264 /* if [y] = 0 then [z] = [x] */
266 { xassert(y->ptr == NULL);
270 /* special case when both [x] and [y] are in short format */
271 if (x->ptr == NULL && y->ptr == NULL)
272 { int xval = x->val, yval = y->val, zval = x->val + y->val;
273 xassert(xval != 0x80000000 && yval != 0x80000000);
274 if (!(xval > 0 && yval > 0 && zval <= 0 ||
275 xval < 0 && yval < 0 && zval >= 0))
276 { mpz_set_si(z, zval);
280 /* convert [x] to long format, if necessary */
282 { xassert(x->val != 0x80000000);
285 t = (unsigned int)(+ x->val);
289 t = (unsigned int)(- x->val);
292 ex->d[0] = (unsigned short)t;
293 ex->d[1] = (unsigned short)(t >> 16);
294 ex->d[2] = ex->d[3] = ex->d[4] = ex->d[5] = 0;
299 xassert(sx == +1 || sx == -1);
302 /* convert [y] to long format, if necessary */
304 { xassert(y->val != 0x80000000);
307 t = (unsigned int)(+ y->val);
311 t = (unsigned int)(- y->val);
314 ey->d[0] = (unsigned short)t;
315 ey->d[1] = (unsigned short)(t >> 16);
316 ey->d[2] = ey->d[3] = ey->d[4] = ey->d[5] = 0;
321 xassert(sy == +1 || sy == -1);
327 if (sx > 0 && sy > 0 || sx < 0 && sy < 0)
328 { /* [x] and [y] have identical signs -- addition */
330 for (; ex || ey; ex = ex->next, ey = ey->next)
331 { if (ex == NULL) ex = &zero;
332 if (ey == NULL) ey = &zero;
333 ee = gmp_get_atom(sizeof(struct mpz_seg));
334 for (k = 0; k <= 5; k++)
335 { t += (unsigned int)ex->d[k];
336 t += (unsigned int)ey->d[k];
337 ee->d[k] = (unsigned short)t;
348 { /* overflow -- one extra digit is needed */
349 ee = gmp_get_atom(sizeof(struct mpz_seg));
351 ee->d[1] = ee->d[2] = ee->d[3] = ee->d[4] = ee->d[5] = 0;
358 { /* [x] and [y] have different signs -- subtraction */
360 for (; ex || ey; ex = ex->next, ey = ey->next)
361 { if (ex == NULL) ex = &zero;
362 if (ey == NULL) ey = &zero;
363 ee = gmp_get_atom(sizeof(struct mpz_seg));
364 for (k = 0; k <= 5; k++)
365 { t += (unsigned int)ex->d[k];
366 t += (0xFFFF - (unsigned int)ey->d[k]);
367 ee->d[k] = (unsigned short)t;
378 { /* |[x]| < |[y]| -- result in complement coding */
381 for (ee = ez; ee != NULL; ee = ee->next)
382 for (k = 0; k <= 5; k++)
383 { t += (0xFFFF - (unsigned int)ee->d[k]);
384 ee->d[k] = (unsigned short)t;
389 /* contruct and normalize result */
397 void mpz_sub(mpz_t z, mpz_t x, mpz_t y)
398 { /* set z to x - y */
404 if (y != z) y->val = - y->val;
409 void mpz_mul(mpz_t z, mpz_t x, mpz_t y)
410 { /* set z to x * y */
411 struct mpz_seg dumx, dumy, *ex, *ey, *es, *e;
412 int sx, sy, k, nx, ny, n;
414 unsigned short *work, *wx, *wy;
415 /* if [x] = 0 then [z] = 0 */
417 { xassert(x->ptr == NULL);
421 /* if [y] = 0 then [z] = 0 */
423 { xassert(y->ptr == NULL);
427 /* special case when both [x] and [y] are in short format */
428 if (x->ptr == NULL && y->ptr == NULL)
429 { int xval = x->val, yval = y->val, sz = +1;
430 xassert(xval != 0x80000000 && yval != 0x80000000);
431 if (xval < 0) xval = - xval, sz = - sz;
432 if (yval < 0) yval = - yval, sz = - sz;
433 if (xval <= 0x7FFFFFFF / yval)
434 { mpz_set_si(z, sz * (xval * yval));
438 /* convert [x] to long format, if necessary */
440 { xassert(x->val != 0x80000000);
443 t = (unsigned int)(+ x->val);
447 t = (unsigned int)(- x->val);
450 ex->d[0] = (unsigned short)t;
451 ex->d[1] = (unsigned short)(t >> 16);
452 ex->d[2] = ex->d[3] = ex->d[4] = ex->d[5] = 0;
457 xassert(sx == +1 || sx == -1);
460 /* convert [y] to long format, if necessary */
462 { xassert(y->val != 0x80000000);
465 t = (unsigned int)(+ y->val);
469 t = (unsigned int)(- y->val);
472 ey->d[0] = (unsigned short)t;
473 ey->d[1] = (unsigned short)(t >> 16);
474 ey->d[2] = ey->d[3] = ey->d[4] = ey->d[5] = 0;
479 xassert(sy == +1 || sy == -1);
482 /* determine the number of digits of [x] */
484 for (e = ex; e != NULL; e = e->next)
485 for (k = 0; k <= 5; k++)
490 /* determine the number of digits of [y] */
492 for (e = ey; e != NULL; e = e->next)
493 for (k = 0; k <= 5; k++)
498 /* we need working array containing at least nx+ny+ny places */
499 work = gmp_get_work(nx+ny+ny);
500 /* load digits of [x] */
502 for (n = 0; n < nx; n++) wx[ny+n] = 0;
503 for (n = 0, e = ex; e != NULL; e = e->next)
504 for (k = 0; k <= 5; k++, n++)
505 if (e->d[k]) wx[ny+n] = e->d[k];
506 /* load digits of [y] */
508 for (n = 0; n < ny; n++) wy[n] = 0;
509 for (n = 0, e = ey; e != NULL; e = e->next)
510 for (k = 0; k <= 5; k++, n++)
511 if (e->d[k]) wy[n] = e->d[k];
512 /* compute [x] * [y] */
513 bigmul(nx, ny, wx, wy);
514 /* construct and normalize result */
519 for (n = 0; n < nx+ny; n++)
521 { e = gmp_get_atom(sizeof(struct mpz_seg));
522 e->d[0] = e->d[1] = e->d[2] = 0;
523 e->d[3] = e->d[4] = e->d[5] = 0;
538 void mpz_neg(mpz_t z, mpz_t x)
539 { /* set z to 0 - x */
545 void mpz_abs(mpz_t z, mpz_t x)
546 { /* set z to the absolute value of x */
548 if (z->val < 0) z->val = - z->val;
552 void mpz_div(mpz_t q, mpz_t r, mpz_t x, mpz_t y)
553 { /* divide x by y, forming quotient q and/or remainder r
554 if q = NULL then quotient is not stored; if r = NULL then
555 remainder is not stored
556 the sign of quotient is determined as in algebra while the
557 sign of remainder is the same as the sign of dividend:
558 +26 : +7 = +3, remainder is +5
559 -26 : +7 = -3, remainder is -5
560 +26 : -7 = -3, remainder is +5
561 -26 : -7 = +3, remainder is -5 */
562 struct mpz_seg dumx, dumy, *ex, *ey, *es, *e;
563 int sx, sy, k, nx, ny, n;
565 unsigned short *work, *wx, *wy;
566 /* divide by zero is not allowed */
568 { xassert(y->ptr == NULL);
569 xfault("mpz_div: divide by zero not allowed\n");
571 /* if [x] = 0 then [q] = [r] = 0 */
573 { xassert(x->ptr == NULL);
574 if (q != NULL) mpz_set_si(q, 0);
575 if (r != NULL) mpz_set_si(r, 0);
578 /* special case when both [x] and [y] are in short format */
579 if (x->ptr == NULL && y->ptr == NULL)
580 { int xval = x->val, yval = y->val;
581 xassert(xval != 0x80000000 && yval != 0x80000000);
582 if (q != NULL) mpz_set_si(q, xval / yval);
583 if (r != NULL) mpz_set_si(r, xval % yval);
586 /* convert [x] to long format, if necessary */
588 { xassert(x->val != 0x80000000);
591 t = (unsigned int)(+ x->val);
595 t = (unsigned int)(- x->val);
598 ex->d[0] = (unsigned short)t;
599 ex->d[1] = (unsigned short)(t >> 16);
600 ex->d[2] = ex->d[3] = ex->d[4] = ex->d[5] = 0;
605 xassert(sx == +1 || sx == -1);
608 /* convert [y] to long format, if necessary */
610 { xassert(y->val != 0x80000000);
613 t = (unsigned int)(+ y->val);
617 t = (unsigned int)(- y->val);
620 ey->d[0] = (unsigned short)t;
621 ey->d[1] = (unsigned short)(t >> 16);
622 ey->d[2] = ey->d[3] = ey->d[4] = ey->d[5] = 0;
627 xassert(sy == +1 || sy == -1);
630 /* determine the number of digits of [x] */
632 for (e = ex; e != NULL; e = e->next)
633 for (k = 0; k <= 5; k++)
638 /* determine the number of digits of [y] */
640 for (e = ey; e != NULL; e = e->next)
641 for (k = 0; k <= 5; k++)
646 /* if nx < ny then [q] = 0 and [r] = [x] */
648 { if (r != NULL) mpz_set(r, x);
649 if (q != NULL) mpz_set_si(q, 0);
652 /* we need working array containing at least nx+ny+1 places */
653 work = gmp_get_work(nx+ny+1);
654 /* load digits of [x] */
656 for (n = 0; n < nx; n++) wx[n] = 0;
657 for (n = 0, e = ex; e != NULL; e = e->next)
658 for (k = 0; k <= 5; k++, n++)
659 if (e->d[k]) wx[n] = e->d[k];
660 /* load digits of [y] */
662 for (n = 0; n < ny; n++) wy[n] = 0;
663 for (n = 0, e = ey; e != NULL; e = e->next)
664 for (k = 0; k <= 5; k++, n++)
665 if (e->d[k]) wy[n] = e->d[k];
666 /* compute quotient and remainder */
667 xassert(wy[ny-1] != 0);
668 bigdiv(nx-ny, ny, wx, wy);
669 /* construct and normalize quotient */
675 for (n = ny; n <= nx; n++)
677 { e = gmp_get_atom(sizeof(struct mpz_seg));
678 e->d[0] = e->d[1] = e->d[2] = 0;
679 e->d[3] = e->d[4] = e->d[5] = 0;
692 /* construct and normalize remainder */
698 for (n = 0; n < ny; n++)
700 { e = gmp_get_atom(sizeof(struct mpz_seg));
701 e->d[0] = e->d[1] = e->d[2] = 0;
702 e->d[3] = e->d[4] = e->d[5] = 0;
718 void mpz_gcd(mpz_t z, mpz_t x, mpz_t y)
719 { /* set z to the greatest common divisor of x and y */
720 /* in case of arbitrary integers GCD(x, y) = GCD(|x|, |y|), and,
721 in particular, GCD(0, 0) = 0 */
729 { mpz_div(NULL, r, u, v);
740 int mpz_cmp(mpz_t x, mpz_t y)
741 { /* compare x and y; return a positive value if x > y, zero if
742 x = y, or a nefative value if x < y */
743 static struct mpz_seg zero = { { 0, 0, 0, 0, 0, 0 }, NULL };
744 struct mpz_seg dumx, dumy, *ex, *ey;
751 /* special case when both [x] and [y] are in short format */
752 if (x->ptr == NULL && y->ptr == NULL)
753 { int xval = x->val, yval = y->val;
754 xassert(xval != 0x80000000 && yval != 0x80000000);
755 cc = (xval > yval ? +1 : xval < yval ? -1 : 0);
758 /* special case when [x] and [y] have different signs */
759 if (x->val > 0 && y->val <= 0 || x->val == 0 && y->val < 0)
763 if (x->val < 0 && y->val >= 0 || x->val == 0 && y->val > 0)
767 /* convert [x] to long format, if necessary */
769 { xassert(x->val != 0x80000000);
772 t = (unsigned int)(+ x->val);
776 t = (unsigned int)(- x->val);
779 ex->d[0] = (unsigned short)t;
780 ex->d[1] = (unsigned short)(t >> 16);
781 ex->d[2] = ex->d[3] = ex->d[4] = ex->d[5] = 0;
786 xassert(sx == +1 || sx == -1);
789 /* convert [y] to long format, if necessary */
791 { xassert(y->val != 0x80000000);
794 t = (unsigned int)(+ y->val);
798 t = (unsigned int)(- y->val);
801 ey->d[0] = (unsigned short)t;
802 ey->d[1] = (unsigned short)(t >> 16);
803 ey->d[2] = ey->d[3] = ey->d[4] = ey->d[5] = 0;
808 xassert(sy == +1 || sy == -1);
812 xassert(sx > 0 && sy > 0 || sx < 0 && sy < 0);
814 for (; ex || ey; ex = ex->next, ey = ey->next)
815 { if (ex == NULL) ex = &zero;
816 if (ey == NULL) ey = &zero;
817 for (k = 0; k <= 5; k++)
818 { if (ex->d[k] > ey->d[k]) cc = +1;
819 if (ex->d[k] < ey->d[k]) cc = -1;
822 if (sx < 0) cc = - cc;
827 { /* return +1 if x > 0, 0 if x = 0, and -1 if x < 0 */
829 s = (x->val > 0 ? +1 : x->val < 0 ? -1 : 0);
833 int mpz_out_str(void *_fp, int base, mpz_t x)
834 { /* output x on stream fp, as a string in given base; the base
835 may vary from 2 to 36;
836 return the number of bytes written, or if an error occurred,
842 static char *set = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
843 if (!(2 <= base && base <= 36))
844 xfault("mpz_out_str: base = %d; invalid base\n", base);
849 /* determine the number of digits */
851 for (n = 0; mpz_sgn(y) != 0; n++)
852 mpz_div(y, NULL, y, b);
854 /* compute the digits */
857 for (j = 0; j < n; j++)
858 { mpz_div(y, r, y, b);
859 xassert(0 <= r->val && r->val < base && r->ptr == NULL);
860 d[j] = (unsigned char)r->val;
862 /* output the integer to the stream */
863 if (fp == NULL) fp = stdout;
865 fputc('-', fp), nwr++;
866 for (j = n-1; j >= 0; j--)
867 fputc(set[d[j]], fp), nwr++;
868 if (ferror(fp)) nwr = 0;
876 /*====================================================================*/
878 mpq_t _mpq_init(void)
879 { /* initialize x, and set its value to 0/1 */
881 x = gmp_get_atom(sizeof(struct mpq));
889 void mpq_clear(mpq_t x)
890 { /* free the space occupied by x */
891 mpz_set_si(&x->p, 0);
892 xassert(x->p.ptr == NULL);
893 mpz_set_si(&x->q, 0);
894 xassert(x->q.ptr == NULL);
895 /* free the number descriptor */
896 gmp_free_atom(x, sizeof(struct mpq));
900 void mpq_canonicalize(mpq_t x)
901 { /* remove any factors that are common to the numerator and
902 denominator of x, and make the denominator positive */
904 xassert(x->q.val != 0);
906 { mpz_neg(&x->p, &x->p);
907 mpz_neg(&x->q, &x->q);
910 mpz_gcd(f, &x->p, &x->q);
911 if (!(f->val == 1 && f->ptr == NULL))
912 { mpz_div(&x->p, NULL, &x->p, f);
913 mpz_div(&x->q, NULL, &x->q, f);
919 void mpq_set(mpq_t z, mpq_t x)
920 { /* set the value of z from x */
922 { mpz_set(&z->p, &x->p);
923 mpz_set(&z->q, &x->q);
928 void mpq_set_si(mpq_t x, int p, unsigned int q)
929 { /* set the value of x to p/q */
931 xfault("mpq_set_si: zero denominator not allowed\n");
932 mpz_set_si(&x->p, p);
933 xassert(q <= 0x7FFFFFFF);
934 mpz_set_si(&x->q, q);
938 double mpq_get_d(mpq_t x)
939 { /* convert x to a double, truncating if necessary */
942 p = mpz_get_d_2exp(&np, &x->p);
943 q = mpz_get_d_2exp(&nq, &x->q);
944 return ldexp(p / q, np - nq);
947 void mpq_set_d(mpq_t x, double val)
948 { /* set x to val; there is no rounding, the conversion is exact */
952 xassert(-DBL_MAX <= val && val <= +DBL_MAX);
960 f = frexp(fabs(val), &n);
961 /* |val| = f * 2^n, where 0.5 <= f < 1.0 */
966 xassert(0 <= d && d <= 15);
968 /* x := 16 * x + d */
969 mpz_set_si(temp, 16);
970 mpz_mul(&x->p, &x->p, temp);
972 mpz_add(&x->p, &x->p, temp);
977 { for (j = 1; j <= n; j++)
978 mpz_add(&x->p, &x->p, &x->p);
981 { for (j = 1; j <= -n; j++)
982 mpz_add(&x->q, &x->q, &x->q);
985 if (s < 0) mpq_neg(x, x);
989 void mpq_add(mpq_t z, mpq_t x, mpq_t y)
990 { /* set z to x + y */
994 mpz_mul(p, &x->p, &y->q);
995 mpz_mul(q, &x->q, &y->p);
997 mpz_mul(q, &x->q, &y->q);
1002 mpq_canonicalize(z);
1006 void mpq_sub(mpq_t z, mpq_t x, mpq_t y)
1007 { /* set z to x - y */
1011 mpz_mul(p, &x->p, &y->q);
1012 mpz_mul(q, &x->q, &y->p);
1014 mpz_mul(q, &x->q, &y->q);
1019 mpq_canonicalize(z);
1023 void mpq_mul(mpq_t z, mpq_t x, mpq_t y)
1024 { /* set z to x * y */
1025 mpz_mul(&z->p, &x->p, &y->p);
1026 mpz_mul(&z->q, &x->q, &y->q);
1027 mpq_canonicalize(z);
1031 void mpq_div(mpq_t z, mpq_t x, mpq_t y)
1032 { /* set z to x / y */
1034 if (mpq_sgn(y) == 0)
1035 xfault("mpq_div: zero divisor not allowed\n");
1038 mpz_mul(p, &x->p, &y->q);
1039 mpz_mul(q, &x->q, &y->p);
1044 mpq_canonicalize(z);
1048 void mpq_neg(mpq_t z, mpq_t x)
1049 { /* set z to 0 - x */
1051 mpz_neg(&z->p, &z->p);
1055 void mpq_abs(mpq_t z, mpq_t x)
1056 { /* set z to the absolute value of x */
1058 mpz_abs(&z->p, &z->p);
1059 xassert(mpz_sgn(&x->q) > 0);
1063 int mpq_cmp(mpq_t x, mpq_t y)
1064 { /* compare x and y; return a positive value if x > y, zero if
1065 x = y, or a nefative value if x < y */
1069 mpq_sub(temp, x, y);
1075 int mpq_sgn(mpq_t x)
1076 { /* return +1 if x > 0, 0 if x = 0, and -1 if x < 0 */
1079 xassert(mpz_sgn(&x->q) > 0);
1083 int mpq_out_str(void *_fp, int base, mpq_t x)
1084 { /* output x on stream fp, as a string in given base; the base
1085 may vary from 2 to 36; output is in the form 'num/den' or if
1086 the denominator is 1 then just 'num';
1087 if the parameter fp is a null pointer, stdout is assumed;
1088 return the number of bytes written, or if an error occurred,
1092 if (!(2 <= base && base <= 36))
1093 xfault("mpq_out_str: base = %d; invalid base\n", base);
1094 if (fp == NULL) fp = stdout;
1095 nwr = mpz_out_str(fp, base, &x->p);
1096 if (x->q.val == 1 && x->q.ptr == NULL)
1099 { fputc('/', fp), nwr++;
1100 nwr += mpz_out_str(fp, base, &x->q);
1102 if (ferror(fp)) nwr = 0;