bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 1/2] libgmp-mpq: New module.


From: marc . nieper+gnu
Subject: [PATCH 1/2] libgmp-mpq: New module.
Date: Thu, 29 Aug 2024 11:19:34 +0200

From: Marc Nieper-Wißkirchen <marc@nieper-wisskirchen.de>

* MODULES.html.sh: Mention libgmp-mpz and
libgmp-mpq.
* config/srclist.txt: Mention mini-mpq.c and mini-mpq.h.
* lib/mini-mpq-gnulib.c: New file.
* lib/mini-mpq.c: New upstream source file.
* lib/mini-mpq.h: New upstream source file.
* modules/libgmp-mpq: New module.
* modules/libgmp-mpz: Conditionally include mini-mpq.h in gmp.h.
* modules/libgmp: Add libgmp-mpq dependency.
---
 ChangeLog             |  14 ++
 MODULES.html.sh       |   2 +
 config/srclist.txt    |   2 +
 lib/mini-mpq-gnulib.c |  48 ++++
 lib/mini-mpq.c        | 556 ++++++++++++++++++++++++++++++++++++++++++
 lib/mini-mpq.h        | 114 +++++++++
 modules/libgmp        |   1 +
 modules/libgmp-mpq    |  33 +++
 modules/libgmp-mpz    |   3 +
 9 files changed, 773 insertions(+)
 create mode 100644 lib/mini-mpq-gnulib.c
 create mode 100644 lib/mini-mpq.c
 create mode 100644 lib/mini-mpq.h
 create mode 100644 modules/libgmp-mpq

diff --git a/ChangeLog b/ChangeLog
index 07e84fb216..6dc01c81f6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2024-08-29  Marc Nieper-Wißkirchen  <marc@nieper-wisskirchen.de>
+
+       libgmp-mpq: New module.
+       * MODULES.html.sh: Mention libgmp-mpz and
+       libgmp-mpq.
+       * config/srclist.txt: Mention mini-mpq.c and mini-mpq.h.
+       * lib/mini-mpq-gnulib.c: New file.
+       * lib/mini-mpq.c: New upstream source file.
+       * lib/mini-mpq.h: New upstream source file.
+       * modules/libgmp-mpq: New module.
+       * modules/libgmp-mpz: Conditionally include mini-mpq.h in gmp.h.
+       * modules/libgmp: Add libgmp-mpq dependency.
+
+
 2024-08-28  Pádraig Brady  <P@draigBrady.com>
 
        avoid GCC -Wmaybe-uninitialized false positives with LTO
diff --git a/MODULES.html.sh b/MODULES.html.sh
index b3990e070a..711659f042 100755
--- a/MODULES.html.sh
+++ b/MODULES.html.sh
@@ -2499,6 +2499,8 @@ func_all_modules ()
 
   func_begin_table
   func_module libgmp
+  func_module libgmp-mpz
+  func_module libgmp-mpq
   func_end_table
 
   element="Support for sharing code with the GNU C Library"
diff --git a/config/srclist.txt b/config/srclist.txt
index ce47f3f210..dbf32d5246 100644
--- a/config/srclist.txt
+++ b/config/srclist.txt
@@ -19,6 +19,8 @@ $AUTOCONF doc/install.texi    doc
 
 $GMP mini-gmp/mini-gmp.c       lib
 $GMP mini-gmp/mini-gmp.h       lib
+$GMP mini-gmp/mini-mpq.c       lib
+$GMP mini-gmp/mini-mpq.h       lib
 
 $GNUSTANDARDS maintain.texi    doc strip-trailing-space
 $GNUSTANDARDS standards.texi   doc strip-trailing-space
diff --git a/lib/mini-mpq-gnulib.c b/lib/mini-mpq-gnulib.c
new file mode 100644
index 0000000000..a234d80af3
--- /dev/null
+++ b/lib/mini-mpq-gnulib.c
@@ -0,0 +1,48 @@
+/* Tailor mini-mpq.c for Gnulib-using applications.
+
+   Copyright 2018-2024 Free Software Foundation, Inc.
+
+   This file is free software.
+   It is dual-licensed under "the GNU LGPLv3+ or the GNU GPLv2+".
+   You can redistribute it and/or modify it under either
+     - the terms of the GNU Lesser General Public License as published
+       by the Free Software Foundation, either version 3, or (at your
+       option) any later version, or
+     - the terms of the GNU General Public License as published by the
+       Free Software Foundation; either version 2, or (at your option)
+       any later version, or
+     - the same dual license "the GNU LGPLv3+ or the GNU GPLv2+".
+
+   This file 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
+   Lesser General Public License and the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License and of the GNU General Public License along with this
+   program.  If not, see <https://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include <stddef.h>
+#include <stdio.h>
+
+#include "mini-mpq.h"
+
+/* Pacify GCC -Wsuggest-attribute=const, pure, malloc.  */
+#if _GL_GNUC_PREREQ (4, 6)
+# pragma GCC diagnostic ignored "-Wsuggest-attribute=const"
+# pragma GCC diagnostic ignored "-Wsuggest-attribute=pure"
+#endif
+#if _GL_GNUC_PREREQ (8, 0)
+# pragma GCC diagnostic ignored "-Wsuggest-attribute=malloc"
+#endif
+
+/* Pacify GCC -Wunused-variable for variables used only in 'assert' calls.  */
+#if (defined NDEBUG \
+     && (4 < __GNUC__ + (6 <= __GNUC_MINOR__) || defined __clang__))
+# pragma GCC diagnostic ignored "-Wunused-variable"
+#endif
+
+#include "mini-mpq.c"
diff --git a/lib/mini-mpq.c b/lib/mini-mpq.c
new file mode 100644
index 0000000000..58ce37f1d2
--- /dev/null
+++ b/lib/mini-mpq.c
@@ -0,0 +1,556 @@
+/* mini-mpq, a minimalistic implementation of a GNU GMP subset.
+
+   Contributed to the GNU project by Marco Bodrato
+
+   Acknowledgment: special thanks to Bradley Lucier for his comments
+   to the preliminary version of this code.
+
+Copyright 2018-2022 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of either:
+
+  * the GNU Lesser General Public License as published by the Free
+    Software Foundation; either version 3 of the License, or (at your
+    option) any later version.
+
+or
+
+  * 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.
+
+or both in parallel, as here.
+
+The GNU MP Library 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 copies of the GNU General Public License and the
+GNU Lesser General Public License along with the GNU MP Library.  If not,
+see https://www.gnu.org/licenses/.  */
+
+#include <assert.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "mini-mpq.h"
+
+#ifndef GMP_LIMB_HIGHBIT
+/* Define macros and static functions already defined by mini-gmp.c */
+#define GMP_LIMB_BITS (sizeof(mp_limb_t) * CHAR_BIT)
+#define GMP_LIMB_HIGHBIT ((mp_limb_t) 1 << (GMP_LIMB_BITS - 1))
+#define GMP_LIMB_MAX ((mp_limb_t) ~ (mp_limb_t) 0)
+#define GMP_NEG_CAST(T,x) (-((T)((x) + 1) - 1))
+#define GMP_MIN(a, b) ((a) < (b) ? (a) : (b))
+
+static mpz_srcptr
+mpz_roinit_normal_n (mpz_t x, mp_srcptr xp, mp_size_t xs)
+{
+  x->_mp_alloc = 0;
+  x->_mp_d = (mp_ptr) xp;
+  x->_mp_size = xs;
+  return x;
+}
+
+static void
+gmp_die (const char *msg)
+{
+  fprintf (stderr, "%s\n", msg);
+  abort();
+}
+#endif
+
+
+/* MPQ helper functions */
+static mpq_srcptr
+mpq_roinit_normal_nn (mpq_t x, mp_srcptr np, mp_size_t ns,
+                    mp_srcptr dp, mp_size_t ds)
+{
+  mpz_roinit_normal_n (mpq_numref(x), np, ns);
+  mpz_roinit_normal_n (mpq_denref(x), dp, ds);
+  return x;
+}
+
+static mpq_srcptr
+mpq_roinit_zz (mpq_t x, mpz_srcptr n, mpz_srcptr d)
+{
+  return mpq_roinit_normal_nn (x, n->_mp_d, n->_mp_size,
+                              d->_mp_d, d->_mp_size);
+}
+
+static void
+mpq_nan_init (mpq_t x)
+{
+  mpz_init (mpq_numref (x));
+  mpz_init (mpq_denref (x));
+}
+
+void
+mpq_init (mpq_t x)
+{
+  mpz_init (mpq_numref (x));
+  mpz_init_set_ui (mpq_denref (x), 1);
+}
+
+void
+mpq_clear (mpq_t x)
+{
+  mpz_clear (mpq_numref (x));
+  mpz_clear (mpq_denref (x));
+}
+
+static void
+mpq_canonical_sign (mpq_t r)
+{
+  mp_size_t ds = mpq_denref (r)->_mp_size;
+  if (ds <= 0)
+    {
+      if (ds == 0)
+       gmp_die("mpq: Fraction with zero denominator.");
+      mpz_neg (mpq_denref (r), mpq_denref (r));
+      mpz_neg (mpq_numref (r), mpq_numref (r));
+    }
+}
+
+static void
+mpq_helper_canonicalize (mpq_t r, const mpz_t num, const mpz_t den)
+{
+  if (num->_mp_size == 0)
+    mpq_set_ui (r, 0, 1);
+  else
+    {
+      mpz_t g;
+
+      mpz_init (g);
+      mpz_gcd (g, num, den);
+      mpz_tdiv_q (mpq_numref (r), num, g);
+      mpz_tdiv_q (mpq_denref (r), den, g);
+      mpz_clear (g);
+      mpq_canonical_sign (r);
+    }
+}
+
+void
+mpq_canonicalize (mpq_t r)
+{
+  mpq_helper_canonicalize (r, mpq_numref (r), mpq_denref (r));
+}
+
+void
+mpq_swap (mpq_t a, mpq_t b)
+{
+  mpz_swap (mpq_numref (a), mpq_numref (b));
+  mpz_swap (mpq_denref (a), mpq_denref (b));
+}
+
+
+/* MPQ assignment and conversions. */
+void
+mpz_set_q (mpz_t r, const mpq_t q)
+{
+  mpz_tdiv_q (r, mpq_numref (q), mpq_denref (q));
+}
+
+void
+mpq_set (mpq_t r, const mpq_t q)
+{
+  mpz_set (mpq_numref (r), mpq_numref (q));
+  mpz_set (mpq_denref (r), mpq_denref (q));
+}
+
+void
+mpq_set_ui (mpq_t r, unsigned long n, unsigned long d)
+{
+  mpz_set_ui (mpq_numref (r), n);
+  mpz_set_ui (mpq_denref (r), d);
+}
+
+void
+mpq_set_si (mpq_t r, signed long n, unsigned long d)
+{
+  mpz_set_si (mpq_numref (r), n);
+  mpz_set_ui (mpq_denref (r), d);
+}
+
+void
+mpq_set_z (mpq_t r, const mpz_t n)
+{
+  mpz_set_ui (mpq_denref (r), 1);
+  mpz_set (mpq_numref (r), n);
+}
+
+void
+mpq_set_num (mpq_t r, const mpz_t z)
+{
+  mpz_set (mpq_numref (r), z);
+}
+
+void
+mpq_set_den (mpq_t r, const mpz_t z)
+{
+  mpz_set (mpq_denref (r), z);
+}
+
+void
+mpq_get_num (mpz_t r, const mpq_t q)
+{
+  mpz_set (r, mpq_numref (q));
+}
+
+void
+mpq_get_den (mpz_t r, const mpq_t q)
+{
+  mpz_set (r, mpq_denref (q));
+}
+
+
+/* MPQ comparisons and the like. */
+int
+mpq_cmp (const mpq_t a, const mpq_t b)
+{
+  mpz_t t1, t2;
+  int res;
+
+  mpz_init (t1);
+  mpz_init (t2);
+  mpz_mul (t1, mpq_numref (a), mpq_denref (b));
+  mpz_mul (t2, mpq_numref (b), mpq_denref (a));
+  res = mpz_cmp (t1, t2);
+  mpz_clear (t1);
+  mpz_clear (t2);
+
+  return res;
+}
+
+int
+mpq_cmp_z (const mpq_t a, const mpz_t b)
+{
+  mpz_t t;
+  int res;
+
+  mpz_init (t);
+  mpz_mul (t, b, mpq_denref (a));
+  res = mpz_cmp (mpq_numref (a), t);
+  mpz_clear (t);
+
+  return res;
+}
+
+int
+mpq_equal (const mpq_t a, const mpq_t b)
+{
+  return (mpz_cmp (mpq_numref (a), mpq_numref (b)) == 0) &&
+    (mpz_cmp (mpq_denref (a), mpq_denref (b)) == 0);
+}
+
+int
+mpq_cmp_ui (const mpq_t q, unsigned long n, unsigned long d)
+{
+  mpq_t t;
+  assert (d != 0);
+  if (ULONG_MAX <= GMP_LIMB_MAX) {
+    mp_limb_t nl = n, dl = d;
+    return mpq_cmp (q, mpq_roinit_normal_nn (t, &nl, n != 0, &dl, 1));
+  } else {
+    int ret;
+
+    mpq_nan_init (t);
+    mpq_set_ui (t, n, d);
+    ret = mpq_cmp (q, t);
+    mpq_clear (t);
+
+    return ret;
+  }
+}
+
+int
+mpq_cmp_si (const mpq_t q, signed long n, unsigned long d)
+{
+  assert (d != 0);
+
+  if (n >= 0)
+    return mpq_cmp_ui (q, n, d);
+  else
+    {
+      mpq_t t;
+
+      if (ULONG_MAX <= GMP_LIMB_MAX)
+       {
+         mp_limb_t nl = GMP_NEG_CAST (unsigned long, n), dl = d;
+         return mpq_cmp (q, mpq_roinit_normal_nn (t, &nl, -1, &dl, 1));
+       }
+      else
+       {
+         unsigned long l_n = GMP_NEG_CAST (unsigned long, n);
+
+         mpq_roinit_normal_nn (t, mpq_numref (q)->_mp_d, - mpq_numref 
(q)->_mp_size,
+                               mpq_denref (q)->_mp_d, mpq_denref 
(q)->_mp_size);
+         return - mpq_cmp_ui (t, l_n, d);
+       }
+    }
+}
+
+int
+mpq_sgn (const mpq_t a)
+{
+  return mpz_sgn (mpq_numref (a));
+}
+
+
+/* MPQ arithmetic. */
+void
+mpq_abs (mpq_t r, const mpq_t q)
+{
+  mpz_abs (mpq_numref (r), mpq_numref (q));
+  mpz_set (mpq_denref (r), mpq_denref (q));
+}
+
+void
+mpq_neg (mpq_t r, const mpq_t q)
+{
+  mpz_neg (mpq_numref (r), mpq_numref (q));
+  mpz_set (mpq_denref (r), mpq_denref (q));
+}
+
+void
+mpq_add (mpq_t r, const mpq_t a, const mpq_t b)
+{
+  mpz_t t;
+
+  mpz_init (t);
+  mpz_gcd (t, mpq_denref (a), mpq_denref (b));
+  if (mpz_cmp_ui (t, 1) == 0)
+    {
+      mpz_mul (t, mpq_numref (a), mpq_denref (b));
+      mpz_addmul (t, mpq_numref (b), mpq_denref (a));
+      mpz_mul (mpq_denref (r), mpq_denref (a), mpq_denref (b));
+      mpz_swap (mpq_numref (r), t);
+    }
+  else
+    {
+      mpz_t x, y;
+      mpz_init (x);
+      mpz_init (y);
+
+      mpz_tdiv_q (x, mpq_denref (b), t);
+      mpz_tdiv_q (y, mpq_denref (a), t);
+      mpz_mul (x, mpq_numref (a), x);
+      mpz_addmul (x, mpq_numref (b), y);
+
+      mpz_gcd (t, x, t);
+      mpz_tdiv_q (mpq_numref (r), x, t);
+      mpz_tdiv_q (x, mpq_denref (b), t);
+      mpz_mul (mpq_denref (r), x, y);
+
+      mpz_clear (x);
+      mpz_clear (y);
+    }
+  mpz_clear (t);
+}
+
+void
+mpq_sub (mpq_t r, const mpq_t a, const mpq_t b)
+{
+  mpq_t t;
+
+  mpq_roinit_normal_nn (t, mpq_numref (b)->_mp_d, - mpq_numref (b)->_mp_size,
+                       mpq_denref (b)->_mp_d, mpq_denref (b)->_mp_size);
+  mpq_add (r, a, t);
+}
+
+void
+mpq_div (mpq_t r, const mpq_t a, const mpq_t b)
+{
+  mpq_t t;
+  mpq_mul (r, a, mpq_roinit_zz (t, mpq_denref (b), mpq_numref (b)));
+}
+
+void
+mpq_mul (mpq_t r, const mpq_t a, const mpq_t b)
+{
+  mpq_t t;
+  mpq_nan_init (t);
+
+  if (a != b) {
+    mpq_helper_canonicalize (t, mpq_numref (a), mpq_denref (b));
+    mpq_helper_canonicalize (r, mpq_numref (b), mpq_denref (a));
+
+    a = r;
+    b = t;
+  }
+
+  mpz_mul (mpq_numref (r), mpq_numref (a), mpq_numref (b));
+  mpz_mul (mpq_denref (r), mpq_denref (a), mpq_denref (b));
+  mpq_clear (t);
+}
+
+static void
+mpq_helper_2exp (mpz_t rn, mpz_t rd, const mpz_t qn, const mpz_t qd, 
mp_bitcnt_t e)
+{
+  mp_bitcnt_t z = mpz_scan1 (qd, 0);
+  z = GMP_MIN (z, e);
+  mpz_mul_2exp (rn, qn, e - z);
+  mpz_tdiv_q_2exp (rd, qd, z);
+}
+
+void
+mpq_div_2exp (mpq_t r, const mpq_t q, mp_bitcnt_t e)
+{
+  mpq_helper_2exp (mpq_denref (r), mpq_numref (r), mpq_denref (q), mpq_numref 
(q), e);
+}
+
+void
+mpq_mul_2exp (mpq_t r, const mpq_t q, mp_bitcnt_t e)
+{
+  mpq_helper_2exp (mpq_numref (r), mpq_denref (r), mpq_numref (q), mpq_denref 
(q), e);
+}
+
+void
+mpq_inv (mpq_t r, const mpq_t q)
+{
+  mpq_set (r, q);
+  mpz_swap (mpq_denref (r), mpq_numref (r));
+  mpq_canonical_sign (r);
+}
+
+
+/* MPQ to/from double. */
+void
+mpq_set_d (mpq_t r, double x)
+{
+  mpz_set_ui (mpq_denref (r), 1);
+
+  /* x != x is true when x is a NaN, and x == x * 0.5 is true when x is
+     zero or infinity. */
+  if (x == x * 0.5 || x != x)
+    mpq_numref (r)->_mp_size = 0;
+  else
+    {
+      double B;
+      mp_bitcnt_t e;
+
+      B = 4.0 * (double) (GMP_LIMB_HIGHBIT >> 1);
+      for (e = 0; x != x + 0.5; e += GMP_LIMB_BITS)
+       x *= B;
+
+      mpz_set_d (mpq_numref (r), x);
+      mpq_div_2exp (r, r, e);
+    }
+}
+
+double
+mpq_get_d (const mpq_t u)
+{
+  mp_bitcnt_t ne, de, ee;
+  mpz_t z;
+  double B, ret;
+
+  ne = mpz_sizeinbase (mpq_numref (u), 2);
+  de = mpz_sizeinbase (mpq_denref (u), 2);
+
+  ee = CHAR_BIT * sizeof (double);
+  if (de == 1 || ne > de + ee)
+    ee = 0;
+  else
+    ee = (ee + de - ne) / GMP_LIMB_BITS + 1;
+
+  mpz_init (z);
+  mpz_mul_2exp (z, mpq_numref (u), ee * GMP_LIMB_BITS);
+  mpz_tdiv_q (z, z, mpq_denref (u));
+  ret = mpz_get_d (z);
+  mpz_clear (z);
+
+  B = 4.0 * (double) (GMP_LIMB_HIGHBIT >> 1);
+  for (B = 1 / B; ee != 0; --ee)
+    ret *= B;
+
+  return ret;
+}
+
+
+/* MPQ and strings/streams. */
+char *
+mpq_get_str (char *sp, int base, const mpq_t q)
+{
+  char *res;
+  char *rden;
+  size_t len;
+
+  res = mpz_get_str (sp, base, mpq_numref (q));
+  if (res == NULL || mpz_cmp_ui (mpq_denref (q), 1) == 0)
+    return res;
+
+  len = strlen (res) + 1;
+  rden = sp ? sp + len : NULL;
+  rden = mpz_get_str (rden, base, mpq_denref (q));
+  assert (rden != NULL);
+
+  if (sp == NULL) {
+    void * (*gmp_reallocate_func) (void *, size_t, size_t);
+    void (*gmp_free_func) (void *, size_t);
+    size_t lden;
+
+    mp_get_memory_functions (NULL, &gmp_reallocate_func, &gmp_free_func);
+    lden = strlen (rden) + 1;
+    res = (char *) gmp_reallocate_func (res, len, (lden + len) * sizeof 
(char));
+    memcpy (res + len, rden, lden);
+    gmp_free_func (rden, lden);
+  }
+
+  res [len - 1] = '/';
+  return res;
+}
+
+size_t
+mpq_out_str (FILE *stream, int base, const mpq_t x)
+{
+  char * str;
+  size_t len, n;
+  void (*gmp_free_func) (void *, size_t);
+
+  str = mpq_get_str (NULL, base, x);
+  if (!str)
+    return 0;
+  len = strlen (str);
+  n = fwrite (str, 1, len, stream);
+  mp_get_memory_functions (NULL, NULL, &gmp_free_func);
+  gmp_free_func (str, len + 1);
+  return n;
+}
+
+int
+mpq_set_str (mpq_t r, const char *sp, int base)
+{
+  const char *slash;
+
+  slash = strchr (sp, '/');
+  if (slash == NULL) {
+    mpz_set_ui (mpq_denref(r), 1);
+    return mpz_set_str (mpq_numref(r), sp, base);
+  } else {
+    char *num;
+    size_t numlen;
+    int ret;
+    void * (*gmp_allocate_func) (size_t);
+    void (*gmp_free_func) (void *, size_t);
+
+    mp_get_memory_functions (&gmp_allocate_func, NULL, &gmp_free_func);
+    numlen = slash - sp;
+    num = (char *) gmp_allocate_func (numlen + 1);
+    memcpy (num, sp, numlen);
+    num[numlen] = '\0';
+    ret = mpz_set_str (mpq_numref(r), num, base);
+    gmp_free_func (num, numlen + 1);
+
+    if (ret != 0)
+      return ret;
+
+    return mpz_set_str (mpq_denref(r), slash + 1, base);
+  }
+}
diff --git a/lib/mini-mpq.h b/lib/mini-mpq.h
new file mode 100644
index 0000000000..8eabcec87c
--- /dev/null
+++ b/lib/mini-mpq.h
@@ -0,0 +1,114 @@
+/* mini-mpq, a minimalistic implementation of a GNU GMP subset.
+
+Copyright 2018, 2019 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of either:
+
+  * the GNU Lesser General Public License as published by the Free
+    Software Foundation; either version 3 of the License, or (at your
+    option) any later version.
+
+or
+
+  * 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.
+
+or both in parallel, as here.
+
+The GNU MP Library 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 copies of the GNU General Public License and the
+GNU Lesser General Public License along with the GNU MP Library.  If not,
+see https://www.gnu.org/licenses/.  */
+
+/* Header */
+
+#ifndef __MINI_MPQ_H__
+#define __MINI_MPQ_H__
+
+#include "mini-gmp.h"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+typedef struct
+{
+  __mpz_struct _mp_num;
+  __mpz_struct _mp_den;
+} __mpq_struct;
+
+typedef __mpq_struct mpq_t[1];
+
+typedef const __mpq_struct *mpq_srcptr;
+typedef __mpq_struct *mpq_ptr;
+
+#define mpq_numref(Q) (&((Q)->_mp_num))
+#define mpq_denref(Q) (&((Q)->_mp_den))
+
+void mpq_abs (mpq_t, const mpq_t);
+void mpq_add (mpq_t, const mpq_t, const mpq_t);
+void mpq_canonicalize (mpq_t);
+void mpq_clear (mpq_t);
+int mpq_cmp (const mpq_t, const mpq_t);
+int mpq_cmp_si (const mpq_t, signed long, unsigned long);
+int mpq_cmp_ui (const mpq_t, unsigned long, unsigned long);
+int mpq_cmp_z (const mpq_t, const mpz_t);
+void mpq_div (mpq_t, const mpq_t, const mpq_t);
+void mpq_div_2exp (mpq_t, const mpq_t, mp_bitcnt_t);
+int mpq_equal (const mpq_t, const mpq_t);
+double mpq_get_d (const mpq_t);
+void mpq_get_den (mpz_t, const mpq_t);
+void mpq_get_num (mpz_t, const mpq_t);
+char * mpq_get_str (char *, int, const mpq_t q);
+void mpq_init (mpq_t);
+void mpq_inv (mpq_t, const mpq_t);
+void mpq_mul (mpq_t, const mpq_t, const mpq_t);
+void mpq_mul_2exp (mpq_t, const mpq_t, mp_bitcnt_t);
+void mpq_neg (mpq_t, const mpq_t);
+void mpq_set (mpq_t, const mpq_t);
+void mpq_set_d (mpq_t, double);
+void mpq_set_den (mpq_t, const mpz_t);
+void mpq_set_num (mpq_t, const mpz_t);
+void mpq_set_si (mpq_t, signed long, unsigned long);
+int mpq_set_str (mpq_t, const char *, int);
+void mpq_set_ui (mpq_t, unsigned long, unsigned long);
+void mpq_set_z (mpq_t, const mpz_t);
+int mpq_sgn (const mpq_t);
+void mpq_sub (mpq_t, const mpq_t, const mpq_t);
+void mpq_swap (mpq_t, mpq_t);
+
+/* This long list taken from gmp.h. */
+/* For reference, "defined(EOF)" cannot be used here.  In g++ 2.95.4,
+   <iostream> defines EOF but not FILE.  */
+#if defined (FILE)                                              \
+  || defined (H_STDIO)                                          \
+  || defined (_H_STDIO)               /* AIX */                 \
+  || defined (_STDIO_H)               /* glibc, Sun, SCO */     \
+  || defined (_STDIO_H_)              /* BSD, OSF */            \
+  || defined (__STDIO_H)              /* Borland */             \
+  || defined (__STDIO_H__)            /* IRIX */                \
+  || defined (_STDIO_INCLUDED)        /* HPUX */                \
+  || defined (__dj_include_stdio_h_)  /* DJGPP */               \
+  || defined (_FILE_DEFINED)          /* Microsoft */           \
+  || defined (__STDIO__)              /* Apple MPW MrC */       \
+  || defined (_MSL_STDIO_H)           /* Metrowerks */          \
+  || defined (_STDIO_H_INCLUDED)      /* QNX4 */                \
+  || defined (_ISO_STDIO_ISO_H)       /* Sun C++ */             \
+  || defined (__STDIO_LOADED)         /* VMS */
+size_t mpq_out_str (FILE *, int, const mpq_t);
+#endif
+
+void mpz_set_q (mpz_t, const mpq_t);
+
+#if defined (__cplusplus)
+}
+#endif
+#endif /* __MINI_MPQ_H__ */
diff --git a/modules/libgmp b/modules/libgmp
index 0668b6c3cb..77a54f6b14 100644
--- a/modules/libgmp
+++ b/modules/libgmp
@@ -6,6 +6,7 @@ Files:
 
 Depends-on:
 libgmp-mpz
+libgmp-mpq
 
 configure.ac:
 
diff --git a/modules/libgmp-mpq b/modules/libgmp-mpq
new file mode 100644
index 0000000000..ac61b01bc2
--- /dev/null
+++ b/modules/libgmp-mpq
@@ -0,0 +1,33 @@
+Description:
+GNU Multiple Precision Arithmetic library (mpq_* part),
+or its mini-gmp substitute
+
+Files:
+lib/mini-mpq-gnulib.c
+lib/mini-mpq.c
+lib/mini-mpq.h
+
+Depends-on:
+libgmp-mpz
+
+configure.ac:
+gl_LIBGMP
+gl_CONDITIONAL([GL_COND_OBJ_MINI_MPQ_GNULIB], [test $HAVE_LIBGMP != yes])
+gl_MODULE_INDICATOR([libgmp-mpq])
+
+Makefile.am:
+if GL_COND_OBJ_MINI_MPQ_GNULIB
+lib_SOURCES += mini-mpq-gnulib.c
+endif
+
+Include:
+<gmp.h>
+
+Link:
+$(LTLIBGMP) when linking with libtool, $(LIBGMP) otherwise
+
+License:
+LGPLv3+ or GPLv2+
+
+Maintainer:
+all
diff --git a/modules/libgmp-mpz b/modules/libgmp-mpz
index 4104e79cba..bdc14e5ff6 100644
--- a/modules/libgmp-mpz
+++ b/modules/libgmp-mpz
@@ -25,6 +25,9 @@ if GL_GENERATE_MINI_GMP_H
 gmp.h: $(top_builddir)/config.status
 @NMD@  $(MKDIR_P) '%reldir%'
        echo '#include "mini-gmp.h"' > $@-t
+       echo '#if GNULIB_LIBGMP_MPQ' >> $@-t
+       echo '# include "mini-mpq.h"' >> $@-t
+       echo '#endif' >> $@-t
        mv $@-t $@
 endif
 if GL_GENERATE_GMP_GMP_H
-- 
2.34.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]