diff options
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | doc/gmp.texi | 2 | ||||
-rw-r--r-- | gmpxx.h | 27 | ||||
-rw-r--r-- | tests/cxx/t-ops2.cc | 9 |
5 files changed, 44 insertions, 5 deletions
@@ -1,6 +1,6 @@ 2015-11-08 Marc Glisse <marc.glisse@inria.fr> - * gmpxx.h (__gmp_fac_function): New class. + * gmpxx.h (__gmp_fac_function, __gmp_primorial_function): New classes. (__GMPP_DECLARE_UNARY_STATIC_MEMFUN, __GMPNN_DECLARE_UNARY_STATIC_MEMFUN, __GMPNS_DECLARE_UNARY_STATIC_MEMFUN, @@ -13,11 +13,12 @@ __GMPNU_DEFINE_UNARY_STATIC_MEMFUN, __GMPND_DEFINE_UNARY_STATIC_MEMFUN, __GMPN_DEFINE_UNARY_STATIC_MEMFUN, __GMP_DEFINE_UNARY_STATIC_MEMFUN): New macros. - (factorial, mpz_class::factorial): New functions. - * tests/cxx/t-ops2.cc: Test factorial. + (factorial, mpz_class::factorial, primorial, mpz_class::primorial): + New functions. + * tests/cxx/t-ops2.cc: Test factorial and primorial. * tests/cxx/Makefile.am: Move t-ops2 after t-do-exceptions-work-at-all-with-this-compiler. - * doc/gmp.texi: Document factorial. + * doc/gmp.texi: Document factorial and primorial. * NEWS: Likewise. 2015-11-07 Marc Glisse <marc.glisse@inria.fr> @@ -7,7 +7,7 @@ medium, provided this notice is preserved. Changes between GMP version 6.1.* and 6.2.0 FEATURES - * New C++ function factorial for mpz_class. + * New C++ functions factorial and primorial for mpz_class. Changes between GMP version 6.0.* and 6.1.0 diff --git a/doc/gmp.texi b/doc/gmp.texi index d4a9c60fe..81246ef89 100644 --- a/doc/gmp.texi +++ b/doc/gmp.texi @@ -6865,6 +6865,8 @@ mpz_fdiv_q (q.get_mpz_t(), a.get_mpz_t(), d.get_mpz_t()); @deftypefunx mpz_class lcm (mpz_class @var{op1}, mpz_class @var{op2}) @deftypefunx mpz_class mpz_class::factorial (type @var{op}) @deftypefunx mpz_class factorial (mpz_class @var{op}) +@deftypefunx mpz_class mpz_class::primorial (type @var{op}) +@deftypefunx mpz_class primorial (mpz_class @var{op}) @maybepagebreak @deftypefunx void mpz_class::swap (mpz_class& @var{op}) @deftypefunx void swap (mpz_class& @var{op1}, mpz_class& @var{op2}) @@ -1216,6 +1216,30 @@ struct __gmp_fac_function { __GMPXX_TMPZ_D; eval (z, temp); } }; +struct __gmp_primorial_function +{ + static void eval(mpz_ptr z, unsigned long l) { mpz_primorial_ui(z, l); } + static void eval(mpz_ptr z, signed long l) + { + if (l < 0) + mpz_set_ui(z, 1); + else + eval(z, static_cast<unsigned long>(l)); + } + static void eval(mpz_ptr z, mpz_srcptr w) + { + if (!mpz_fits_ulong_p(w)) + if (mpz_sgn(w) < 0) + mpz_set_ui(z, 1); + else + throw std::bad_alloc(); // or std::overflow_error ("factorial")? + else + eval(z, mpz_get_ui(w)); + } + static void eval(mpz_ptr z, double d) + { __GMPXX_TMPZ_D; eval (z, temp); } +}; + /**************** Auxiliary classes ****************/ @@ -1659,6 +1683,7 @@ public: __GMP_DECLARE_INCREMENT_OPERATOR(operator--) __GMP_DECLARE_UNARY_STATIC_MEMFUN(mpz_t, factorial, __gmp_fac_function) + __GMP_DECLARE_UNARY_STATIC_MEMFUN(mpz_t, primorial, __gmp_primorial_function) }; typedef __gmp_expr<mpz_t, mpz_t> mpz_class; @@ -3249,6 +3274,7 @@ __GMP_DEFINE_UNARY_FUNCTION_1(mpf_t, ceil, __gmp_ceil_function) __GMP_DEFINE_UNARY_FUNCTION_1(mpf_t, sqrt, __gmp_sqrt_function) __GMP_DEFINE_UNARY_FUNCTION_1(mpz_t, sqrt, __gmp_sqrt_function) __GMP_DEFINE_UNARY_FUNCTION_1(mpz_t, factorial, __gmp_fac_function) +__GMP_DEFINE_UNARY_FUNCTION_1(mpz_t, primorial, __gmp_primorial_function) __GMP_DEFINE_BINARY_FUNCTION_1(mpf_t, hypot, __gmp_hypot_function) __GMP_DEFINE_BINARY_FUNCTION_1(mpz_t, gcd, __gmp_gcd_function) __GMP_DEFINE_BINARY_FUNCTION_1(mpz_t, lcm, __gmp_lcm_function) @@ -3279,6 +3305,7 @@ __GMPZ_DEFINE_INCREMENT_OPERATOR(operator++, __gmp_unary_increment) __GMPZ_DEFINE_INCREMENT_OPERATOR(operator--, __gmp_unary_decrement) __GMP_DEFINE_UNARY_STATIC_MEMFUN(mpz_t, mpz_class::factorial, __gmp_fac_function) +__GMP_DEFINE_UNARY_STATIC_MEMFUN(mpz_t, mpz_class::primorial, __gmp_primorial_function) // member operators for mpq_class diff --git a/tests/cxx/t-ops2.cc b/tests/cxx/t-ops2.cc index ac8ea0d65..1403b4ab8 100644 --- a/tests/cxx/t-ops2.cc +++ b/tests/cxx/t-ops2.cc @@ -158,6 +158,15 @@ void checkz (){ catch (std::domain_error) {} try { ret=factorial(mpz_class(1)<<300); ASSERT_ALWAYS(0); } catch (std::bad_alloc) {} + ASSERT_ALWAYS(mpz_class::primorial(mpz_class(3))==6); + ASSERT_ALWAYS(mpz_class::primorial(mpz_class(2)*2)==6); + ASSERT_ALWAYS(mpz_class::primorial(3)==6); + ASSERT_ALWAYS(mpz_class::primorial(3ul)==6); + ASSERT_ALWAYS(mpz_class::primorial(3.f)==6); + ASSERT_ALWAYS(mpz_class::primorial(-mpz_class(3))==1); + ASSERT_ALWAYS(mpz_class::primorial(-5)==1); + try { ret=primorial(mpz_class(1)<<300); ASSERT_ALWAYS(0); } + catch (std::bad_alloc) {} } template<class T> |