1 /*
2  * Copyright (C) 1999, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2011,
3  * 2012, 2013 Free Software Foundation, Inc.
4  *
5  * This file is part of GNU libmatheval
6  *
7  * GNU libmatheval is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation, either version 3 of the
10  * License, or (at your option) any later version.
11  *
12  * GNU libmatheval is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with GNU libmatheval.  If not, see
19  * <http://www.gnu.org/licenses/>.
20  */
21 
22 #if HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 
26 #include "common.h"
27 #include "matheval.h"
28 #include "node.h"
29 #include "symbol_table.h"
30 
31 /* Minimal length of evaluator symbol table.  */
32 #define MIN_TABLE_LENGTH 211
33 
34 /* Function used to parse string representing function (this function is
35  * generated by parser generator). */
36 extern int      yyparse();
37 
38 /* Following variables are needed for parsing (parser is able to
39  * communicate with program from which it is used through global variables
40  * only). */
41 char           *input_string;	/* String representing function.  */
42 Node           *root;		/* Root of tree representation of
43 				 * function.  */
44 SymbolTable    *symbol_table;	/* Evaluator symbol table.  */
45 int             ok;		/* Flag determining if parsing went OK.  */
46 
47 /* Data structure representing evaluator.  */
48 typedef struct {
49 	Node           *root;	/* Root of tree representation of
50 				 * function.  */
51 	SymbolTable    *symbol_table;	/* Evalutor symbol table.  */
52 	char           *string;	/* Evaluator textual representation. */
53 	int             count;	/* Number of evaluator variables. */
54 	char          **names;	/* Array of pointers to evaluator variable
55 				 * names. */
56 } Evaluator;
57 
58 void           *
evaluator_create(char * string)59 evaluator_create(char *string)
60 {
61 	Evaluator      *evaluator;	/* Evaluator representing function
62 					 * given by string.  */
63 	char           *stringn;	/* Copy of string terminated by
64 					 * newline character.  */
65 
66 	/* Copy string representing function and terminate it with newline
67 	 * (this is necessary because parser expect newline character to
68 	 * terminate its input). */
69 	stringn = XMALLOC(char, strlen(string) + 2);
70 
71 	strcpy(stringn, string);
72 	strcat(stringn, "\n");
73 
74 	/* Initialize global variables used by parser. */
75 	input_string = stringn;
76 	root = NULL;
77 	symbol_table = symbol_table_create(MIN_TABLE_LENGTH);
78 	ok = 1;
79 
80 	/* Do parsing. */
81 	yyparse();
82 
83 	/* Free copy of string representing function. */
84 	XFREE(stringn);
85 
86 	/* Return null pointer as error indicator if parsing error
87 	 * occured. */
88 	if (!ok) {
89                 symbol_table_destroy(symbol_table);
90 		return NULL;
91         }
92 
93 	/* Simplify tree represention of function. */
94 	root = node_simplify(root);
95 
96 	/* Allocate memory for and initialize evaluator data structure. */
97 	evaluator = XMALLOC(Evaluator, 1);
98 	evaluator->root = root;
99 	evaluator->symbol_table = symbol_table;
100 	evaluator->string = NULL;
101 	evaluator->count = 0;
102 	evaluator->names = NULL;
103 
104 	return evaluator;
105 }
106 
107 void
evaluator_destroy(void * evaluator)108 evaluator_destroy(void *evaluator)
109 {
110 	/* Destroy tree represention of function, symbol table, array of
111 	 * pointers to evaluator variable names, as well as data structure
112 	 * representing evaluator. */
113 	node_destroy(((Evaluator *) evaluator)->root);
114 	symbol_table_destroy(((Evaluator *) evaluator)->symbol_table);
115 	XFREE(((Evaluator *) evaluator)->string);
116 	XFREE(((Evaluator *) evaluator)->names);
117 	XFREE(evaluator);
118 }
119 
120 double
evaluator_evaluate(void * evaluator,int count,char ** names,double * values)121 evaluator_evaluate(void *evaluator, int count, char **names,
122 		   double *values)
123 {
124 	Record         *record;	/* Symbol table record corresponding to
125 				 * given variable name.  */
126 	int             i;	/* Loop counter.  */
127 
128 	/* Assign values to symbol table records corresponding to variable
129 	 * names. */
130 	for (i = 0; i < count; i++) {
131 		record =
132 		    symbol_table_lookup(((Evaluator *) evaluator)->
133 					symbol_table, names[i]);
134 		if (record && record->type == 'v')
135 			record->data.value = values[i];
136 	}
137 
138 	/* Evaluate function value using tree represention of function. */
139 	return node_evaluate(((Evaluator *) evaluator)->root);
140 }
141 
142 char           *
evaluator_get_string(void * evaluator)143 evaluator_get_string(void *evaluator)
144 {
145 	int             length;	/* Length of evaluator textual
146 				 * representaion. */
147 
148 	/* If not already, create and remember evaluator textual
149 	 * representation. */
150 	if (!((Evaluator *) evaluator)->string) {
151 		length = node_get_length(((Evaluator *) evaluator)->root);
152 		((Evaluator *) evaluator)->string =
153 		    XMALLOC(char, length + 1);
154 		node_write(((Evaluator *) evaluator)->root,
155 			   ((Evaluator *) evaluator)->string);
156 		((Evaluator *) evaluator)->string[length] = 0;
157 	}
158 
159 	/* Return requsted information. */
160 	return ((Evaluator *) evaluator)->string;
161 }
162 
163 void
evaluator_get_variables(void * evaluator,char *** names,int * count)164 evaluator_get_variables(void *evaluator, char ***names, int *count)
165 {
166 	Record        **records;	/* Array of symbol table records
167 					 * containing evaluator variables.
168 					 */
169 	int             i;	/* Loop counter.  */
170 
171 	/* If not already, find and remember evaluator variable names. */
172 	if (!((Evaluator *) evaluator)->names) {
173 		symbol_table_clear_flags(((Evaluator *) evaluator)->
174 					 symbol_table);
175 		node_flag_variables(((Evaluator *) evaluator)->root);
176 		((Evaluator *) evaluator)->count =
177 		    symbol_table_get_flagged_count(((Evaluator *)
178 						    evaluator)->
179 						   symbol_table);
180 		records =
181 		    XMALLOC(Record *, ((Evaluator *) evaluator)->count);
182 		symbol_table_get_flagged(((Evaluator *) evaluator)->
183 					 symbol_table, records,
184 					 ((Evaluator *) evaluator)->count);
185 		((Evaluator *) evaluator)->names =
186 		    XMALLOC(char *, ((Evaluator *) evaluator)->count);
187 		for (i = 0; i < ((Evaluator *) evaluator)->count; i++)
188 			((Evaluator *) evaluator)->names[i] =
189 			    records[i]->name;
190 		XFREE(records);
191 	}
192 
193 	/* Return requested information. */
194 	*count = ((Evaluator *) evaluator)->count;
195 	*names = ((Evaluator *) evaluator)->names;
196 }
197 
198 void           *
evaluator_derivative(void * evaluator,char * name)199 evaluator_derivative(void *evaluator, char *name)
200 {
201 	Evaluator      *derivative;	/* Derivative function evaluator. */
202 
203 	/* Allocate memory for and initalize data structure for evaluator
204 	 * representing derivative of function given by evaluator. */
205 	derivative = XMALLOC(Evaluator, 1);
206 	derivative->root =
207 	    node_simplify(node_derivative
208 			  (((Evaluator *) evaluator)->root, name,
209 			   ((Evaluator *) evaluator)->symbol_table));
210 	derivative->symbol_table =
211 	    symbol_table_assign(((Evaluator *) evaluator)->symbol_table);
212 	derivative->string = NULL;
213 	derivative->count = 0;
214 	derivative->names = NULL;
215 
216 	return derivative;
217 }
218 
219 double
evaluator_evaluate_x(void * evaluator,double x)220 evaluator_evaluate_x(void *evaluator, double x)
221 {
222 	char           *names[] = {
223 		"x"
224 	};			/* Array of variable names.  */
225 	double          values[1];	/* Array of variable values.  */
226 
227 	/* Evaluate function for given values of variable "x". */
228 	values[0] = x;
229 	return evaluator_evaluate(evaluator,
230 				  sizeof(names) / sizeof(names[0]), names,
231 				  values);
232 }
233 
234 double
evaluator_evaluate_x_y(void * evaluator,double x,double y)235 evaluator_evaluate_x_y(void *evaluator, double x, double y)
236 {
237 	char           *names[] = {
238 		"x", "y"
239 	};			/* Array of variable names.  */
240 	double          values[2];	/* Array of variable values.  */
241 
242 	/* Evaluate function for given values of variable "x" and "y". */
243 	values[0] = x, values[1] = y;
244 	return evaluator_evaluate(evaluator,
245 				  sizeof(names) / sizeof(names[0]), names,
246 				  values);
247 }
248 
249 double
evaluator_evaluate_x_y_z(void * evaluator,double x,double y,double z)250 evaluator_evaluate_x_y_z(void *evaluator, double x, double y, double z)
251 {
252 	char           *names[] = {
253 		"x", "y", "z"
254 	};			/* Array of variable names.  */
255 	double          values[3];	/* Array of variable values.  */
256 
257 	/* Evaluate function for given values of variable "x", "y" and
258 	 * "z". */
259 	values[0] = x, values[1] = y, values[2] = z;
260 	return evaluator_evaluate(evaluator,
261 				  sizeof(names) / sizeof(names[0]), names,
262 				  values);
263 }
264 
265 void           *
evaluator_derivative_x(void * evaluator)266 evaluator_derivative_x(void *evaluator)
267 {
268 	/* Differentiate function using derivation variable "x". */
269 	return evaluator_derivative(evaluator, "x");
270 }
271 
272 void           *
evaluator_derivative_y(void * evaluator)273 evaluator_derivative_y(void *evaluator)
274 {
275 	/* Differentiate function using derivation variable "y". */
276 	return evaluator_derivative(evaluator, "y");
277 }
278 
279 void           *
evaluator_derivative_z(void * evaluator)280 evaluator_derivative_z(void *evaluator)
281 {
282 	/* Differentiate function using derivation variable "z". */
283 	return evaluator_derivative(evaluator, "z");
284 }
285