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