ni...@lysator.liu.se (Niels Möller) writes: > Another revision, this time as a patch. As you can see, I renamed things > a bit more. Compile tested only...
New patch below, including some testcases (no tests for mpz_roinit_n and MPZ_ROINIT_N though). I'd like to check this in now. Any objections? While writing the tests, I discovered some additional things I miss. See tests/mpz/t-limbs.c, the alt_mul function. IT would be useful to have a function to allocate a new limb array (using gmp:s alloc function), and use that later to replace the limb array in an mpz. Useful for inplace operations, where the underlying mpn function can't work in-place. Then it's desirable to pass the old limb array as input, and the newly allocated array as output, and replace when done. Regards, /Niels diff -r 32f62aca5666 Makefile.am --- a/Makefile.am Thu Feb 21 11:03:04 2013 +0100 +++ b/Makefile.am Sat Feb 23 17:38:59 2013 +0100 @@ -174,7 +174,9 @@ MPZ_OBJECTS = mpz/abs$U.lo mpz/add$U.lo mpz/ior$U.lo mpz/iset$U.lo mpz/iset_d$U.lo mpz/iset_si$U.lo \ mpz/iset_str$U.lo mpz/iset_ui$U.lo mpz/jacobi$U.lo mpz/kronsz$U.lo \ mpz/kronuz$U.lo mpz/kronzs$U.lo mpz/kronzu$U.lo \ - mpz/lcm$U.lo mpz/lcm_ui$U.lo mpz/lucnum_ui$U.lo mpz/lucnum2_ui$U.lo \ + mpz/lcm$U.lo mpz/lcm_ui$U.lo mpz/limbs_finish$U.lo \ + mpz/limbs_modify$U.lo mpz/limbs_read$U.lo mpz/limbs_write.lo \ + mpz/lucnum_ui$U.lo mpz/lucnum2_ui$U.lo \ mpz/millerrabin$U.lo mpz/mod$U.lo mpz/mul$U.lo mpz/mul_2exp$U.lo \ mpz/mul_si$U.lo mpz/mul_ui$U.lo \ mpz/n_pow_ui$U.lo mpz/neg$U.lo mpz/nextprime$U.lo \ @@ -182,7 +184,7 @@ MPZ_OBJECTS = mpz/abs$U.lo mpz/add$U.lo mpz/popcount$U.lo mpz/pow_ui$U.lo mpz/powm$U.lo mpz/powm_sec$U.lo \ mpz/powm_ui$U.lo mpz/primorial_ui$U.lo \ mpz/pprime_p$U.lo mpz/random$U.lo mpz/random2$U.lo \ - mpz/realloc$U.lo mpz/realloc2$U.lo mpz/remove$U.lo \ + mpz/realloc$U.lo mpz/realloc2$U.lo mpz/remove$U.lo mpz/roinit_n$U.lo \ mpz/root$U.lo mpz/rootrem$U.lo mpz/rrandomb$U.lo mpz/scan0$U.lo \ mpz/scan1$U.lo mpz/set$U.lo mpz/set_d$U.lo mpz/set_f$U.lo \ mpz/set_q$U.lo mpz/set_si$U.lo mpz/set_str$U.lo mpz/set_ui$U.lo \ diff -r 32f62aca5666 gmp-h.in --- a/gmp-h.in Thu Feb 21 11:03:04 2013 +0100 +++ b/gmp-h.in Sat Feb 23 17:38:59 2013 +0100 @@ -1117,6 +1117,22 @@ using std::FILE; #define mpz_eor __gmpz_xor __GMP_DECLSPEC void mpz_xor (mpz_ptr, mpz_srcptr, mpz_srcptr); +#define mpz_limbs_read __gmpz_limbs_read +__GMP_DECLSPEC mp_srcptr mpz_limbs_read (mpz_srcptr); + +#define mpz_limbs_write __gmpz_limbs_write +__GMP_DECLSPEC mp_ptr mpz_limbs_write (mpz_ptr, mp_size_t); + +#define mpz_limbs_modify __gmpz_limbs_modify +__GMP_DECLSPEC mp_ptr mpz_limbs_modify (mpz_ptr, mp_size_t); + +#define mpz_limbs_finish __gmpz_limbs_finish +__GMP_DECLSPEC void mpz_limbs_finish (mpz_ptr, mp_size_t); + +#define mpz_roinit_n __gmpz_roinit_n +__GMP_DECLSPEC mpz_srcptr mpz_roinit_n (mpz_ptr, mp_srcptr, mp_size_t); + +#define MPZ_ROINIT_N(xp, xs) {{0, (xs),(xp) }} /**************** Rational (i.e. Q) routines. ****************/ diff -r 32f62aca5666 mpz/Makefile.am --- a/mpz/Makefile.am Thu Feb 21 11:03:04 2013 +0100 +++ b/mpz/Makefile.am Sat Feb 23 17:38:59 2013 +0100 @@ -43,12 +43,13 @@ libmpz_la_SOURCES = aors.h aors_ui.h fit import.c init.c init2.c inits.c inp_raw.c inp_str.c \ invert.c ior.c iset.c iset_d.c iset_si.c iset_str.c iset_ui.c \ jacobi.c kronsz.c kronuz.c kronzs.c kronzu.c \ - lcm.c lcm_ui.c lucnum_ui.c lucnum2_ui.c mfac_uiui.c millerrabin.c \ + lcm.c lcm_ui.c limbs_read.c limbs_write.c limbs_modify.c limbs_finish.c \ + lucnum_ui.c lucnum2_ui.c mfac_uiui.c millerrabin.c \ mod.c mul.c mul_2exp.c mul_si.c mul_ui.c n_pow_ui.c neg.c nextprime.c \ oddfac_1.c \ out_raw.c out_str.c perfpow.c perfsqr.c popcount.c pow_ui.c powm.c \ powm_sec.c powm_ui.c pprime_p.c prodlimbs.c primorial_ui.c random.c random2.c \ - realloc.c realloc2.c remove.c root.c rootrem.c rrandomb.c \ + realloc.c realloc2.c remove.c roinit_n.c root.c rootrem.c rrandomb.c \ scan0.c scan1.c set.c set_d.c set_f.c set_q.c set_si.c set_str.c \ set_ui.c setbit.c size.c sizeinbase.c sqrt.c sqrtrem.c sub.c sub_ui.c \ swap.c tdiv_ui.c tdiv_q.c tdiv_q_2exp.c tdiv_q_ui.c tdiv_qr.c \ diff -r 32f62aca5666 mpz/limbs_finish.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mpz/limbs_finish.c Sat Feb 23 17:38:59 2013 +0100 @@ -0,0 +1,29 @@ +/* mpz_finish_limbs -- Update mpz after writing to the limb array. + +Copyright 2013 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 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 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 Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +mpz_limbs_finish (mpz_ptr x, mp_size_t xs) +{ + mp_size_t xn = ABS(xs); + MPN_NORMALIZE (PTR (x), xn); + SIZ (x) = xs < 0 ? -xn : xn; +} diff -r 32f62aca5666 mpz/limbs_modify.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mpz/limbs_modify.c Sat Feb 23 17:38:59 2013 +0100 @@ -0,0 +1,28 @@ +/* mpz_limbs_modify -- Read-and-modify access to the mpn-style limb array. + +Copyright 2013 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 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 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 Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */ + +#include "gmp.h" +#include "gmp-impl.h" + +mp_ptr +mpz_limbs_modify (mpz_ptr x, mp_size_t n) +{ + ASSERT (n > 0); + return MPZ_REALLOC (x, n); +} diff -r 32f62aca5666 mpz/limbs_read.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mpz/limbs_read.c Sat Feb 23 17:38:59 2013 +0100 @@ -0,0 +1,27 @@ +/* mpz_limbs_read -- Read access to the mpn-style limb array. + +Copyright 2013 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 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 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 Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */ + +#include "gmp.h" +#include "gmp-impl.h" + +mp_srcptr +mpz_limbs_read (mpz_srcptr x) +{ + return PTR(x); +} diff -r 32f62aca5666 mpz/limbs_write.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mpz/limbs_write.c Sat Feb 23 17:38:59 2013 +0100 @@ -0,0 +1,28 @@ +/* mpz_limbs_write -- Write access to the mpn-style limb array. + +Copyright 2013 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 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 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 Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */ + +#include "gmp.h" +#include "gmp-impl.h" + +mp_ptr +mpz_limbs_write (mpz_ptr x, mp_size_t n) +{ + ASSERT (n > 0); + return MPZ_NEWALLOC (x, n); +} diff -r 32f62aca5666 mpz/roinit_n.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mpz/roinit_n.c Sat Feb 23 17:38:59 2013 +0100 @@ -0,0 +1,30 @@ +/* mpz_roinit_n -- Initialize mpz with read-only limb array. + +Copyright 2013 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 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 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 Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */ + +#include "gmp.h" +#include "gmp-impl.h" + +mpz_srcptr +mpz_roinit_n (mpz_ptr x, mp_srcptr xp, mp_size_t xs) +{ + ALLOC (x) = 0; + SIZ (x) = xs; + PTR (x) = xp; + return x; +} diff -r 32f62aca5666 tests/mpz/Makefile.am --- a/tests/mpz/Makefile.am Thu Feb 21 11:03:04 2013 +0100 +++ b/tests/mpz/Makefile.am Sat Feb 23 17:38:59 2013 +0100 @@ -30,7 +30,7 @@ check_PROGRAMS = t-addsub t-cmp t-mul t- t-fac_ui t-mfac_uiui t-primorial_ui t-fib_ui t-lucnum_ui t-scan t-fits \ t-divis t-divis_2exp t-cong t-cong_2exp t-sizeinbase t-set_str \ t-aorsmul t-cmp_d t-cmp_si t-hamdist t-oddeven t-popcount t-set_f \ - t-io_raw t-import t-export t-pprime_p t-nextprime t-remove + t-io_raw t-import t-export t-pprime_p t-nextprime t-remove t-limbs TESTS = $(check_PROGRAMS) diff -r 32f62aca5666 tests/mpz/t-limbs.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/mpz/t-limbs.c Sat Feb 23 17:38:59 2013 +0100 @@ -0,0 +1,171 @@ +/* Test mpz_limbs_* functions + +Copyright 2013 Free Software Foundation, Inc. + +This file is part of the GNU MP Library test suite. + +The GNU MP Library test suite 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 3 of the License, +or (at your option) any later version. + +The GNU MP Library test suite 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 +the GNU MP Library test suite. If not, see http://www.gnu.org/licenses/. */ + +#include <stdlib.h> +#include <stdio.h> + +#include "gmp.h" +#include "gmp-impl.h" +#include "tests.h" + +#define COUNT 100 +#define BITSIZE 500 + +/* Like mpz_add. For simplicity, support positive inputs only. */ +static void +alt_add (mpz_ptr r, mpz_srcptr a, mpz_srcptr b) +{ + mp_size_t an = mpz_size (a); + mp_size_t bn = mpz_size (b); + mp_ptr rp; + + ASSERT (an > 0); + ASSERT (bn > 0); + if (an < bn) + { + MP_SIZE_T_SWAP (an, bn); + MPZ_SRCPTR_SWAP (a, b); + } + rp = mpz_limbs_modify (r, an + 1); + rp[an] = mpn_add (rp, mpz_limbs_read (a), an, mpz_limbs_read (b), bn); + mpz_limbs_finish (r, an + 1); +} + +static void +check_funcs (const char *name, + void (*f)(mpz_ptr, mpz_srcptr, mpz_srcptr), + void (*ref_f)(mpz_ptr, mpz_srcptr, mpz_srcptr), + mpz_srcptr a, mpz_srcptr b) +{ + mpz_t r, ref; + mpz_inits (r, ref, NULL); + + ref_f (ref, a, b); + MPZ_CHECK_FORMAT (ref); + f (r, a, b); + MPZ_CHECK_FORMAT (r); + + if (mpz_cmp (r, ref) != 0) + { + printf ("%s failed, abits %u, bbits %u\n", + (unsigned) mpz_sizeinbase (a, 2), + (unsigned) mpz_sizeinbase (b, 2)); + gmp_printf ("a = %Zx\n", a); + gmp_printf ("b = %Zx\n", b); + gmp_printf ("r = %Zx (bad)\n", r); + gmp_printf ("ref = %Zx\n", ref); + } + mpz_clears (r, ref, NULL); +} + +static void +check_add (void) +{ + gmp_randstate_ptr rands = RANDS; + mpz_t bs, a, b; + unsigned i; + mpz_inits (bs, a, b, NULL); + for (i = 0; i < COUNT; i++) + { + mpz_rrandomb (bs, rands, 32); + mpz_rrandomb (a, rands, 1 + mpz_get_ui (bs) % BITSIZE); + mpz_rrandomb (bs, rands, 32); + mpz_rrandomb (b, rands, 1 + mpz_get_ui (bs) % BITSIZE); + + check_funcs ("add", alt_add, mpz_add, a, b); + } + mpz_clears (bs, a, b, NULL); +} + +static void +alt_mul (mpz_ptr r, mpz_srcptr a, mpz_srcptr b) +{ + mp_size_t an = mpz_size (a); + mp_size_t bn = mpz_size (b); + mp_srcptr ap, bp; + mp_ptr rp; + TMP_DECL; + + TMP_MARK; + + ASSERT (an > 0); + ASSERT (bn > 0); + if (an < bn) + { + MP_SIZE_T_SWAP (an, bn); + MPZ_SRCPTR_SWAP (a, b); + } + /* NOTE: This copying seems unnecessary; better to allocate new + result area, and free the old area when done. */ + if (r == a) + { + mp_ptr tp = TMP_ALLOC_LIMBS (an); + MPN_COPY (tp, mpz_limbs_read (a), an); + ap = tp; + bp = (a == b) ? ap : mpz_limbs_read (b); + } + else if (r == b) + { + mp_ptr tp = TMP_ALLOC_LIMBS (bn); + MPN_COPY (tp, mpz_limbs_read (b), bn); + bp = tp; + ap = mpz_limbs_read (a); + } + else + { + ap = mpz_limbs_read (a); + bp = mpz_limbs_read (b); + } + mpn_mul (mpz_limbs_write (r, an + bn), + ap, an, bp, bn); + + mpz_limbs_finish (r, an + bn); +} + +void +check_mul (void) +{ + gmp_randstate_ptr rands = RANDS; + mpz_t bs, a, b, r, ref; + unsigned i; + mpz_inits (bs, a, b, NULL); + for (i = 0; i < COUNT; i++) + { + mpz_rrandomb (bs, rands, 32); + mpz_rrandomb (a, rands, 1 + mpz_get_ui (bs) % BITSIZE); + mpz_rrandomb (bs, rands, 32); + mpz_rrandomb (b, rands, 1 + mpz_get_ui (bs) % BITSIZE); + + check_funcs ("mul", alt_mul, mpz_mul, a, b); + } + mpz_clears (bs, a, b, NULL); +} + +int +main (int argc, char *argv[]) +{ + tests_start (); + tests_end (); + + check_add (); + check_mul (); + + return 0; + +} -- Niels Möller. PGP-encrypted email is preferred. Keyid C0B98E26. Internet email is subject to wholesale government surveillance. _______________________________________________ gmp-devel mailing list gmp-devel@gmplib.org http://gmplib.org/mailman/listinfo/gmp-devel