Ciao,

the message wasintended for gmp-devel, but of course was not off-topic on
discuss too.

Il Mer, 14 Febbraio 2018 7:53 pm, Marco Bodrato ha scritto:
> Ciao,
>
> Il Mar, 13 Febbraio 2018 7:38 pm, Daniele Panozzo ha scritto:
>> Is there any plan to extend mini-gmp to rationals (mpq)? This would
>> really
>> make it perfect for my use case.
>
> Curious request. We sometimes discussed about modularising mini-gmp. This
> request would benefit of such a modularisation.
>
> It shouldn't be too difficoult to add the mpq layer; at least if you don't
> need to deal with floats types nor strings.
>
> I tried to write some functions, just to see how difficoult it could be. I
> attach a possible implementation. Would it fit your needs?
>
> Of course, extending mini-gmp would not only mean writing some simple
> functions, but also integrating them in the existing code and, this is
> REALLY IMPORTANT, writing some tests!
>
> The attached code was NOT TESTED in any way! It can be a starting point.

Ĝis,
m

-- 
http://bodrato.it/papers/
/* mini-mpq, a minimalistic implementation of a GNU GMP subset.

Copyright 1991-1997, 1999-2018 Free Software Foundation, Inc.
Copyright 2018 Marco BODRATO.

This file is intendet for the GNU MP Library.

This is free software; you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License as published by
the Free Software Foundation; either version 3 of the License, or (at
your option) any later version.

This software 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 Affero
General Public License for more details.

You should have received copies of the GNU Affero General Public
License with the software.
If not, see https://www.gnu.org/licenses/.  */

/* WARNING: this code was not tested! */


/* Header */

#include "mini-gmp.h"

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_ptr, mpq_srcptr);
void mpq_add (mpq_ptr, mpq_srcptr, mpq_srcptr);
void mpq_clear (mpq_t);
void mpq_canonicalize (mpq_ptr);
int mpq_cmp (mpq_srcptr, mpq_srcptr);
int mpq_cmp_z (mpq_srcptr, mpz_srcptr);
void mpq_div (mpq_ptr, mpq_srcptr, mpq_srcptr);
void mpq_div_2exp (mpq_ptr, mpq_srcptr, mp_bitcnt_t);
int mpq_equal (mpq_srcptr, mpq_srcptr);
void mpq_get_den (mpz_ptr, mpq_srcptr);
void mpq_get_num (mpz_ptr, mpq_srcptr);
void mpq_init (mpq_t);
void mpq_inv (mpq_ptr, mpq_srcptr);
void mpq_mul (mpq_ptr, mpq_srcptr, mpq_srcptr);
void mpq_mul_2exp (mpq_ptr, mpq_srcptr, mp_bitcnt_t);
void mpq_neg (mpq_ptr, mpq_srcptr);
void mpq_set (mpq_ptr, mpq_srcptr);
void mpq_set_den (mpq_ptr, mpz_srcptr);
void mpq_set_num (mpq_ptr, mpz_srcptr);
void mpq_set_si (mpq_ptr, signed long, unsigned long);
void mpq_set_ui (mpq_ptr, unsigned long, unsigned long);
void mpq_set_z (mpq_ptr, mpz_srcptr);
void mpq_sub (mpq_ptr, mpq_srcptr, mpq_srcptr);
void mpq_swap (mpq_ptr, mpq_ptr);
int _mpq_cmp_si (mpq_srcptr, signed long int, unsigned long int);
int _mpq_cmp_ui (mpq_srcptr, unsigned long int, unsigned long int);

void mpz_set_q (mpz_ptr, mpq_srcptr);


/* Implementation */

/* #include "mini-gmp.c" */

#define NUM(x) mpq_numref(x)
#define DEN(x) mpq_denref(x)

void
mpz_set_q (mpz_ptr r, mpq_srcptr q)
{
  mpz_div_qr (r, NULL, NUM(q), DEN(q), GMP_DIV_TRUNC);
}

void
mpq_init (mpq_t x)
{
  mpz_init (NUM(x));
  mpz_init_set_ui (DEN(x), 1);
}

void
mpq_clear (mpq_t x)
{
  mpz_clear (NUM(x));
  mpz_clear (DEN(x));
}

static void
__mpq_canonical_sign (mpq_ptr r)
{
  if (mpz_cmp_ui (DEN(r), 0) < 0)
    {
      mpz_neg (DEN(r), DEN(r));
      mpz_neg (NUM(r), NUM(r));
    }
}

static void
__mpq_helper_canonicalize (mpq_ptr r, mpz_t g)
{
  if (mpz_cmp_ui (NUM(r), 0) == 0)
    {
      mpz_set_ui (DEN(r), 1);
    }
  else
    {
      mpz_gcd (g, NUM(r), DEN(r));
      mpz_div_qr (NUM(r), NULL, NUM(r), g, GMP_DIV_TRUNC);
      mpz_div_qr (DEN(r), NULL, DEN(r), g, GMP_DIV_TRUNC);
      __mpq_canonical_sign (r);
    }
}

void
mpq_canonicalize (mpq_ptr r)
{
  mpz_t t;

  mpz_init (t);
  __mpq_helper_canonicalize (r, t);
  mpz_clear (t);
}

void
mpq_abs (mpq_ptr r, mpq_srcptr q)
{
  mpz_abs (NUM(r), NUM(q));
  mpz_set (DEN(r), DEN(q));
}

void
mpq_neg (mpq_ptr r, mpq_srcptr q)
{
  mpz_neg (NUM(r), NUM(q));
  mpz_set (DEN(r), DEN(q));
}

void
mpq_set (mpq_ptr r, mpq_srcptr q)
{
  mpz_set (NUM(r), NUM(q));
  mpz_set (DEN(r), DEN(q));
}

void
mpq_set_ui (mpq_ptr r, unsigned long n, unsigned long d)
{
  mpz_set_ui (NUM(r), n);
  mpz_set_ui (DEN(r), d);
}

void
mpq_set_si (mpq_ptr r, signed long n, unsigned long d)
{
  mpz_set_si (NUM(r), n);
  mpz_set_ui (DEN(r), d);
}

void
mpq_set_z (mpq_ptr r, mpz_srcptr n)
{
  mpz_set (NUM(r), n);
  mpz_set_ui (DEN(r), 1);
}

void
mpq_set_num (mpq_ptr r, mpz_srcptr z)
{
  mpz_set (NUM(r), z);
}

void
mpq_set_den (mpq_ptr r, mpz_srcptr z)
{
  mpz_set (DEN(r), z);
}

void
mpq_get_num (mpz_ptr r, mpq_srcptr q)
{
  mpz_set (r, NUM(q));
}

void
mpq_get_den (mpz_ptr r, mpq_srcptr q)
{
  mpz_set (r, DEN(q));
}

void
mpq_swap (mpq_ptr a, mpq_ptr b)
{
  mpz_swap (NUM(a), NUM(b));
  mpz_swap (DEN(a), DEN(b));
}

void
mpq_add (mpq_ptr r, mpq_srcptr a, mpq_srcptr b)
{
  mpz_t t;

  mpz_init (t);
  mpz_mul (t, NUM(a), DEN(b));
  mpz_addmul (t, NUM(b), DEN(a));
  mpz_mul (DEN(r), DEN(a), DEN(b));
  mpz_swap (NUM(r), t);
  __mpq_helper_canonicalize (r, t);
  mpz_clear (t);
}

void
mpq_sub (mpq_ptr r, mpq_srcptr a, mpq_srcptr b)
{
  mpz_t t;

  mpz_init (t);
  mpz_mul (t, NUM(a), DEN(b));
  mpz_submul (t, NUM(b), DEN(a));
  mpz_mul (DEN(r), DEN(a), DEN(b));
  mpz_swap (NUM(r), t);
  __mpq_helper_canonicalize (r, t);
  mpz_clear (t);
}

void
mpq_mul (mpq_ptr r, mpq_srcptr a, mpq_srcptr b)
{
  mpz_t t;

  mpz_init (t);
  mpz_mul (t, NUM(a), DEN(b));
  mpz_mul (DEN(r), DEN(a), NUM(b));
  mpz_swap (NUM(r), t);
  __mpq_helper_canonicalize (r, t);
  mpz_clear (t);
}

void
mpq_div (mpq_ptr r, mpq_srcptr a, mpq_srcptr b)
{
  mpz_mul (NUM(r), NUM(a), NUM(b));
  mpz_mul (DEN(r), DEN(a), DEN(b));
  mpq_canonicalize (r);
}

void
mpq_div_2exp (mpq_ptr r, mpq_srcptr q, mp_bitcnt_t e)
{
  mpz_mul_2exp (DEN (r), DEN(q), e);
  mpz_set (NUM (r), NUM(q));
  mpq_canonicalize (r);
}

void
mpq_mul_2exp (mpq_ptr r, mpq_srcptr q, mp_bitcnt_t e)
{
  mpz_mul_2exp (NUM (r), NUM(q), e);
  mpz_set (DEN (r), DEN(q));
  mpq_canonicalize (r);
}

void
mpq_inv (mpq_ptr r, mpq_srcptr q)
{
  mpq_set (r, q);
  mpz_swap (DEN(r), NUM(r));
  __mpq_canonical_sign (r);
}

int
mpq_cmp (mpq_srcptr a, mpq_srcptr b)
{
  mpz_t t1, t2;
  int res;

  mpz_init (t1);
  mpz_init (t2);
  mpz_mul (t1, NUM(a), DEN(b));
  mpz_mul (t2, NUM(b), DEN(a));
  res = mpz_cmp (t1, t2);
  mpz_clear (t1);
  mpz_clear (t2);
}

int
mpq_cmp_z (mpq_srcptr a, mpz_srcptr b)
{
  mpz_t t;
  int res;

  mpz_init (t);
  mpz_mul (t, b, DEN(a));
  res = mpz_cmp (NUM(a), t);
  mpz_clear (t);
}

int
mpq_equal (mpq_srcptr a, mpq_srcptr b)
{
  return (mpz_cmp (NUM(a), NUM(b)) == 0) &&
    (mpz_cmp (DEN(a), DEN(b)) == 0);
}

int
_mpq_cmp_ui (mpq_srcptr q, unsigned long int n, unsigned long int d)
{
  mpq_t t;
  int res;
  
  mpq_init (t);
  mpq_set_ui (t, n, d);
  res = mpq_cmp (q, t);
  mpq_clear (t);
  return res;
}

int
_mpq_cmp_si (mpq_srcptr q, signed long int n, unsigned long int d)
{
  mpq_t t;
  int res;
  
  mpq_init (t);
  mpq_set_si (t, n, d);
  res = mpq_cmp (q, t);
  mpq_clear (t);
  return res;
}
_______________________________________________
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel

Reply via email to