symbolic4
symbolic4.c
Go to the documentation of this file.
1 
2 /*
3 
4  Copyright (c) 2019 Hannes Eberhard
5 
6  Permission is hereby granted, free of charge, to any person obtaining a copy
7  of this software and associated documentation files (the "Software"), to deal
8  in the Software without restriction, including without limitation the rights
9  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  copies of the Software, and to permit persons to whom the Software is
11  furnished to do so, subject to the following conditions:
12 
13  The above copyright notice and this permission notice shall be included in all
14  copies or substantial portions of the Software.
15 
16  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  SOFTWARE.
23 
24  */
25 
26 #include "symbolic4.h"
27 
28 bool use_abbrevations = true;
29 bool use_spaces = true;
30 char* default_priorities = "XYZABCDUVWSTPQRJKLMNOFGHEIxyzabcduvwstpqrjklmnofghei";
31 
32 uint8_t process_equation(expression* source);
33 uint8_t process_solve(expression* source);
34 uint8_t process_value(expression* source);
35 uint8_t process_factors(expression* source);
36 uint8_t process_derivative(expression* source);
37 uint8_t process_integral(expression* source);
38 uint8_t process_stationary_points(expression* source);
39 uint8_t process_tangent(expression* source);
40 uint8_t process_normal(expression* source);
41 uint8_t process_angle(expression* source);
42 uint8_t process_vector_magnitude(expression* source);
43 uint8_t process_vector_normalized(expression* source);
44 uint8_t process_vector_angle(expression* source);
45 uint8_t process_vector_dot_product(expression* source);
48 void process_approximate(expression* source);
49 
50 uint8_t symbolic4(char* buffer, const char* query) {
51 
52  expression* root;
53 
54  allocated_pointers = calloc(ALLOCATED_POINTERS_LENGTH, sizeof(void*));
56  buffer[0] = '\0';
57 
59 
60  ERROR_CHECK(tokenize(root, query));
61  ERROR_CHECK(validate(root));
62  parse(root);
63 
64  if (root->identifier == EXPI_PARSE) {
65  expression_to_string(buffer, root->children[0], (root->child_count == 2) ? (uint8_t) root->children[1]->value.numeric.numerator : ETSF_INFIX);
66  } else {
67  ERROR_CHECK(process(root, true));
68  expression_to_string(buffer, root, ETSF_INFIX);
69  }
70 
71  free_expression(root, false);
73  free(allocated_pointers);
74 
75  return RETS_SUCCESS;
76 
77 }
78 
79 uint8_t process(expression* source, bool recursive) {
80 
81  uint8_t i;
82 
83  for (i = 0; i < source->child_count && recursive; i++) {
84  if (source->children[i] == NULL) continue;
85  ERROR_CHECK(process(source->children[i], true));
86  }
87 
88  if ((source->type == EXPT_FUNCTION || source->identifier == EXPT_STRUCTURE) && source->child_count == 0) {
90  }
91 
92  switch (source->identifier) {
93  case EXPI_EQUATION: ERROR_CHECK(process_equation(source)); break;
94  case EXPI_SOLVE: ERROR_CHECK(process_solve(source)); break;
95  case EXPI_FACTORS: ERROR_CHECK(process_factors(source)); break;
96  case EXPI_VALUE: process_value(source); break;
97  case EXPI_DERIVATIVE: ERROR_CHECK(process_derivative(source)); break;
98  case EXPI_INTEGRAL: ERROR_CHECK(process_integral(source)); break;
99  case EXPI_TANGENT: ERROR_CHECK(process_tangent(source)); break;
100  case EXPI_NORMAL: ERROR_CHECK(process_normal(source)); break;
101  case EXPI_ANGLE: ERROR_CHECK(process_angle(source)); break;
102  case EXPI_V_MAG: ERROR_CHECK(process_vector_magnitude(source)); break;
104  case EXPI_V_ANGLE: ERROR_CHECK(process_vector_angle(source)); break;
108  case EXPI_APPROXIMATE: process_approximate(source); break;
109  default: ERROR_CHECK(simplify(source, !recursive)); break;
110  }
111 
112  return RETS_SUCCESS;
113 
114 }
115 
116 uint8_t process_equation(expression* source) {
117  if (source->child_count != 2) return set_error(ERRD_SYNTAX, ERRI_ARGUMENTS, "");
118  ERROR_CHECK(solve(source, NULL));
119  return RETS_SUCCESS;
120 }
121 
122 uint8_t process_solve(expression* source) {
123 
124  if (source->children[0]->identifier != EXPI_EQUATION) return set_error(ERRD_SYNTAX, ERRI_ARGUMENTS, "");
125 
126  if (source->child_count == 1) {
127  ERROR_CHECK(solve(source->children[0], NULL));
128  } else if (source->child_count == 2 && source->children[1]->identifier == EXPI_SYMBOL) {
129  ERROR_CHECK(solve(source->children[0], source->children[1]));
130  } else {
131  return set_error(ERRD_SYNTAX, ERRI_ARGUMENTS, "");
132  }
133 
134  replace_expression(source, copy_expression(source->children[0]));
135 
136  return RETS_SUCCESS;
137 
138 }
139 
140 uint8_t process_factors(expression* source) {
141 
142  expression* result;
143 
144  if (source->child_count != 1) return set_error(ERRD_SYNTAX, ERRI_ARGUMENTS, "");
145 
146  if (source->children[0]->identifier == EXPI_LITERAL) {
147  if (source->children[0]->sign == 1 && source->children[0]->value.numeric.denominator == 1) {
148  result = prime_factors(source->children[0]->value.numeric.numerator);
149  } else {
150  return RETS_UNCHANGED;
151  }
152  } else {
153  factor_square_free(&result, source->children[0]);
154  }
155 
156  replace_expression(source, result);
157 
158  return RETS_SUCCESS;
159 
160 }
161 
162 uint8_t process_value(expression* source) {
163 
164  uint8_t i;
165  expression* symbol;
166 
167  if (source->child_count < 2) {
168  return set_error(ERRD_SYNTAX, ERRI_ARGUMENTS, "");
169  } else if (source->children[1]->identifier != EXPI_EQUATION) {
170  symbol = guess_symbol(source->children[0], "", 0);
171  replace_occurences(source->children[0], symbol, source->children[1]);
172  free_expression(symbol, false);
173  } else {
174  for (i = 1; i < source->child_count; i++) {
175  if (source->children[i]->identifier == EXPI_EQUATION) {
176  replace_occurences(source->children[0], source->children[i]->children[0], source->children[i]->children[1]);
177  } else {
178  return set_error(ERRD_SYNTAX, ERRI_ARGUMENTS, "");
179  }
180  }
181  }
182 
183  replace_expression(source, copy_expression(source->children[0]));
184  simplify(source, true);
185 
186  return RETS_SUCCESS;
187 
188 }
189 
190 uint8_t process_derivative(expression* source) {
191 
192  expression* result;
193 
194  if (source->child_count == 1) {
195  ERROR_CHECK(derivative(&result, source->children[0], NULL, true));
196  } else if (source->child_count == 2 && source->children[1]->identifier == EXPI_SYMBOL) {
197  ERROR_CHECK(derivative(&result, source->children[0], source->children[1], true));
198  } else {
200  }
201 
202  replace_expression(source, result);
203 
204  return RETS_SUCCESS;
205 
206 }
207 
208 uint8_t process_integral(expression* source) {
209 
210  expression* result;
211 
212  if (source->child_count == 1) {
213  ERROR_CHECK(antiderivative(&result, source->children[0], NULL, true));
214  } else if (source->child_count == 2 && source->children[1]->identifier == EXPI_SYMBOL) {
215  ERROR_CHECK(antiderivative(&result, source->children[0], source->children[1], true));
216  } else if (source->child_count == 3) {
217  ERROR_CHECK(definite_integral(&result, source->children[0], NULL, source->children[1], source->children[2]));
218  } else {
220  }
221 
222  replace_expression(source, result);
223 
224  return RETS_SUCCESS;
225 
226 }
227 
229 
230  expression* result = copy_expression(source->children[0]);
231 
232  if (source->child_count == 1) {
233  stationary_points(result, NULL);
234  } else if (source->child_count == 2) {
235  stationary_points(result, source->children[1]);
236  } else {
238  }
239 
240  replace_expression(source, result);
241 
242  return RETS_SUCCESS;
243 
244 }
245 
246 uint8_t process_tangent(expression* source) {
247 
248  expression* variable;
249  expression* result;
250 
251  if (source->child_count == 2) {
252  variable = guess_symbol(source, "", 0);
253  ERROR_CHECK(function_tangent(&result, source->children[0], variable, source->children[1], true));
254  } else if (source->child_count == 3) {
255  ERROR_CHECK(function_tangent(&result, source->children[0], source->children[1], source->children[2], true));
256  } else {
258  }
259 
260  replace_expression(source, result);
261 
262  return RETS_SUCCESS;
263 
264 }
265 
266 uint8_t process_normal(expression* source) {
267 
268  expression* variable;
269  expression* result;
270 
271  if (source->child_count == 2) {
272  variable = guess_symbol(source, "", 0);
273  ERROR_CHECK(function_normal(&result, source->children[0], variable, source->children[1], true));
274  } else if (source->child_count == 3) {
275  ERROR_CHECK(function_normal(&result, source->children[0], source->children[1], source->children[2], true));
276  } else {
278  }
279 
280  replace_expression(source, result);
281 
282  return RETS_SUCCESS;
283 
284 }
285 
286 uint8_t process_angle(expression* source) {
287 
288  expression* result;
289 
291  ERROR_CHECK(function_intersection_angle(&result, source->children[0], source->children[1]));
292 
293  replace_expression(source, result);
294 
295  return RETS_SUCCESS;
296 
297 }
298 
300 
301  expression* result;
302 
303  if (source->child_count == 1 && source->children[0]->identifier == EXPI_LIST) {
304  ERROR_CHECK(vector_magnitude(&result, source->children[0], true));
305  } else {
306  ERROR_CHECK(vector_magnitude(&result, source, true));
307  }
308 
309  replace_expression(source, result);
310 
311  return RETS_SUCCESS;
312 
313 }
314 
316 
317  expression* result;
318  expression* magnitude;
319 
320  if (source->children[0]->identifier == EXPI_LIST) {
321  if (source->child_count == 1) {
322  magnitude = new_literal(1, 1, 1);
323  } else if (source->child_count == 2) {
324  if (source->children[1]->identifier == EXPI_LIST) {
325  vector_magnitude(&magnitude, source->children[1], true);
326  } else {
327  magnitude = copy_expression(source->children[1]);
328  }
329  } else {
331  }
332  ERROR_CHECK(vector_normalized(&result, source->children[0], magnitude, true));
333  } else {
334  magnitude = new_literal(1, 1, 1);
335  ERROR_CHECK(vector_normalized(&result, source, magnitude, true));
336  }
337 
338  replace_expression(source, result);
339 
340  return RETS_SUCCESS;
341 
342 }
343 
345 
346  expression* result;
347 
348  if (source->child_count == 2 && source->children[0]->identifier == EXPI_LIST && source->children[1]->identifier == EXPI_LIST) {
349  if (source->children[0]->child_count == source->children[1]->child_count) {
350  ERROR_CHECK(vector_angle(&result, source->children[0], source->children[1], true));
351  } else {
353  }
354  } else {
356  }
357 
358  replace_expression(source, result);
359 
360  return RETS_SUCCESS;
361 
362 }
363 
365 
366  expression* result;
367 
368  if (source->child_count == 2 && source->children[0]->identifier == EXPI_LIST && source->children[1]->identifier == EXPI_LIST) {
369  if (source->children[0]->child_count == source->children[1]->child_count) {
370  ERROR_CHECK(vector_dot_product(&result, source->children[0], source->children[1], true));
371  } else {
373  }
374  } else {
376  }
377 
378  replace_expression(source, result);
379 
380  return RETS_SUCCESS;
381 
382 }
383 
385 
386  expression* result;
387 
388  if (source->child_count == 2 && source->children[0]->identifier == EXPI_LIST && source->children[1]->identifier == EXPI_LIST) {
389  if (source->children[0]->child_count == 3 && source->children[1]->child_count == 3) {
390  ERROR_CHECK(vector_cross_product(&result, source->children[0], source->children[1], true));
391  } else {
393  }
394  } else {
396  }
397 
398  replace_expression(source, result);
399 
400  return RETS_SUCCESS;
401 
402 }
403 
405 
406  expression* result;
407 
408  if (source->child_count == 3 && source->children[0]->identifier == EXPI_LIST && source->children[1]->identifier == EXPI_LIST && source->children[2]->identifier == EXPI_LIST) {
409  if (source->children[0]->child_count == 3 && source->children[1]->child_count == 3 && source->children[2]->child_count == 3) {
410  ERROR_CHECK(vector_triple_product(&result, source->children[0], source->children[1], source->children[2], true));
411  } else {
413  }
414  } else {
416  }
417 
418  replace_expression(source, result);
419 
420  return RETS_SUCCESS;
421 
422 }
423 
425  approximate(source);
426  literal_to_double_symbol(source);
427  replace_expression(source, copy_expression(source->children[0]));
428 }
EXPI_SOLVE
Definition: expression.h:66
ERRI_ARGUMENTS
Definition: foundation.h:58
EXPI_LIST
Definition: expression.h:90
EXPT_FUNCTION
Definition: expression.h:35
smart_free_all
void smart_free_all(void)
Frees all pointers.
Definition: foundation.c:133
process_tangent
uint8_t process_tangent(expression *source)
Definition: symbolic4.c:246
numeric_value::denominator
uintmax_t denominator
Definition: expression.h:109
symbolic4.h
stationary_points
uint8_t stationary_points(expression *source, expression *variable)
Definition: derivative.c:259
validate
uint8_t validate(expression *tokens)
Definition: parser.c:321
vector_triple_product
uint8_t vector_triple_product(expression **result, expression *source_1, expression *source_2, expression *source_3, bool persistent)
Definition: vector.c:162
expression::type
expression_type type
Definition: expression.h:114
process_normal
uint8_t process_normal(expression *source)
Definition: symbolic4.c:266
EXPI_SYMBOL
Definition: expression.h:45
process_vector_dot_product
uint8_t process_vector_dot_product(expression *source)
Definition: symbolic4.c:364
default_priorities
char * default_priorities
Definition: symbolic4.c:30
derivative
uint8_t derivative(expression **result, expression *source, expression *variable, bool persistent)
Definition: derivative.c:209
replace_expression
void replace_expression(expression *a, expression *b)
Definition: expression.c:309
ERRI_VECTOR_DIMENSIONS
Definition: foundation.h:59
expression
Definition: expression.h:112
expression::identifier
expression_identifier identifier
Definition: expression.h:115
literal_to_double_symbol
void literal_to_double_symbol(expression *source)
Definition: expression.c:912
process_angle
uint8_t process_angle(expression *source)
Definition: symbolic4.c:286
antiderivative
uint8_t antiderivative(expression **result, expression *source, expression *variable, bool persistent)
Definition: integral.c:373
prime_factors
expression * prime_factors(uintmax_t source)
Definition: math_foundation.c:65
vector_dot_product
uint8_t vector_dot_product(expression **result, expression *source_1, expression *source_2, bool persistent)
Definition: vector.c:110
replace_occurences
void replace_occurences(expression *source, const expression *child, const expression *replacement)
Definition: expression.c:688
EXPT_STRUCTURE
Definition: expression.h:36
EXPI_V_TRIPLE_PRODUCT
Definition: expression.h:84
ERRD_VECTOR
Definition: foundation.h:46
function_intersection_angle
uint8_t function_intersection_angle(expression **result, expression *g, expression *h)
Definition: derivative.c:407
EXPI_V_MAG
Definition: expression.h:79
ERRD_SYNTAX
Definition: foundation.h:36
ETSF_INFIX
Definition: expression.h:103
expression::sign
int8_t sign
Definition: expression.h:117
ERROR_CHECK
#define ERROR_CHECK(F)
Check if the return status of a function is RETS_ERROR. If so, return RETS_ERROR.
Definition: foundation.h:31
EXPI_V_NORMALIZED
Definition: expression.h:80
EXPI_TANGENT
Definition: expression.h:75
process_derivative
uint8_t process_derivative(expression *source)
Definition: symbolic4.c:190
expression::value
union expression::@0 value
process_vector_normalized
uint8_t process_vector_normalized(expression *source)
Definition: symbolic4.c:315
solve
uint8_t solve(expression *source, expression *variable)
Definition: solve.c:337
EXPI_V_CROSS_PRODUCT
Definition: expression.h:83
RETS_UNCHANGED
Definition: foundation.h:69
vector_magnitude
uint8_t vector_magnitude(expression **result, expression *source, bool persistent)
Definition: vector.c:28
EXPI_NORMAL
Definition: expression.h:76
vector_normalized
uint8_t vector_normalized(expression **result, expression *source, expression *magnitude, bool persistent)
Definition: vector.c:50
vector_angle
uint8_t vector_angle(expression **result, expression *source_1, expression *source_2, bool persistent)
Definition: vector.c:81
RETS_SUCCESS
Definition: foundation.h:67
use_spaces
bool use_spaces
Determines if spaces should be used in the result string (such as "x + y * z" instead of "x+y*z")
Definition: symbolic4.c:29
process_factors
uint8_t process_factors(expression *source)
Definition: symbolic4.c:140
EXPI_DERIVATIVE
Definition: expression.h:70
free_expression
void free_expression(expression *source, bool persistent)
Definition: expression.c:315
symbolic4
uint8_t symbolic4(char *buffer, const char *query)
Definition: symbolic4.c:50
EXPI_PARSE
Definition: expression.h:97
process_vector_angle
uint8_t process_vector_angle(expression *source)
Definition: symbolic4.c:344
process_vector_triple_product
uint8_t process_vector_triple_product(expression *source)
Definition: symbolic4.c:404
set_error
uint8_t set_error(error_domain domain, error_identifier identifier, const char *body)
Sets current_error to the arguments provided.
Definition: foundation.c:152
function_tangent
uint8_t function_tangent(expression **result, expression *source, expression *variable, expression *x_value, bool persistent)
Definition: derivative.c:329
approximate
void approximate(expression *source)
Definition: simplify.c:1267
EXPI_FACTORS
Definition: expression.h:67
tokenize
uint8_t tokenize(expression *tokens, const char *query)
Definition: parser.c:293
process_equation
uint8_t process_equation(expression *source)
Definition: symbolic4.c:116
expression::numeric
numeric_value numeric
Definition: expression.h:129
process_approximate
void process_approximate(expression *source)
Definition: symbolic4.c:424
expression_to_string
void expression_to_string(char *buffer, const expression *source, expression_to_string_format format)
Serializes an expression into a specified format.
Definition: expression.c:1031
ALLOCATED_POINTERS_LENGTH
#define ALLOCATED_POINTERS_LENGTH
Definition: symbolic4.h:30
process_stationary_points
uint8_t process_stationary_points(expression *source)
Definition: symbolic4.c:228
copy_expression
expression * copy_expression(const expression *source)
Returns a deep copy of an expression.
Definition: expression.c:286
process_value
uint8_t process_value(expression *source)
Definition: symbolic4.c:162
function_normal
uint8_t function_normal(expression **result, expression *source, expression *variable, expression *x_value, bool persistent)
Definition: derivative.c:367
vector_cross_product
uint8_t vector_cross_product(expression **result, expression *source_1, expression *source_2, bool persistent)
Definition: vector.c:133
simplify
uint8_t simplify(expression *source, bool recursive)
Definition: simplify.c:1117
process_integral
uint8_t process_integral(expression *source)
Definition: symbolic4.c:208
definite_integral
uint8_t definite_integral(expression **result, expression *source, expression *variable, expression *lower_bound, expression *upper_bound)
Definition: integral.c:406
get_expression_string
const char * get_expression_string(expression_identifier identifier)
Returns the keyword string corresponding to the identifier.
Definition: expression.c:950
new_expression
expression * new_expression(expression_type type, expression_identifier identifier, uint8_t child_count,...)
Allocates and initializes a new expression with the arguments provided.
Definition: expression.c:183
EXPI_EQUATION
Definition: expression.h:48
process
uint8_t process(expression *source, bool recursive)
Definition: symbolic4.c:79
EXPI_APPROXIMATE
Definition: expression.h:86
EXPI_V_DOT_PRODUCT
Definition: expression.h:82
guess_symbol
expression * guess_symbol(const expression *source, const char *custom_priorities, uint8_t rank)
Definition: expression.c:830
new_literal
expression * new_literal(int8_t sign, uintmax_t numerator, uintmax_t denominator)
Allocates and initializes a new literal expression.
Definition: expression.c:225
EXPI_INTEGRAL
Definition: expression.h:71
EXPI_VALUE
Definition: expression.h:68
process_vector_cross_product
uint8_t process_vector_cross_product(expression *source)
Definition: symbolic4.c:384
allocated_pointers
void ** allocated_pointers
Definition: foundation.c:29
factor_square_free
uint8_t factor_square_free(expression **factors, const expression *source)
Definition: polynomial.c:680
process_solve
uint8_t process_solve(expression *source)
Definition: symbolic4.c:122
EXPI_V_ANGLE
Definition: expression.h:81
expression::child_count
uint8_t child_count
Definition: expression.h:119
expression::children
struct expression ** children
Definition: expression.h:124
EXPI_ANGLE
Definition: expression.h:77
numeric_value::numerator
uintmax_t numerator
Definition: expression.h:108
use_abbrevations
bool use_abbrevations
Determines if abbrevations should be used in the result string (such as "Deriv" instead of "Derivativ...
Definition: symbolic4.c:28
process_vector_magnitude
uint8_t process_vector_magnitude(expression *source)
Definition: symbolic4.c:299
parse
void parse(expression *tokens)
Definition: parser.c:451
EXPI_LITERAL
Definition: expression.h:44