/*
* Copyright (C) 1999, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2011,
* 2012, 2013 Free Software Foundation, Inc.
*
* This file is part of GNU libmatheval
*
* GNU libmatheval is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* GNU libmatheval is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU libmatheval. If not, see
* .
*/
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include "common.h"
#include "matheval.h"
#include "node.h"
#include "symbol_table.h"
/* Minimal length of evaluator symbol table. */
#define MIN_TABLE_LENGTH 211
/* Function used to parse string representing function (this function is
* generated by parser generator). */
extern int yyparse();
/* Following variables are needed for parsing (parser is able to
* communicate with program from which it is used through global variables
* only). */
char *input_string; /* String representing function. */
Node *root; /* Root of tree representation of
* function. */
SymbolTable *symbol_table; /* Evaluator symbol table. */
int ok; /* Flag determining if parsing went OK. */
/* Data structure representing evaluator. */
typedef struct {
Node *root; /* Root of tree representation of
* function. */
SymbolTable *symbol_table; /* Evalutor symbol table. */
char *string; /* Evaluator textual representation. */
int count; /* Number of evaluator variables. */
char **names; /* Array of pointers to evaluator variable
* names. */
} Evaluator;
void *
evaluator_create(char *string)
{
Evaluator *evaluator; /* Evaluator representing function
* given by string. */
char *stringn; /* Copy of string terminated by
* newline character. */
/* Copy string representing function and terminate it with newline
* (this is necessary because parser expect newline character to
* terminate its input). */
stringn = XMALLOC(char, strlen(string) + 2);
strcpy(stringn, string);
strcat(stringn, "\n");
/* Initialize global variables used by parser. */
input_string = stringn;
root = NULL;
symbol_table = symbol_table_create(MIN_TABLE_LENGTH);
ok = 1;
/* Do parsing. */
yyparse();
/* Free copy of string representing function. */
XFREE(stringn);
/* Return null pointer as error indicator if parsing error
* occured. */
if (!ok) {
symbol_table_destroy(symbol_table);
return NULL;
}
/* Simplify tree represention of function. */
root = node_simplify(root);
/* Allocate memory for and initialize evaluator data structure. */
evaluator = XMALLOC(Evaluator, 1);
evaluator->root = root;
evaluator->symbol_table = symbol_table;
evaluator->string = NULL;
evaluator->count = 0;
evaluator->names = NULL;
return evaluator;
}
void
evaluator_destroy(void *evaluator)
{
/* Destroy tree represention of function, symbol table, array of
* pointers to evaluator variable names, as well as data structure
* representing evaluator. */
node_destroy(((Evaluator *) evaluator)->root);
symbol_table_destroy(((Evaluator *) evaluator)->symbol_table);
XFREE(((Evaluator *) evaluator)->string);
XFREE(((Evaluator *) evaluator)->names);
XFREE(evaluator);
}
double
evaluator_evaluate(void *evaluator, int count, char **names,
double *values)
{
Record *record; /* Symbol table record corresponding to
* given variable name. */
int i; /* Loop counter. */
/* Assign values to symbol table records corresponding to variable
* names. */
for (i = 0; i < count; i++) { record = symbol_table_lookup(((Evaluator *) evaluator)->
symbol_table, names[i]);
if (record && record->type == 'v')
record->data.value = values[i];
}
/* Evaluate function value using tree represention of function. */
return node_evaluate(((Evaluator *) evaluator)->root);
}
char *
evaluator_get_string(void *evaluator)
{
int length; /* Length of evaluator textual
* representaion. */
/* If not already, create and remember evaluator textual
* representation. */
if (!((Evaluator *) evaluator)->string) {
length = node_get_length(((Evaluator *) evaluator)->root);
((Evaluator *) evaluator)->string =
XMALLOC(char, length + 1);
node_write(((Evaluator *) evaluator)->root,
((Evaluator *) evaluator)->string);
((Evaluator *) evaluator)->string[length] = 0;
}
/* Return requsted information. */
return ((Evaluator *) evaluator)->string;
}
void
evaluator_get_variables(void *evaluator, char ***names, int *count)
{
Record **records; /* Array of symbol table records
* containing evaluator variables.
*/
int i; /* Loop counter. */
/* If not already, find and remember evaluator variable names. */
if (!((Evaluator *) evaluator)->names) {
symbol_table_clear_flags(((Evaluator *) evaluator)->
symbol_table);
node_flag_variables(((Evaluator *) evaluator)->root);
((Evaluator *) evaluator)->count =
symbol_table_get_flagged_count(((Evaluator *)
evaluator)->
symbol_table);
records =
XMALLOC(Record *, ((Evaluator *) evaluator)->count);
symbol_table_get_flagged(((Evaluator *) evaluator)->
symbol_table, records,
((Evaluator *) evaluator)->count);
((Evaluator *) evaluator)->names =
XMALLOC(char *, ((Evaluator *) evaluator)->count);
for (i = 0; i < ((Evaluator *) evaluator)->count; i++)
((Evaluator *) evaluator)->names[i] =
records[i]->name;
XFREE(records);
}
/* Return requested information. */
*count = ((Evaluator *) evaluator)->count;
*names = ((Evaluator *) evaluator)->names;
}
void *
evaluator_derivative(void *evaluator, char *name)
{
Evaluator *derivative; /* Derivative function evaluator. */
/* Allocate memory for and initalize data structure for evaluator
* representing derivative of function given by evaluator. */
derivative = XMALLOC(Evaluator, 1);
derivative->root =
node_simplify(node_derivative
(((Evaluator *) evaluator)->root, name,
((Evaluator *) evaluator)->symbol_table));
derivative->symbol_table =
symbol_table_assign(((Evaluator *) evaluator)->symbol_table);
derivative->string = NULL;
derivative->count = 0;
derivative->names = NULL;
return derivative;
}
double
evaluator_evaluate_x(void *evaluator, double x)
{
char *names[] = {
"x"
}; /* Array of variable names. */
double values[1]; /* Array of variable values. */
/* Evaluate function for given values of variable "x". */
values[0] = x;
return evaluator_evaluate(evaluator,
sizeof(names) / sizeof(names[0]), names,
values);
}
double
evaluator_evaluate_x_y(void *evaluator, double x, double y)
{
char *names[] = {
"x", "y"
}; /* Array of variable names. */
double values[2]; /* Array of variable values. */
/* Evaluate function for given values of variable "x" and "y". */
values[0] = x, values[1] = y;
return evaluator_evaluate(evaluator,
sizeof(names) / sizeof(names[0]), names,
values);
}
double
evaluator_evaluate_x_y_z(void *evaluator, double x, double y, double z)
{
char *names[] = {
"x", "y", "z"
}; /* Array of variable names. */
double values[3]; /* Array of variable values. */
/* Evaluate function for given values of variable "x", "y" and
* "z". */
values[0] = x, values[1] = y, values[2] = z;
return evaluator_evaluate(evaluator,
sizeof(names) / sizeof(names[0]), names,
values);
}
void *
evaluator_derivative_x(void *evaluator)
{
/* Differentiate function using derivation variable "x". */
return evaluator_derivative(evaluator, "x");
}
void *
evaluator_derivative_y(void *evaluator)
{
/* Differentiate function using derivation variable "y". */
return evaluator_derivative(evaluator, "y");
}
void *
evaluator_derivative_z(void *evaluator)
{
/* Differentiate function using derivation variable "z". */
return evaluator_derivative(evaluator, "z");
}