diff options
author | Marc Glisse <marc.glisse@inria.fr> | 2015-11-12 07:00:04 +0100 |
---|---|---|
committer | Marc Glisse <marc.glisse@inria.fr> | 2015-11-12 07:00:04 +0100 |
commit | ad4ce78ca479da52138dc2b4ad3ea3b08a7e9080 (patch) | |
tree | a5d77489d93388dacb558a8df8f5a0ec0d7a8dd6 | |
parent | bd5a7c516b870f1014c849dfb20f883912eb37c4 (diff) | |
download | gmp-ad4ce78ca479da52138dc2b4ad3ea3b08a7e9080.tar.gz |
New C++ function fibonacci.
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | doc/gmp.texi | 2 | ||||
-rw-r--r-- | gmpxx.h | 47 | ||||
-rw-r--r-- | tests/cxx/t-ops2z.cc | 9 |
4 files changed, 58 insertions, 8 deletions
@@ -1,3 +1,11 @@ +2015-11-12 Marc Glisse <marc.glisse@inria.fr> + + * gmpxx.h (__gmp_fibonacci_function): New class. + (fibonacci, mpz_class::fibonacci): New functions. + (__gmp_fac_function, __gmp_primorial_function): Add braces. + * tests/cxx/t-ops2z.cc: Test fibonacci. + * doc/gmp.texi: Document fibonacci. + 2015-11-10 Marc Glisse <marc.glisse@inria.fr> * gmpxx.h (__gmp_primorial_function): Throw on negative operands. diff --git a/doc/gmp.texi b/doc/gmp.texi index 81246ef89..91d935471 100644 --- a/doc/gmp.texi +++ b/doc/gmp.texi @@ -6867,6 +6867,8 @@ mpz_fdiv_q (q.get_mpz_t(), a.get_mpz_t(), d.get_mpz_t()); @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}) +@deftypefunx mpz_class mpz_class::fibonacci (type @var{op}) +@deftypefunx mpz_class fibonacci (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}) @@ -1206,10 +1206,12 @@ struct __gmp_fac_function static void eval(mpz_ptr z, mpz_srcptr w) { if (!mpz_fits_ulong_p(w)) - if (mpz_sgn(w) < 0) - throw std::domain_error ("factorial(negative)"); - else - throw std::bad_alloc(); // or std::overflow_error ("factorial")? + { + if (mpz_sgn(w) < 0) + throw std::domain_error ("factorial(negative)"); + else + throw std::bad_alloc(); // or std::overflow_error ("factorial")? + } eval(z, mpz_get_ui(w)); } static void eval(mpz_ptr z, double d) @@ -1228,16 +1230,42 @@ struct __gmp_primorial_function static void eval(mpz_ptr z, mpz_srcptr w) { if (!mpz_fits_ulong_p(w)) - if (mpz_sgn(w) < 0) - throw std::domain_error ("primorial(negative)"); - else - throw std::bad_alloc(); // or std::overflow_error ("primorial")? + { + if (mpz_sgn(w) < 0) + throw std::domain_error ("primorial(negative)"); + else + throw std::bad_alloc(); // or std::overflow_error ("primorial")? + } eval(z, mpz_get_ui(w)); } static void eval(mpz_ptr z, double d) { __GMPXX_TMPZ_D; eval (z, temp); } }; +struct __gmp_fib_function +{ + static void eval(mpz_ptr z, unsigned long l) { mpz_fib_ui(z, l); } + static void eval(mpz_ptr z, signed long l) + { + if (l < 0) + { + eval(z, -static_cast<unsigned long>(l)); + if ((l & 1) == 0) + mpz_neg(z, z); + } + else + eval(z, static_cast<unsigned long>(l)); + } + static void eval(mpz_ptr z, mpz_srcptr w) + { + if (!mpz_fits_slong_p(w)) + throw std::bad_alloc(); // or std::overflow_error ("fibonacci")? + eval(z, mpz_get_si(w)); + } + static void eval(mpz_ptr z, double d) + { __GMPXX_TMPZ_D; eval (z, temp); } +}; + /**************** Auxiliary classes ****************/ @@ -1682,6 +1710,7 @@ public: __GMP_DECLARE_UNARY_STATIC_MEMFUN(mpz_t, factorial, __gmp_fac_function) __GMP_DECLARE_UNARY_STATIC_MEMFUN(mpz_t, primorial, __gmp_primorial_function) + __GMP_DECLARE_UNARY_STATIC_MEMFUN(mpz_t, fibonacci, __gmp_fib_function) }; typedef __gmp_expr<mpz_t, mpz_t> mpz_class; @@ -3273,6 +3302,7 @@ __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_UNARY_FUNCTION_1(mpz_t, fibonacci, __gmp_fib_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) @@ -3304,6 +3334,7 @@ __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) +__GMP_DEFINE_UNARY_STATIC_MEMFUN(mpz_t, mpz_class::fibonacci, __gmp_fib_function) // member operators for mpq_class diff --git a/tests/cxx/t-ops2z.cc b/tests/cxx/t-ops2z.cc index a6ef7de3d..a51dd9fe5 100644 --- a/tests/cxx/t-ops2z.cc +++ b/tests/cxx/t-ops2z.cc @@ -105,6 +105,15 @@ void checkz (){ catch (std::domain_error) {} try { ret=primorial(mpz_class(1)<<300); ASSERT_ALWAYS(0); } catch (std::bad_alloc) {} + ASSERT_ALWAYS(mpz_class::fibonacci(mpz_class(6))==8); + ASSERT_ALWAYS(mpz_class::fibonacci(mpz_class(2)*2)==3); + ASSERT_ALWAYS(mpz_class::fibonacci(3)==2); + ASSERT_ALWAYS(mpz_class::fibonacci(3ul)==2); + ASSERT_ALWAYS(mpz_class::fibonacci(3.f)==2); + ASSERT_ALWAYS(fibonacci(-mpz_class(6))==-8); + ASSERT_ALWAYS(mpz_class::fibonacci(-3)==2); + try { ret=fibonacci(mpz_class(1)<<300); ASSERT_ALWAYS(0); } + catch (std::bad_alloc) {} } int |