Files
RedBear-OS/recipes/libs/libmpfr/source/src/mpfr-mini-gmp.c
T
vasilito ff4ff35918 feat: track all source trees in git — full fork offline-first model
Red Bear OS is a full fork. All sources must be available from git clone
with zero network access. Removed gitignore rules that excluded fetched
source trees under recipes/*/source/, local/recipes/kde/*/source/,
local/recipes/qt/*/source/, and vendor source trees.

Build artifacts (target/, build/, source.tar, *.o, *.so) remain excluded.

127291 files added — kernel, relibc, base, bootloader, pkgar, all KDE/Qt
frameworks, mesa, wayland, DRM drivers, and every other recipe source.
2026-05-14 10:55:53 +01:00

319 lines
7.9 KiB
C

/* mpfr-mini-gmp.c -- Interface functions for mini-gmp.
Copyright 2014-2025 Free Software Foundation, Inc.
Contributed by the Pascaline and Caramba projects, INRIA.
This file is part of the GNU MPFR Library.
The GNU MPFR Library is free software; you can redistribute it and/or modify
it under the terms of 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.
The GNU MPFR 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 Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the GNU MPFR Library; see the file COPYING.LESSER.
If not, see <https://www.gnu.org/licenses/>. */
/* The following include will do 2 things: include the config.h
if there is one (as it may define MPFR_USE_MINI_GMP), and avoid
an empty translation unit (see ISO C99, 6.9). */
#include "mpfr-impl.h"
#ifdef MPFR_USE_MINI_GMP
/************************ random generation functions ************************/
#ifdef WANT_gmp_randinit_default
void
gmp_randinit_default (gmp_randstate_t state)
{
}
#endif
#ifdef WANT_gmp_randseed_ui
void
gmp_randseed_ui (gmp_randstate_t state, unsigned long int seed)
{
/* Note: We possibly ignore the high-order bits of seed. One should take
that into account when setting GMP_CHECK_RANDOMIZE for the tests. */
srand ((unsigned int) seed);
}
#endif
#ifdef WANT_gmp_randclear
void
gmp_randclear (gmp_randstate_t state)
{
}
#endif
#ifdef WANT_gmp_randinit_set
void
gmp_randinit_set (gmp_randstate_t s1, gmp_randstate_t s2)
{
}
#endif
static unsigned int
rand15 (void)
{
/* With a good PRNG, we could use "rand () % 32768", but let's choose
the following from <https://c-faq.com/lib/randrange.html>. Note that
on most platforms, the compiler should generate a shift. */
return rand () / (RAND_MAX / 32768 + 1);
}
static mp_limb_t
random_limb (void)
{
mp_limb_t r = 0;
int i = GMP_NUMB_BITS;
while (i > 0)
{
r = (r << 15) | rand15 ();
i -= 15;
}
return r;
}
#ifdef WANT_mpz_urandomb
void
mpz_urandomb (mpz_t rop, gmp_randstate_t state, mp_bitcnt_t nbits)
{
unsigned long n, i;
mpz_realloc2 (rop, nbits);
n = (nbits - 1) / GMP_NUMB_BITS + 1; /* number of limbs */
for (i = n; i-- > 0;)
rop->_mp_d[i] = random_limb ();
i = n * GMP_NUMB_BITS - nbits;
/* mask the upper i bits */
if (i)
rop->_mp_d[n-1] = MPFR_LIMB_LSHIFT(rop->_mp_d[n-1], i) >> i;
while (n > 0 && (rop->_mp_d[n-1] == 0))
n--;
rop->_mp_size = n;
}
#endif
#ifdef WANT_gmp_urandomm_ui
/* generates a random unsigned long */
static unsigned long
random_ulong (void)
{
#ifdef MPFR_LONG_WITHIN_LIMB
/* we assume a limb and an unsigned long have both a number of different
values that is a power of two, thus when we cast a random limb into
an unsigned long, we still get an uniform distribution */
return random_limb ();
#else
/* with the same assumption as above, we need to generate as many random
limbs needed to "fill" an unsigned long */
unsigned long u, v;
v = MPFR_LIMB_MAX;
u = random_limb ();
while (v < ULONG_MAX)
{
v = (v << GMP_NUMB_BITS) + MPFR_LIMB_MAX;
u = (u << GMP_NUMB_BITS) + random_limb ();
}
return u;
#endif
}
unsigned long
gmp_urandomm_ui (gmp_randstate_t state, unsigned long n)
{
unsigned long p, q, r;
MPFR_ASSERTN (n > 0);
p = random_ulong (); /* p is in [0, ULONG_MAX], thus p is uniform among
ULONG_MAX+1 values */
q = n * (ULONG_MAX / n);
r = ULONG_MAX % n;
if (r != n - 1) /* ULONG_MAX+1 is not multiple of n, will happen whenever
n is not a power of two */
while (p >= q)
p = random_ulong ();
return p % n;
}
#endif
#ifdef WANT_gmp_urandomb_ui
unsigned long
gmp_urandomb_ui (gmp_randstate_t state, unsigned long n)
{
#ifdef MPFR_LONG_WITHIN_LIMB
/* Since n may be equal to the width of unsigned long,
we must not shift 1UL by n as this may be UB. */
return n == 0 ? 0 : random_limb () & (((1UL << (n - 1)) << 1) - 1);
#else
unsigned long res = 0;
int m = n; /* remaining bits to generate */
while (m >= GMP_NUMB_BITS)
{
/* we can generate a full limb */
res = (res << GMP_NUMB_BITS) | (unsigned long) random_limb ();
m -= GMP_NUMB_BITS;
}
MPFR_ASSERTD (m < GMP_NUMB_BITS); /* thus m < width(unsigned long) */
if (m != 0) /* generate m extra bits */
res = (res << m) | (unsigned long) (random_limb () % (1UL << m));
return res;
#endif
}
#endif
/************************* division functions ********************************/
#ifdef WANT_mpn_divrem_1
mp_limb_t
mpn_divrem_1 (mp_limb_t *qp, mp_size_t qxn, mp_limb_t *np, mp_size_t nn,
mp_limb_t d0)
{
mpz_t q, r, n, d;
mp_limb_t ret, dd[1];
d->_mp_d = dd;
d->_mp_d[0] = d0;
d->_mp_size = 1;
mpz_init (q);
mpz_init (r);
if (qxn == 0)
{
n->_mp_d = np;
n->_mp_size = nn;
}
else
{
mpz_init2 (n, (nn + qxn) * GMP_NUMB_BITS);
mpn_copyi (n->_mp_d + qxn, np, nn);
mpn_zero (n->_mp_d, qxn);
n->_mp_size = nn + qxn;
}
mpz_tdiv_qr (q, r, n, d);
if (q->_mp_size > 0)
mpn_copyi (qp, q->_mp_d, q->_mp_size);
if (q->_mp_size < nn + qxn)
mpn_zero (qp + q->_mp_size, nn + qxn - q->_mp_size);
ret = (r->_mp_size == 1) ? r->_mp_d[0] : 0;
mpz_clear (q);
mpz_clear (r);
if (qxn != 0)
mpz_clear (n);
return ret;
}
#endif
#ifdef WANT_mpn_divrem
mp_limb_t
mpn_divrem (mp_limb_t *qp, mp_size_t qn, mp_limb_t *np,
mp_size_t nn, const mp_limb_t *dp, mp_size_t dn)
{
mpz_t q, r, n, d;
mp_limb_t ret;
MPFR_ASSERTN(qn == 0);
qn = nn - dn;
n->_mp_d = np;
n->_mp_size = nn;
d->_mp_d = (mp_limb_t*) dp;
d->_mp_size = dn;
mpz_init (q);
mpz_init (r);
mpz_tdiv_qr (q, r, n, d);
MPFR_ASSERTN(q->_mp_size == qn || q->_mp_size == qn + 1);
mpn_copyi (qp, q->_mp_d, qn);
ret = (q->_mp_size == qn) ? 0 : q->_mp_d[qn];
if (r->_mp_size > 0)
mpn_copyi (np, r->_mp_d, r->_mp_size);
if (r->_mp_size < dn)
mpn_zero (np + r->_mp_size, dn - r->_mp_size);
mpz_clear (q);
mpz_clear (r);
return ret;
}
#endif
#ifdef WANT_mpn_tdiv_qr
void
mpn_tdiv_qr (mp_limb_t *qp, mp_limb_t *rp, mp_size_t qxn,
const mp_limb_t *np, mp_size_t nn,
const mp_limb_t *dp, mp_size_t dn)
{
mpz_t q, r, n, d;
MPFR_ASSERTN(qxn == 0);
n->_mp_d = (mp_limb_t*) np;
n->_mp_size = nn;
d->_mp_d = (mp_limb_t*) dp;
d->_mp_size = dn;
mpz_init (q);
mpz_init (r);
mpz_tdiv_qr (q, r, n, d);
MPFR_ASSERTN(q->_mp_size > 0);
mpn_copyi (qp, q->_mp_d, q->_mp_size);
if (q->_mp_size < nn - dn + 1)
mpn_zero (qp + q->_mp_size, nn - dn + 1 - q->_mp_size);
if (r->_mp_size > 0)
mpn_copyi (rp, r->_mp_d, r->_mp_size);
if (r->_mp_size < dn)
mpn_zero (rp + r->_mp_size, dn - r->_mp_size);
mpz_clear (q);
mpz_clear (r);
}
#endif
#if 0 /* this function is useful for debugging, thus please keep it here */
void
mpz_dump (mpz_t z)
{
mp_size_t n = z->_mp_size;
MPFR_STAT_STATIC_ASSERT ((GMP_NUMB_BITS % 4) == 0);
if (n == 0)
printf ("0");
else
{
int first = 1;
if (n < 0)
{
printf ("-");
n = -n;
}
while (n > 0)
{
if (first)
{
printf ("%lx", (unsigned long) z->_mp_d[n-1]);
first = 0;
}
else
{
char s[17];
int len;
sprintf (s, "%lx", (unsigned long) z->_mp_d[n-1]);
len = strlen (s);
/* one character should be printed for 4 bits */
while (len++ < GMP_NUMB_BITS / 4)
printf ("0");
printf ("%lx", (unsigned long) z->_mp_d[n-1]);
}
n--;
}
}
printf ("\n");
}
#endif
#endif /* MPFR_USE_MINI_GMP */