Alternative bernoulli(const numeric &)

Markus Nullmeier markus.nullmeier at urz.uni-heidelberg.de
Fri Jan 18 15:44:36 CET 2002


Hello,

being unware of GiNaC's implemetation, I wrote my own
Bernoulli number function after reading Peter Stone's
straightforward description in his Maple Worksheet
http://minyos.its.rmit.edu.au/~e05254/MAPLE/ENGMATH/TAYLOR/BERNUM.MWS

Later I adapted my function to bernoulli() in numeric.cpp, as it
turned out to be about twice as fast as GiNaC 1.0.3 (gcc 2.95, -O2).

Thus maybe you'll find the enclosed patch useful in some
way or the other. Hopefully no hidden bugs remain.

Markus


--- GiNaC-1.0.3/ginac/numeric.cpp	Wed Dec 19 12:11:46 2001
+++ GiNaC-1.0.3_new_bernoulli/ginac/numeric.cpp	Fri Jan 18 14:44:16 2002
@@ -1512,7 +1512,7 @@
 	// But if somebody works with the n'th Bernoulli number she is likely to
 	// also need all previous Bernoulli numbers. So we need a complete remember
 	// table and above divide and conquer algorithm is not suited to build one
-	// up.  The code below is adapted from Pari's function bernvec().
+	// up.
 	// 
 	// (There is an interesting relation with the tangent polynomials described
 	// in `Concrete Mathematics', which leads to a program twice as fast as our
@@ -1520,38 +1520,38 @@
 	// addition to the remember table.  This doubles the memory footprint so
 	// we don't use it.)
 	
+	unsigned n = nn.to_int();
+
 	// the special cases not covered by the algorithm below
-	if (nn.is_equal(_num1))
-		return _num_1_2;
-	if (nn.is_odd())
-		return _num0;
-	
+	if (n & 1)
+		return (n == 1) ? _num_1_2 : _num0;
+	if (!n)
+		return _num1;
+
 	// store nonvanishing Bernoulli numbers here
 	static std::vector< cln::cl_RA > results;
-	static int highest_result = 0;
-	// algorithm not applicable to B(0), so just store it
-	if (results.empty())
-		results.push_back(cln::cl_RA(1));
-	
-	int n = nn.to_long();
-	for (int i=highest_result; i<n/2; ++i) {
-		cln::cl_RA B = 0;
-		long n = 8;
-		long m = 5;
-		long d1 = i;
-		long d2 = 2*i-1;
-		for (int j=i; j>0; --j) {
-			B = cln::cl_I(n*m) * (B+results[j]) / (d1*d2);
-			n += 4;
-			m += 2;
-			d1 -= 1;
-			d2 -= 2;
-		}
-		B = (1 - ((B+1)/(2*i+3))) / (cln::cl_I(1)<<(2*i+2));
-		results.push_back(B);
-		++highest_result;
-	}
-	return results[n/2];
+	static unsigned next_r = 0;
+
+	// algorithm not applicable to B(2), so just store it
+	if (!next_r) {
+		results.push_back(cln::recip(cln::cl_RA(6)));
+		next_r = 4;
+	} 
+	for (unsigned p = next_r; p <= n;  p += 2) {
+		cln::cl_I  c = 1;
+		cln::cl_RA b = cln::cl_RA(1-p)/2;
+		unsigned p3 = p+3;
+		unsigned p2 = p+2;
+		unsigned pm = p-2;
+		unsigned i, k;
+		for (i=2, k=0; i <= pm; i += 2, k++) {
+			c = cln::exquo(c * ((p3 - i)*(p2 - i)), (i - 1)*i);
+			b = b + c * results[k];
+		} 
+		results.push_back(- b / (p + 1));
+		next_r += 2;
+	} 
+	return results[n/2 - 1];
 }
 
 



More information about the GiNaC-devel mailing list