[GiNaC-devel] [PATCH] Fix get_builtin_reader() and make it a bit simpler.

Alexei Sheplyakov varg at metalica.kh.ua
Mon Aug 10 21:22:52 CEST 2009


The code below seems to be too incorrect or at least too fragile

	enum {
		log,
		exp,
		// skipped
		NFUNCTIONS
	};
	std::vector<function_options>::const_iterator it =
		registered_functions_hack::get_registered_functions().begin();
	unsigned serial = 0;
	for ( ; serial<NFUNCTIONS; ++it, ++serial ) {
		prototype proto = make_pair(it->get_name(), it->get_nparams());
		reader[proto] = encode_serial_as_reader_func(serial);
	}

What happens if a user-defined function(s) get registered *before* "official"
ones (so serials of built-in functions won't start from 0)? This can easily
happen because the order of initialization in different compilation units is
implementation defined. Or someone adds a built-in function and inserts
REGISTER_FUNCTION_*P between REGISTER_FUNCTION_1P(log, ...) and
REGISTER_FUNCTION_1P(exp, ...)? Or compiler decides to swap
REGISTER_FUNCTION_1P(log, ...) and REGISTER_FUNCTION_1P(exp, ...)?

The fix is simple: don't fiddle with serials, use the old (pre 1.5.2)
approach, that is, let autogen produce the `reader functions' and use
them to make a prototype_table.

---
 ginac/parser/builtin_fcns.def   |   84 ++++++++++++++++++++++++++++++++++++++-
 ginac/parser/default_reader.tpl |   56 ++++----------------------
 2 files changed, 92 insertions(+), 48 deletions(-)

diff --git a/ginac/parser/builtin_fcns.def b/ginac/parser/builtin_fcns.def
index 96cd0a2..a7379d0 100644
--- a/ginac/parser/builtin_fcns.def
+++ b/ginac/parser/builtin_fcns.def
@@ -1,14 +1,96 @@
 Autogen definitions ginacfcns;
 
+function = { name = "log"; };
+function = { name = "exp"; };
+function = { name = "sin"; };
+function = { name = "cos"; };
+function = { name = "tan"; };
+function = { name = "asin"; };
+function = { name = "acos"; };
+function = { name = "atan"; };
+
+function = { name = "sinh"; };
+function = { name = "cosh"; };
+function = { name = "tanh"; };
+function = { name = "asinh"; };
+function = { name = "acosh"; };
+function = { name = "atanh"; };
+
+function = { 
+       name = "atan2";
+       args = 2;
+};
+
+function = { 
+       name = "Li2";
+       comment = "Dilogarithm";
+};
+
+function = {
+       name = "Li3";
+       comment = "Trilogarithm";
+};
+
+function = {
+       name = "zetaderiv";
+       comment = "Derivatives of Riemann's Zeta-function";
+       args = 2;
+};
+
+function = {
+       name = "Li";
+       args = 2;
+       comment = "Polylogarithm and multiple polylogarithm";
+};
+
+function = {
+       name =  "S";
+       args = 3;
+       comment = "Nielsen's generalized polylogarithm";
+};
+
+function = {
+       name =  "H";
+       args = 2;
+       comment = "Harmonic polylogarithm";
+};
+
+function = { name = "lgamma"; };
+function = { name = "tgamma"; };
+
+function = {
+       name = "beta";
+       args = 2;
+       comment = "Beta-function";
+};
+
+function = { name = "factorial"; };
+
+function = {
+       name = "binomial";
+       args = 2;
+};
+
+function = {
+       name = "Order";
+       comment = "Order term function (for truncated power series)";
+};
+
 /* Thease are not functions, but anyway ... */
-function = { name = "sqrt"; };
+function = { 
+	name = "sqrt"; 
+	quasi = 1;
+};
 
 function = { 
 	name = "pow";
 	args = 2;
+	quasi = 1;
 };
 
 function = {
 	name = "power";
 	args = 2;
+	quasi = 1;
 };
+
diff --git a/ginac/parser/default_reader.tpl b/ginac/parser/default_reader.tpl
index e65802a..32f20f4 100644
--- a/ginac/parser/default_reader.tpl
+++ b/ginac/parser/default_reader.tpl
@@ -62,10 +62,10 @@ const prototype_table& get_default_reader()
 	static bool initialized = false;
 	static prototype_table reader;
 	if (!initialized) {
-		[+ FOR function +]
+		[+ FOR function +][+ IF (exist? "quasi") +]
 		reader[make_pair("[+ (get "name") +]", [+ 
 			(if (exist? "args") (get "args") "1")
-			+])] = [+ (get "name") +]_reader;[+
+			+])] = [+ (get "name") +]_reader;[+ ENDIF +][+
 		ENDFOR +]
 		std::vector<function_options>::const_iterator it =
 			registered_functions_hack::get_registered_functions().begin();
@@ -87,51 +87,13 @@ const prototype_table& get_builtin_reader()
 	using std::make_pair;
 	static bool initialized = false;
 	static prototype_table reader;
-	if (!initialized) {
-		[+ FOR function +]
-		reader[make_pair("[+ (get "name") +]", [+ 
-			(if (exist? "args") (get "args") "1")
-			+])] = [+ (get "name") +]_reader;[+
-		ENDFOR +]
-		enum {
-			log,
-			exp,
-			sin,
-			cos,
-			tan,
-			asin,
-			acos,
-			atan,
-			sinh,
-			cosh,
-			tanh,
-			asinh,
-			acosh,
-			atanh,
-			atan2,
-			Li2,
-			Li3,
-			zetaderiv,
-			Li,
-			S,
-			H,
-			lgamma,
-			tgamma,
-			beta,
-			factorial,
-			binomial,
-			Order,
-			NFUNCTIONS
-		};
-		std::vector<function_options>::const_iterator it =
-			registered_functions_hack::get_registered_functions().begin();
-		unsigned serial = 0;
-		for ( ; serial<NFUNCTIONS; ++it, ++serial ) {
-			prototype proto = make_pair(it->get_name(), it->get_nparams());
-			reader[proto] = encode_serial_as_reader_func(serial);
-		}
-		initialized = true;
-	}
+	if (initialized)
+		return reader;
+	[+ FOR function +]
+	reader[make_pair("[+ (get "name") +]", [+ 
+		(if (exist? "args") (get "args") "1")
+		+])] = [+ (get "name") +]_reader;[+
+	ENDFOR +]
 	return reader;
 }
 
-- 
1.6.3.3



More information about the GiNaC-devel mailing list