summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Glisse <marc.glisse@inria.fr>2015-11-12 07:00:04 +0100
committerMarc Glisse <marc.glisse@inria.fr>2015-11-12 07:00:04 +0100
commitad4ce78ca479da52138dc2b4ad3ea3b08a7e9080 (patch)
treea5d77489d93388dacb558a8df8f5a0ec0d7a8dd6
parentbd5a7c516b870f1014c849dfb20f883912eb37c4 (diff)
downloadgmp-ad4ce78ca479da52138dc2b4ad3ea3b08a7e9080.tar.gz
New C++ function fibonacci.
-rw-r--r--ChangeLog8
-rw-r--r--doc/gmp.texi2
-rw-r--r--gmpxx.h47
-rw-r--r--tests/cxx/t-ops2z.cc9
4 files changed, 58 insertions, 8 deletions
diff --git a/ChangeLog b/ChangeLog
index 801a4203b..be78744c3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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})
diff --git a/gmpxx.h b/gmpxx.h
index e4b26dd2c..bf36b9aca 100644
--- a/gmpxx.h
+++ b/gmpxx.h
@@ -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