mathexpr: Introduce changes by Jean-Philippe Meuret
This commit is contained in:
parent
520274a73d
commit
0dab63bf3b
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
|
|
||||||
mathexpr.cpp version 2.0
|
mathexpr.cpp version 2.1
|
||||||
|
|
||||||
Copyright (c) 1997-2000 Yann OLLIVIER
|
Copyright (c) 1997-2000 Yann OLLIVIER
|
||||||
|
|
||||||
|
@ -12,7 +12,33 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include"mathexpr.h"
|
/* 2009 changes by Jean-Philippe Meuret <jpmeuret@free.fr> for Qatsh
|
||||||
|
- added EFunction class to support external functions with any number of parameters
|
||||||
|
- fixed memory leaks in ROperation::Expr() in the Num, Var and Error cases
|
||||||
|
- added code comments in several places
|
||||||
|
- ROperation::ROperation(const char*,int,PRVar*,int,PRFunction*) :
|
||||||
|
changed 1st arg from 'char*' to 'const char*' for GCC 4.2 (deprecated conversion)
|
||||||
|
- optimised IsNumeric(char), IsFunction(const char*,int,int,PRFunction*),
|
||||||
|
and IsolateVars(...).
|
||||||
|
- added parenthesis at line 513 on GCC suggestion :
|
||||||
|
before: if(s[i]==opc&&(op!=Sub||i&&s[i-1]==')'))return i;
|
||||||
|
after : if(s[i]==opc&&(op!=Sub||(i&&s[i-1]==')')))return i;
|
||||||
|
|
||||||
|
TODO:
|
||||||
|
- make code more readable (1 instruction per line, consistent indentation,
|
||||||
|
at least all the end-of-block '}' on their own line, ...)
|
||||||
|
- give member data a special name, for easier understanding (ex: a leading "_" or "m_")
|
||||||
|
- reimplement code parts without any goto instruction
|
||||||
|
- add more comments
|
||||||
|
- use constants everywhere the same litteral is used more than once in the code
|
||||||
|
- use strxxx standard libC functions for all string manipulations
|
||||||
|
- and even better ... move all "[const] char*" to sdt::string
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include "mathexpr.h"
|
||||||
|
|
||||||
|
|
||||||
char* MidStr(const char*s,int i1,int i2)
|
char* MidStr(const char*s,int i1,int i2)
|
||||||
{
|
{
|
||||||
|
@ -27,10 +53,12 @@ char* MidStr(const char*s,int i1,int i2)
|
||||||
s1[i2-i1+1]=0;return s1;
|
s1[i2-i1+1]=0;return s1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return a copy of the given string (use strdup ?)
|
||||||
char* CopyStr(const char*s)
|
char* CopyStr(const char*s)
|
||||||
{char*s1=new char[strlen(s)+1];char*s12=s1;const char*s2=s;
|
{char*s1=new char[strlen(s)+1];char*s12=s1;const char*s2=s;
|
||||||
while((*s12++=*s2++));return s1;}
|
while((*s12++=*s2++));return s1;}
|
||||||
|
|
||||||
|
// Insert a char at a given position in a string (increase string length by 1)
|
||||||
void InsStr(char*&s,int n,char c)// Warning : deletes the old string
|
void InsStr(char*&s,int n,char c)// Warning : deletes the old string
|
||||||
{if(n<0||n>(int)strlen(s))return;
|
{if(n<0||n>(int)strlen(s))return;
|
||||||
char*s1=new char[strlen(s)+2];
|
char*s1=new char[strlen(s)+2];
|
||||||
|
@ -48,6 +76,7 @@ for(i=0;s[i];i++)if(s[i]!=s2[i])return 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tell if s[n...] == s2
|
||||||
signed char CompStr(const char*s,int n,const char*s2)
|
signed char CompStr(const char*s,int n,const char*s2)
|
||||||
{if(n<0||n>=(int)strlen(s)||n+(int)strlen(s2)>(int)strlen(s))return 0;
|
{if(n<0||n>=(int)strlen(s)||n+(int)strlen(s2)>(int)strlen(s))return 0;
|
||||||
int i;
|
int i;
|
||||||
|
@ -72,7 +101,49 @@ RVar::RVar(const char*namep,double*pvalp)
|
||||||
{pval=pvalp;name=CopyStr(namep);}
|
{pval=pvalp;name=CopyStr(namep);}
|
||||||
|
|
||||||
RVar::~RVar()
|
RVar::~RVar()
|
||||||
{if(name!=NULL)delete[] name;}
|
{
|
||||||
|
if(name!=NULL)delete[] name;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFunction::EFunction(unsigned nvarsp)
|
||||||
|
{
|
||||||
|
nvars = nvarsp;
|
||||||
|
pvars = new double[nvarsp];
|
||||||
|
}
|
||||||
|
|
||||||
|
EFunction::~EFunction()
|
||||||
|
{
|
||||||
|
if (pvars)
|
||||||
|
delete[] pvars;
|
||||||
|
}
|
||||||
|
|
||||||
|
double EFunction::operator()(double* pvarsp)
|
||||||
|
{
|
||||||
|
// Store variables in the pvars array.
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; i < nvars; i++)
|
||||||
|
pvars[i] = pvarsp[i];
|
||||||
|
|
||||||
|
// Compute value.
|
||||||
|
return Val();
|
||||||
|
}
|
||||||
|
|
||||||
|
double EFunction::operator()(double var1p, ...)
|
||||||
|
{
|
||||||
|
// Store 1st variable (always here) in the pvars array.
|
||||||
|
pvars[0] = var1p;
|
||||||
|
|
||||||
|
// Store other variables in the pvars array.
|
||||||
|
va_list vl;
|
||||||
|
va_start(vl, var1p);
|
||||||
|
unsigned i;
|
||||||
|
for (i = 1; i < nvars; i++)
|
||||||
|
pvars[i] = (double)va_arg(vl, double);
|
||||||
|
va_end(vl);
|
||||||
|
|
||||||
|
// Compute value.
|
||||||
|
return Val();
|
||||||
|
}
|
||||||
|
|
||||||
RFunction::RFunction()
|
RFunction::RFunction()
|
||||||
{
|
{
|
||||||
|
@ -86,11 +157,18 @@ RFunction::RFunction(double ((*pfuncvalp)(double)))
|
||||||
nvars=1;ppvar=NULL;op=ErrVal;buf=NULL;
|
nvars=1;ppvar=NULL;op=ErrVal;buf=NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RFunction::RFunction(EFunction& efunc)
|
||||||
|
{
|
||||||
|
type=2;pfuncobjval=&efunc;name=new char[1];name[0]=0;
|
||||||
|
nvars=efunc.nvars;ppvar=NULL;op=ErrVal;buf=NULL;
|
||||||
|
}
|
||||||
|
|
||||||
RFunction::RFunction(const RFunction& rfunc)
|
RFunction::RFunction(const RFunction& rfunc)
|
||||||
{
|
{
|
||||||
if(this==&rfunc)return;
|
if(this==&rfunc)return;
|
||||||
type=rfunc.type;op=rfunc.op;
|
type=rfunc.type;op=rfunc.op;
|
||||||
pfuncval=rfunc.pfuncval;
|
pfuncval=rfunc.pfuncval;
|
||||||
|
pfuncobjval=rfunc.pfuncobjval;
|
||||||
name=CopyStr(rfunc.name);
|
name=CopyStr(rfunc.name);
|
||||||
nvars=rfunc.nvars;
|
nvars=rfunc.nvars;
|
||||||
if(rfunc.ppvar!=NULL&&nvars){
|
if(rfunc.ppvar!=NULL&&nvars){
|
||||||
|
@ -129,6 +207,7 @@ RFunction& RFunction::operator=(const RFunction& rfunc)
|
||||||
if(this==&rfunc)return *this;
|
if(this==&rfunc)return *this;
|
||||||
type=rfunc.type;op=rfunc.op;
|
type=rfunc.type;op=rfunc.op;
|
||||||
pfuncval=rfunc.pfuncval;
|
pfuncval=rfunc.pfuncval;
|
||||||
|
pfuncobjval=rfunc.pfuncobjval;
|
||||||
delete[]name;
|
delete[]name;
|
||||||
name=CopyStr(rfunc.name);
|
name=CopyStr(rfunc.name);
|
||||||
if(ppvar!=NULL)delete[]ppvar;
|
if(ppvar!=NULL)delete[]ppvar;
|
||||||
|
@ -150,6 +229,7 @@ double RFunction::Val(double x) const
|
||||||
{
|
{
|
||||||
if(type==-1||nvars>=2)return ErrVal;
|
if(type==-1||nvars>=2)return ErrVal;
|
||||||
if(type==0)return (*pfuncval)(x);
|
if(type==0)return (*pfuncval)(x);
|
||||||
|
if(type==2)return (*pfuncobjval)(x);
|
||||||
double xb=*(*ppvar)->pval,y;
|
double xb=*(*ppvar)->pval,y;
|
||||||
*(*ppvar)->pval=x; // Warning : could cause trouble if this value is used in a parallel process
|
*(*ppvar)->pval=x; // Warning : could cause trouble if this value is used in a parallel process
|
||||||
y=op.Val();
|
y=op.Val();
|
||||||
|
@ -161,6 +241,7 @@ double RFunction::Val(double*pv) const
|
||||||
{
|
{
|
||||||
if(type==-1)return ErrVal;
|
if(type==-1)return ErrVal;
|
||||||
if(type==0)return (*pfuncval)(*pv);
|
if(type==0)return (*pfuncval)(*pv);
|
||||||
|
if(type==2)return (*pfuncobjval)(pv);
|
||||||
double y;
|
double y;
|
||||||
int i;
|
int i;
|
||||||
for(i=0;i<nvars;i++){
|
for(i=0;i<nvars;i++){
|
||||||
|
@ -311,8 +392,8 @@ ROperation resultat;
|
||||||
resultat.op=Pow;resultat.mmb1=new ROperation(op1);
|
resultat.op=Pow;resultat.mmb1=new ROperation(op1);
|
||||||
resultat.mmb2=new ROperation(op2);
|
resultat.mmb2=new ROperation(op2);
|
||||||
return resultat;
|
return resultat;
|
||||||
}
|
}
|
||||||
|
|
||||||
ROperation sqrt(const ROperation& op)
|
ROperation sqrt(const ROperation& op)
|
||||||
{ROperation rop;rop.op=Sqrt;rop.mmb2=new ROperation(op);return rop;}
|
{ROperation rop;rop.op=Sqrt;rop.mmb2=new ROperation(op);return rop;}
|
||||||
ROperation abs(const ROperation& op)
|
ROperation abs(const ROperation& op)
|
||||||
|
@ -344,8 +425,8 @@ ROperation ApplyOperator(int n,ROperation**pops,ROperation (*func)(const ROperat
|
||||||
|
|
||||||
ROperation RFunction::operator()(const ROperation& op)
|
ROperation RFunction::operator()(const ROperation& op)
|
||||||
{
|
{
|
||||||
/* Code to use to replace explcitly instead of using a pointer to
|
/* Code to use to replace explicitly instead of using a pointer to
|
||||||
if(nvars!=op.NMembers()||type==-1||type==0)return ErrVal;
|
if(nvars!=op.NMembers()||type==-1||type==0||type==2)return ErrVal;
|
||||||
ROperation op2=*pop;int i;
|
ROperation op2=*pop;int i;
|
||||||
RVar**ppvar2=new PRVar[nvars];char s[11]="";
|
RVar**ppvar2=new PRVar[nvars];char s[11]="";
|
||||||
for(i=0;i<nvars;i++){
|
for(i=0;i<nvars;i++){
|
||||||
|
@ -364,24 +445,29 @@ ROperation RFunction::operator()(const ROperation& op)
|
||||||
return op2;
|
return op2;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Auxiliary string functions
|
//Auxiliary string functions=====================================================
|
||||||
|
|
||||||
void SupprSpaces(char*&s)//Deletes the old string
|
// Remove spaces, tabs and line feeds (deletes the old string)
|
||||||
|
void SupprSpaces(char*&s)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for(i=0;s[i];i++)if(s[i]==' '||s[i]=='\t'||s[i]=='\n')DelStr(s,i--);
|
for(i=0;s[i];i++)if(s[i]==' '||s[i]=='\t'||s[i]=='\n')DelStr(s,i--);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tell if a char is part of a decimal literal (decimal digits and decimal dot).
|
||||||
signed char IsNumeric(char c)
|
signed char IsNumeric(char c)
|
||||||
{if(c!='0'&&c!='1'&&c!='2'&&c!='3'&&c!='4'
|
{
|
||||||
&&c!='5'&&c!='6'&&c!='7'&&c!='8'&&c!='9'&&c!='.')return 0;
|
if((c<'0'||c>'9')&&c!='.')
|
||||||
return 1;
|
return 0;
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tell if a string is a decimal literal (TODO: fix positive answer even when multiple dots).
|
||||||
signed char IsTNumeric(char *s)
|
signed char IsTNumeric(char *s)
|
||||||
{int i;for(i=0;i<(int)strlen(s);i++)if(!IsNumeric(s[i]))return 0;return 1;
|
{int i;for(i=0;i<(int)strlen(s);i++)if(!IsNumeric(s[i]))return 0;return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Searchs the corresponding bracket of an opening bracket
|
||||||
int SearchCorOpenbracket(char*s,int n) //Searchs the corresponding bracket of an opening bracket
|
int SearchCorOpenbracket(char*s,int n) //Searchs the corresponding bracket of an opening bracket
|
||||||
{if(n>=(int)strlen(s)-1)return -1;
|
{if(n>=(int)strlen(s)-1)return -1;
|
||||||
int i,c=1;
|
int i,c=1;
|
||||||
|
@ -392,6 +478,7 @@ for(i=n+1;s[i];i++){
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Searchs the corresponding bracket of a closing bracket
|
||||||
int SearchCorClosebracket(char*s,int n) //Searchs the corresponding bracket of a closing bracket
|
int SearchCorClosebracket(char*s,int n) //Searchs the corresponding bracket of a closing bracket
|
||||||
{if(n<1)return -1;
|
{if(n<1)return -1;
|
||||||
int i,c=1;
|
int i,c=1;
|
||||||
|
@ -414,22 +501,26 @@ int SearchOperator(char*s,ROperator op)
|
||||||
case Div:opc='/';break;
|
case Div:opc='/';break;
|
||||||
case Pow:opc='^';break;
|
case Pow:opc='^';break;
|
||||||
case NthRoot:opc='#';break;
|
case NthRoot:opc='#';break;
|
||||||
case E10:opc='E';break;
|
case E10:opc='E';break;
|
||||||
default:return -1;
|
default:return -1;
|
||||||
};
|
};
|
||||||
int i;
|
int i;
|
||||||
for(i=(int)strlen(s)-1;i>=0;i--){
|
for(i=(int)strlen(s)-1;i>=0;i--){
|
||||||
if(s[i]==opc&&(op!=Sub||i&&s[i-1]==')'))return i;
|
if(s[i]==opc&&(op!=Sub||(i&&s[i-1]==')')))return i;
|
||||||
if(s[i]==')'){i=SearchCorClosebracket(s,i);if(i==-1)return -1;};
|
if(s[i]==')'){i=SearchCorClosebracket(s,i);if(i==-1)return -1;};
|
||||||
};
|
};
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimplifyStr(char*&s) //Warning : deletes the old string
|
void SimplifyStr(char*&s) //Warning : deletes the old string
|
||||||
{if(!strlen(s))return;
|
{
|
||||||
|
// Nothing more to do if string is empty
|
||||||
|
if(!strlen(s))return;
|
||||||
|
// Remove useless matching parenthesis (1st and last char)
|
||||||
char*s1=s,*s2=s+strlen(s);signed char ind=0;
|
char*s1=s,*s2=s+strlen(s);signed char ind=0;
|
||||||
if(s1[0]=='('&&SearchCorOpenbracket(s1,0)==s2-s1-1){
|
if(s1[0]=='('&&SearchCorOpenbracket(s1,0)==s2-s1-1){
|
||||||
s1++;s2--;ind=1;}
|
s1++;s2--;ind=1;}
|
||||||
|
// Return an empty string if nothing remains
|
||||||
if(s1==s2)
|
if(s1==s2)
|
||||||
{
|
{
|
||||||
delete[]s;
|
delete[]s;
|
||||||
|
@ -437,7 +528,9 @@ if(s1==s2)
|
||||||
s[0]=0;
|
s[0]=0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// Remove any leading spaces
|
||||||
if(s1[0]==' '){ind=1;while(s1[0]==' '&&s1<s2)s1++;}
|
if(s1[0]==' '){ind=1;while(s1[0]==' '&&s1<s2)s1++;}
|
||||||
|
// Return an empty string if nothing remains
|
||||||
if(s1==s2)
|
if(s1==s2)
|
||||||
{
|
{
|
||||||
delete[]s;
|
delete[]s;
|
||||||
|
@ -445,14 +538,19 @@ if(s1==s2)
|
||||||
s[0]=0;
|
s[0]=0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// Remove any ending spaces
|
||||||
if(*(s2-1)==' '){ind=1;while(s2>s1&&*(s2-1)==' ')s2--;}
|
if(*(s2-1)==' '){ind=1;while(s2>s1&&*(s2-1)==' ')s2--;}
|
||||||
*s2=0;
|
*s2=0;
|
||||||
|
// Replace input string by simplified one
|
||||||
s1=CopyStr(s1);delete[]s;s=s1;
|
s1=CopyStr(s1);delete[]s;s=s1;
|
||||||
|
// Continue simplification (recursive) if needed
|
||||||
if(ind)SimplifyStr(s);
|
if(ind)SimplifyStr(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
int max(int a, int b){return (a>b?a:b);}
|
int max(int a, int b){return (a>b?a:b);}
|
||||||
|
|
||||||
|
// Detect the name of a variable from the given list, and return its length ;
|
||||||
|
// the longest possible name is kept (xyz wins against xy)
|
||||||
int IsVar(const char*s,int n,int nvar,PRVar*ppvar)
|
int IsVar(const char*s,int n,int nvar,PRVar*ppvar)
|
||||||
{
|
{
|
||||||
if(n<0||n>(int)strlen(s))return 0;
|
if(n<0||n>(int)strlen(s))return 0;
|
||||||
|
@ -461,6 +559,7 @@ int IsVar(const char*s,int n,int nvar,PRVar*ppvar)
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Detect the name of a standard function, and return its length
|
||||||
int IsFunction(const char*s,int n)
|
int IsFunction(const char*s,int n)
|
||||||
{
|
{
|
||||||
if(CompStr(s,n,"sin")||CompStr(s,n,"cos")||CompStr(s,n,"exp")
|
if(CompStr(s,n,"sin")||CompStr(s,n,"cos")||CompStr(s,n,"exp")
|
||||||
|
@ -474,15 +573,17 @@ int IsFunction(const char*s,int n)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Detect the name of a function (be it a user defined one from the given list, or a standard one),
|
||||||
|
// and return its length ; the longest possible name is kept (xyz wins against xy)
|
||||||
|
// Limitations: standard functions are searched first, and may mask user defined ones
|
||||||
|
// whose name begins with a standard one (ex: user "sine" masked by standard "sin")
|
||||||
|
// WARNING: IF PATCHED TO DO OTHERWISE, SHOULD BE PATCHED TOGETHER WITH THE
|
||||||
|
// PARSER BELOW which treats standard functions before user-defined ones
|
||||||
int IsFunction(const char*s,int n,int nfunc,PRFunction*ppfunc)
|
int IsFunction(const char*s,int n,int nfunc,PRFunction*ppfunc)
|
||||||
//Not recognized if a user-defined function is eg "sine" ie begins like
|
|
||||||
//a standard function
|
|
||||||
//IF PATCHED TO DO OTHERWISE, SHOULD BE PATCHED TOGETHER WITH THE
|
|
||||||
//PARSER BELOW which treats standard functions before user-defined ones
|
|
||||||
{
|
{
|
||||||
int l=IsFunction(s,n);
|
int l=IsFunction(s,n);
|
||||||
if(l)return l;
|
if(l)return l;
|
||||||
int i;l=0;
|
int i;
|
||||||
for(i=0;i<nfunc;i++)if(CompStr(s,n,ppfunc[i]->name))l=max(l,strlen(ppfunc[i]->name));
|
for(i=0;i<nfunc;i++)if(CompStr(s,n,ppfunc[i]->name))l=max(l,strlen(ppfunc[i]->name));
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
@ -492,49 +593,68 @@ signed char IsFunction(ROperator op)
|
||||||
op==Atan||op==Asin||op==Acos||op==Atan||op==Sqrt||op==Opp);
|
op==Atan||op==Asin||op==Acos||op==Atan||op==Sqrt||op==Opp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Enclose numbers between parenthesis (deletes the old string).
|
||||||
void IsolateVars(char*&s,int nvar,PRVar*ppvar,int nfunc,PRFunction*ppfunc)//Deletes the old string
|
void IsolateVars(char*&s,int nvar,PRVar*ppvar,int nfunc,PRFunction*ppfunc)//Deletes the old string
|
||||||
{
|
{
|
||||||
int i,j;
|
int i,j;
|
||||||
i=0;
|
i=0;
|
||||||
for(i=0;s[i];i++){
|
for(i=0;s[i];i++){
|
||||||
|
// Jump over a (...) bloc if any
|
||||||
if(s[i]=='('){i=SearchCorOpenbracket(s,i);if(i==-1)return;continue;};
|
if(s[i]=='('){i=SearchCorOpenbracket(s,i);if(i==-1)return;continue;};
|
||||||
|
// When detecting a variable or constant name, if no longer function name can match,
|
||||||
|
// and if enclose it between ( and )
|
||||||
if(((j=IsVar(s,i,nvar,ppvar))>IsFunction(s,i,nfunc,ppfunc))||((CompStr(s,i,"pi")||CompStr(s,i,"PI")||CompStr(s,i,"Pi"))&&(j=2))){
|
if(((j=IsVar(s,i,nvar,ppvar))>IsFunction(s,i,nfunc,ppfunc))||((CompStr(s,i,"pi")||CompStr(s,i,"PI")||CompStr(s,i,"Pi"))&&(j=2))){
|
||||||
InsStr(s,i,'(');InsStr(s,i+j+1,')');i+=j+1;continue;};
|
InsStr(s,i,'(');InsStr(s,i+j+1,')');i+=j+1;continue;};
|
||||||
if(IsFunction(s,i,nfunc,ppfunc)){i+=IsFunction(s,i,nfunc,ppfunc)-1;if(!s[i])return;continue;};
|
if((j=IsFunction(s,i,nfunc,ppfunc))){i+=j-1;if(!s[i])return;continue;};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Enclose numbers between parenthesis (deletes the old string).
|
||||||
void IsolateNumbers(char*&s,int nvar,RVar**ppvar,int nfunc,RFunction**ppfunc)//Deletes the old string
|
void IsolateNumbers(char*&s,int nvar,RVar**ppvar,int nfunc,RFunction**ppfunc)//Deletes the old string
|
||||||
{
|
{
|
||||||
int i,i2,ind=0,t1,t2;
|
int i,i2=0,ind=0,t1,t2;
|
||||||
for(i=0;s[i];i++){
|
for(i=0;s[i];i++){
|
||||||
|
// When detecting the end of a number, enclose it between ( and )
|
||||||
if(ind&&!IsNumeric(s[i])){ind=0;InsStr(s,i2,'(');i++;InsStr(s,i,')');continue;};
|
if(ind&&!IsNumeric(s[i])){ind=0;InsStr(s,i2,'(');i++;InsStr(s,i,')');continue;};
|
||||||
|
// Jump over a variable or a function name if any
|
||||||
t1=IsVar(s,i,nvar,ppvar);t2=IsFunction(s,i,nfunc,ppfunc);
|
t1=IsVar(s,i,nvar,ppvar);t2=IsFunction(s,i,nfunc,ppfunc);
|
||||||
if(t1||t2){i+=max(t1,t2)-1;continue;};
|
if(t1||t2){i+=max(t1,t2)-1;continue;};
|
||||||
|
// Jump over a (...) bloc if any (the remainder of the function "call")
|
||||||
if(s[i]=='('){i=SearchCorOpenbracket(s,i);if(i==-1)return;continue;};
|
if(s[i]=='('){i=SearchCorOpenbracket(s,i);if(i==-1)return;continue;};
|
||||||
|
// Here, we detect the beginning of a number
|
||||||
if(!ind&&IsNumeric(s[i])){i2=i;ind=1;};
|
if(!ind&&IsNumeric(s[i])){i2=i;ind=1;};
|
||||||
};
|
};
|
||||||
|
// If the end of a number has not yet been detected, now it _is_, so enclose it between ( and )
|
||||||
if(ind)InsStr(s,i2,'(');i++;InsStr(s,i,')');
|
if(ind)InsStr(s,i2,'(');i++;InsStr(s,i,')');
|
||||||
}
|
}
|
||||||
|
|
||||||
ROperation::ROperation(char*sp,int nvar,PRVar*ppvarp,int nfuncp,PRFunction*ppfuncp)
|
ROperation::ROperation(const char*sp,int nvar,PRVar*ppvarp,int nfuncp,PRFunction*ppfuncp)
|
||||||
{
|
{
|
||||||
ValC=ErrVal;mmb1=NULL;mmb2=NULL;pvar=NULL;op=ErrOp;pvarval=NULL;containfuncflag=0;pfunc=NULL;pinstr=NULL;pvals=NULL;ppile=NULL;pfuncpile=NULL;
|
ValC=ErrVal;mmb1=NULL;mmb2=NULL;pvar=NULL;op=ErrOp;pvarval=NULL;containfuncflag=0;pfunc=NULL;pinstr=NULL;pvals=NULL;ppile=NULL;pfuncpile=NULL;
|
||||||
int i,j,k,l;signed char flag=1;
|
int i,j,k,l;signed char flag=1;
|
||||||
char*s=CopyStr(sp),*s1=NULL,*s2=NULL;
|
char*s=CopyStr(sp),*s1=NULL,*s2=NULL;
|
||||||
|
// Simplify formula and remove leading : and ; (why ?)
|
||||||
SimplifyStr(s);if(!s[0]||!strcmp(s,"Error")){goto fin;}
|
SimplifyStr(s);if(!s[0]||!strcmp(s,"Error")){goto fin;}
|
||||||
while(s[0]==':'||s[0]==';'){
|
while(s[0]==':'||s[0]==';'){
|
||||||
s1=CopyStr(s+1);delete[]s;s=s1;s1=NULL;
|
s1=CopyStr(s+1);delete[]s;s=s1;s1=NULL;
|
||||||
SimplifyStr(s);if(!s[0]||!strcmp(s,"Error")){goto fin;}
|
SimplifyStr(s);if(!s[0]||!strcmp(s,"Error")){goto fin;}
|
||||||
}
|
}
|
||||||
|
// Case 1: Formula = Integer or decimal litteral, or predefined constant litteral (pi)
|
||||||
if(IsTNumeric(s)){op=Num;ValC=atof(s);mmb1=NULL;mmb2=NULL;goto fin;};
|
if(IsTNumeric(s)){op=Num;ValC=atof(s);mmb1=NULL;mmb2=NULL;goto fin;};
|
||||||
if(EqStr(s,"pi")||EqStr(s,"PI")||EqStr(s,"Pi"))
|
if(EqStr(s,"pi")||EqStr(s,"PI")||EqStr(s,"Pi"))
|
||||||
{op=Num;ValC=3.141592653589793238462643383279L;mmb1=NULL;mmb2=NULL;goto fin;};
|
{op=Num;ValC=3.141592653589793238462643383279L;mmb1=NULL;mmb2=NULL;goto fin;};
|
||||||
|
// Case 2: Formula = Variable with a name that is longer than a matching user defined or standard
|
||||||
|
// function (Note: remaining chars are ignored if any !).
|
||||||
if(IsFunction(s,0,nfuncp,ppfuncp)<IsVar(s,0,nvar,ppvarp))
|
if(IsFunction(s,0,nfuncp,ppfuncp)<IsVar(s,0,nvar,ppvarp))
|
||||||
for(i=0;i<nvar;i++)if(EqStr(s,(*(ppvarp+i))->name))
|
for(i=0;i<nvar;i++)if(EqStr(s,(*(ppvarp+i))->name))
|
||||||
{pvar=ppvarp[i];pvarval=pvar->pval;op=Var;mmb1=NULL;mmb2=NULL;goto fin;};
|
{pvar=ppvarp[i];pvarval=pvar->pval;op=Var;mmb1=NULL;mmb2=NULL;goto fin;};
|
||||||
|
// Case 3: Something else.
|
||||||
for(k=0;s[k];k++){
|
for(k=0;s[k];k++){
|
||||||
|
// Jump over a (...) block.
|
||||||
if(s[k]=='('){k=SearchCorOpenbracket(s,k);if(k==-1)break;continue;};
|
if(s[k]=='('){k=SearchCorOpenbracket(s,k);if(k==-1)break;continue;};
|
||||||
|
// Detect a function (user defined or standard one), with a name that is longer
|
||||||
|
// than the one of any matching variable => add a : or ; at the end of its name
|
||||||
|
// (; if f(...) notation used, : if ????)
|
||||||
if((l=IsFunction(s,k,nfuncp,ppfuncp))&&l>=IsVar(s,k,nvar,ppvarp)){
|
if((l=IsFunction(s,k,nfuncp,ppfuncp))&&l>=IsVar(s,k,nvar,ppvarp)){
|
||||||
i=k+l;while(s[i]==' ')i++;
|
i=k+l;while(s[i]==' ')i++;
|
||||||
if(s[i]=='('){
|
if(s[i]=='('){
|
||||||
|
@ -543,38 +663,49 @@ ROperation::ROperation(char*sp,int nvar,PRVar*ppvarp,int nfuncp,PRFunction*ppfun
|
||||||
}else if(s[i]!=':'&&s[i]!=';'){InsStr(s,i,':');k=i;}
|
}else if(s[i]!=':'&&s[i]!=';'){InsStr(s,i,':');k=i;}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Enclose any number, constant (Pi) and var name between parenthesis,
|
||||||
|
// and remove any (useless) space, tab or new line.
|
||||||
IsolateNumbers(s,nvar,ppvarp,nfuncp,ppfuncp);
|
IsolateNumbers(s,nvar,ppvarp,nfuncp,ppfuncp);
|
||||||
if(nvar)IsolateVars(s,nvar,ppvarp,nfuncp,ppfuncp);
|
if(nvar)IsolateVars(s,nvar,ppvarp,nfuncp,ppfuncp);
|
||||||
SupprSpaces(s);
|
SupprSpaces(s);
|
||||||
|
// Case 3a: "," binary operator (Juxtaposition)
|
||||||
i=SearchOperator(s,Juxt);
|
i=SearchOperator(s,Juxt);
|
||||||
if(i!=-1){s1=MidStr(s,0,i-1);s2=MidStr(s,i+1,strlen(s)-1);
|
if(i!=-1){s1=MidStr(s,0,i-1);s2=MidStr(s,i+1,strlen(s)-1);
|
||||||
op=Juxt;mmb1=new ROperation(s1,nvar,ppvarp,nfuncp,ppfuncp);
|
op=Juxt;mmb1=new ROperation(s1,nvar,ppvarp,nfuncp,ppfuncp);
|
||||||
mmb2=new ROperation(s2,nvar,ppvarp,nfuncp,ppfuncp);goto fin;
|
mmb2=new ROperation(s2,nvar,ppvarp,nfuncp,ppfuncp);goto fin;
|
||||||
};
|
};
|
||||||
|
// Case 3b: "+" binary operator (Addition)
|
||||||
i=SearchOperator(s,Add);
|
i=SearchOperator(s,Add);
|
||||||
if(i!=-1){s1=MidStr(s,0,i-1);s2=MidStr(s,i+1,strlen(s)-1);
|
if(i!=-1){s1=MidStr(s,0,i-1);s2=MidStr(s,i+1,strlen(s)-1);
|
||||||
op=Add;mmb1=new ROperation(s1,nvar,ppvarp,nfuncp,ppfuncp);
|
op=Add;mmb1=new ROperation(s1,nvar,ppvarp,nfuncp,ppfuncp);
|
||||||
mmb2=new ROperation(s2,nvar,ppvarp,nfuncp,ppfuncp);goto fin;
|
mmb2=new ROperation(s2,nvar,ppvarp,nfuncp,ppfuncp);goto fin;
|
||||||
};
|
};
|
||||||
|
// Case 3c: "-" binary operator (Substraction)
|
||||||
i=SearchOperator(s,Sub);
|
i=SearchOperator(s,Sub);
|
||||||
if(i!=-1){
|
if(i!=-1){
|
||||||
s1=MidStr(s,0,i-1);s2=MidStr(s,i+1,strlen(s)-1);
|
s1=MidStr(s,0,i-1);s2=MidStr(s,i+1,strlen(s)-1);
|
||||||
op=Sub;mmb1=new ROperation(s1,nvar,ppvarp,nfuncp,ppfuncp);
|
op=Sub;mmb1=new ROperation(s1,nvar,ppvarp,nfuncp,ppfuncp);
|
||||||
mmb2=new ROperation(s2,nvar,ppvarp,nfuncp,ppfuncp);goto fin;
|
mmb2=new ROperation(s2,nvar,ppvarp,nfuncp,ppfuncp);goto fin;
|
||||||
};
|
};
|
||||||
|
// Case 3d: "-" unary operator (Negation)
|
||||||
if(s[0]=='-'){s2=MidStr(s,1,strlen(s)-1);
|
if(s[0]=='-'){s2=MidStr(s,1,strlen(s)-1);
|
||||||
op=Opp;mmb1=NULL;
|
op=Opp;mmb1=NULL;
|
||||||
mmb2=new ROperation(s2,nvar,ppvarp,nfuncp,ppfuncp);goto fin;
|
mmb2=new ROperation(s2,nvar,ppvarp,nfuncp,ppfuncp);goto fin;
|
||||||
};
|
};
|
||||||
|
// Enclose function "calls" between parenthesis
|
||||||
for(i=0;s[i];i++){
|
for(i=0;s[i];i++){
|
||||||
|
// Jump over a (...) block.
|
||||||
if(s[i]=='('){i=SearchCorOpenbracket(s,i);if(i==-1)break;continue;};
|
if(s[i]=='('){i=SearchCorOpenbracket(s,i);if(i==-1)break;continue;};
|
||||||
|
// Detecting a function "call" :
|
||||||
if(IsFunction(s,i,nfuncp,ppfuncp)){
|
if(IsFunction(s,i,nfuncp,ppfuncp)){
|
||||||
k=i+IsFunction(s,i,nfuncp,ppfuncp);while(s[k]==' ')k++;
|
k=i+IsFunction(s,i,nfuncp,ppfuncp);while(s[k]==' ')k++; // Ignore spaces (Is it usefull, as SupprSpaces was called before ?)
|
||||||
|
// f(...) notation => enclose it between parenthesis (=> "(f(...))" )
|
||||||
if(s[k]==';'){
|
if(s[k]==';'){
|
||||||
// s=DelStr(s,k);
|
// s=DelStr(s,k);
|
||||||
j=k;while(s[j]!='(')j++;
|
j=k;while(s[j]!='(')j++;
|
||||||
j=SearchCorOpenbracket(s,j);
|
j=SearchCorOpenbracket(s,j);
|
||||||
if(j!=-1){InsStr(s,j,')');InsStr(s,i,'(');i=j+2;}
|
if(j!=-1){InsStr(s,j,')');InsStr(s,i,'(');i=j+2;}
|
||||||
|
// ??? => enclose it between parenthesis (=> "(???)" )
|
||||||
}else if(s[k]==':'){
|
}else if(s[k]==':'){
|
||||||
// s=DelStr(s,k);
|
// s=DelStr(s,k);
|
||||||
for(j=k;s[j];j++)
|
for(j=k;s[j];j++)
|
||||||
|
@ -591,8 +722,10 @@ ROperation::ROperation(char*sp,int nvar,PRVar*ppvarp,int nfuncp,PRFunction*ppfun
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Add explicit multiply operator "*" anywhere implicit ( (...)<here>(...) )
|
||||||
for(i=0;s[i]&&s[i+1];i++)if(s[i]==')'&&s[i+1]=='(')
|
for(i=0;s[i]&&s[i+1];i++)if(s[i]==')'&&s[i+1]=='(')
|
||||||
InsStr(s,++i,'*');
|
InsStr(s,++i,'*');
|
||||||
|
// Case 3e: Standard or user defined function
|
||||||
if(s[0]=='('&&SearchCorOpenbracket(s,0)==(int)strlen(s)-1){
|
if(s[0]=='('&&SearchCorOpenbracket(s,0)==(int)strlen(s)-1){
|
||||||
if(CompStr(s,1,"exp")){op=Exp;s2=MidStr(s,4,strlen(s)-2);}
|
if(CompStr(s,1,"exp")){op=Exp;s2=MidStr(s,4,strlen(s)-2);}
|
||||||
else if(CompStr(s,1,"abs")){op=Abs;s2=MidStr(s,4,strlen(s)-2);}
|
else if(CompStr(s,1,"abs")){op=Abs;s2=MidStr(s,4,strlen(s)-2);}
|
||||||
|
@ -622,21 +755,25 @@ ROperation::ROperation(char*sp,int nvar,PRVar*ppvarp,int nfuncp,PRFunction*ppfun
|
||||||
if(op==Fun)if(mmb2->NMembers()!=pfunc->nvars){op=ErrOp;mmb1=NULL;mmb2=NULL;goto fin;}
|
if(op==Fun)if(mmb2->NMembers()!=pfunc->nvars){op=ErrOp;mmb1=NULL;mmb2=NULL;goto fin;}
|
||||||
goto fin;
|
goto fin;
|
||||||
};
|
};
|
||||||
|
// Case 3f: "*" binary operator (Multiplication)
|
||||||
i=SearchOperator(s,Mult);
|
i=SearchOperator(s,Mult);
|
||||||
if(i!=-1){s1=MidStr(s,0,i-1);s2=MidStr(s,i+1,strlen(s)-1);
|
if(i!=-1){s1=MidStr(s,0,i-1);s2=MidStr(s,i+1,strlen(s)-1);
|
||||||
op=Mult;mmb1=new ROperation(s1,nvar,ppvarp,nfuncp,ppfuncp);
|
op=Mult;mmb1=new ROperation(s1,nvar,ppvarp,nfuncp,ppfuncp);
|
||||||
mmb2=new ROperation(s2,nvar,ppvarp,nfuncp,ppfuncp);goto fin;
|
mmb2=new ROperation(s2,nvar,ppvarp,nfuncp,ppfuncp);goto fin;
|
||||||
};
|
};
|
||||||
|
// Case 3g: "/" binary operator (Division)
|
||||||
i=SearchOperator(s,Div);
|
i=SearchOperator(s,Div);
|
||||||
if(i!=-1){s1=MidStr(s,0,i-1);s2=MidStr(s,i+1,strlen(s)-1);
|
if(i!=-1){s1=MidStr(s,0,i-1);s2=MidStr(s,i+1,strlen(s)-1);
|
||||||
op=Div;mmb1=new ROperation(s1,nvar,ppvarp,nfuncp,ppfuncp);
|
op=Div;mmb1=new ROperation(s1,nvar,ppvarp,nfuncp,ppfuncp);
|
||||||
mmb2=new ROperation(s2,nvar,ppvarp,nfuncp,ppfuncp);goto fin;
|
mmb2=new ROperation(s2,nvar,ppvarp,nfuncp,ppfuncp);goto fin;
|
||||||
};
|
};
|
||||||
|
// Case 3h: "^" binary operator (Power)
|
||||||
i=SearchOperator(s,Pow);
|
i=SearchOperator(s,Pow);
|
||||||
if(i!=-1){s1=MidStr(s,0,i-1);s2=MidStr(s,i+1,strlen(s)-1);
|
if(i!=-1){s1=MidStr(s,0,i-1);s2=MidStr(s,i+1,strlen(s)-1);
|
||||||
op=Pow;mmb1=new ROperation(s1,nvar,ppvarp,nfuncp,ppfuncp);
|
op=Pow;mmb1=new ROperation(s1,nvar,ppvarp,nfuncp,ppfuncp);
|
||||||
mmb2=new ROperation(s2,nvar,ppvarp,nfuncp,ppfuncp);goto fin;
|
mmb2=new ROperation(s2,nvar,ppvarp,nfuncp,ppfuncp);goto fin;
|
||||||
};
|
};
|
||||||
|
// Case 3i: "#" binary operator (Square or N>2 th root)
|
||||||
i=SearchOperator(s,NthRoot);
|
i=SearchOperator(s,NthRoot);
|
||||||
if(i!=-1){s1=MidStr(s,0,i-1);s2=MidStr(s,i+1,strlen(s)-1);
|
if(i!=-1){s1=MidStr(s,0,i-1);s2=MidStr(s,i+1,strlen(s)-1);
|
||||||
if(i==0||s[i-1]!=')')
|
if(i==0||s[i-1]!=')')
|
||||||
|
@ -644,12 +781,17 @@ ROperation::ROperation(char*sp,int nvar,PRVar*ppvarp,int nfuncp,PRFunction*ppfun
|
||||||
{op=NthRoot;mmb1=new ROperation(s1,nvar,ppvarp,nfuncp,ppfuncp);};
|
{op=NthRoot;mmb1=new ROperation(s1,nvar,ppvarp,nfuncp,ppfuncp);};
|
||||||
mmb2=new ROperation(s2,nvar,ppvarp,nfuncp,ppfuncp);goto fin;
|
mmb2=new ROperation(s2,nvar,ppvarp,nfuncp,ppfuncp);goto fin;
|
||||||
};
|
};
|
||||||
|
// Case 3k: "E" binary operator (power of 10)
|
||||||
i=SearchOperator(s,E10);
|
i=SearchOperator(s,E10);
|
||||||
if(i!=-1){s1=MidStr(s,0,i-1);s2=MidStr(s,i+1,strlen(s)-1);
|
if(i!=-1){s1=MidStr(s,0,i-1);s2=MidStr(s,i+1,strlen(s)-1);
|
||||||
op=E10;mmb1=new ROperation(s1,nvar,ppvarp,nfuncp,ppfuncp);
|
op=E10;mmb1=new ROperation(s1,nvar,ppvarp,nfuncp,ppfuncp);
|
||||||
mmb2=new ROperation(s2,nvar,ppvarp,nfuncp,ppfuncp);goto fin;
|
mmb2=new ROperation(s2,nvar,ppvarp,nfuncp,ppfuncp);goto fin;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Other cases: Error.
|
||||||
op=ErrOp;mmb1=NULL;mmb2=NULL;
|
op=ErrOp;mmb1=NULL;mmb2=NULL;
|
||||||
|
|
||||||
|
//
|
||||||
fin:
|
fin:
|
||||||
BuildCode();
|
BuildCode();
|
||||||
delete[]s;if(s1!=NULL)delete[] s1;if(s2!=NULL)delete[]s2;
|
delete[]s;if(s1!=NULL)delete[] s1;if(s2!=NULL)delete[]s2;
|
||||||
|
@ -677,6 +819,7 @@ int operator==(const RFunction& f1,const RFunction& f2)
|
||||||
if(f1.type!=f2.type)return 0;
|
if(f1.type!=f2.type)return 0;
|
||||||
if(f1.type==-1)return 1; // Nonfunction==nonfunction
|
if(f1.type==-1)return 1; // Nonfunction==nonfunction
|
||||||
if(f1.type==0)return (f1.pfuncval==f2.pfuncval&&EqStr(f1.name,f2.name));
|
if(f1.type==0)return (f1.pfuncval==f2.pfuncval&&EqStr(f1.name,f2.name));
|
||||||
|
if(f1.type==2)return (f1.pfuncobjval==f2.pfuncobjval&&EqStr(f1.name,f2.name));
|
||||||
if(f1.op!=f2.op)return 0;
|
if(f1.op!=f2.op)return 0;
|
||||||
if(!EqStr(f1.name,f2.name))return 0;
|
if(!EqStr(f1.name,f2.name))return 0;
|
||||||
if(f1.nvars!=f2.nvars)return 0;
|
if(f1.nvars!=f2.nvars)return 0;
|
||||||
|
@ -761,7 +904,7 @@ signed char ROperation::HasError(const ROperation*pop) const
|
||||||
|
|
||||||
int ROperation::NMembers() const //Number of members for an operation like a,b,c...
|
int ROperation::NMembers() const //Number of members for an operation like a,b,c...
|
||||||
{
|
{
|
||||||
if(op==Fun)return(pfunc->type==1?pfunc->op.NMembers():pfunc->type==0?1:0);
|
if(op==Fun)return(pfunc->type==1?pfunc->op.NMembers():pfunc->type==0?1:pfunc->type==2?pfunc->nvars:0);
|
||||||
if(op!=Juxt)return 1;else if(mmb2==NULL)return 0;else return 1+mmb2->NMembers();
|
if(op!=Juxt)return 1;else if(mmb2==NULL)return 0;else return 1+mmb2->NMembers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -823,7 +966,7 @@ ROperation ROperation::Diff(const RVar& var) const
|
||||||
case Asin:return(mmb2->Diff(var)/sqrt(1-((*mmb2)^2)));
|
case Asin:return(mmb2->Diff(var)/sqrt(1-((*mmb2)^2)));
|
||||||
case Acos:return(-mmb2->Diff(var)/sqrt(1-((*mmb2)^2)));
|
case Acos:return(-mmb2->Diff(var)/sqrt(1-((*mmb2)^2)));
|
||||||
case Abs:return(mmb2->Diff(var)*(*mmb2)/(*this));
|
case Abs:return(mmb2->Diff(var)*(*mmb2)/(*this));
|
||||||
case Fun:if(pfunc->type==-1||pfunc->type==0)return ErrVal;
|
case Fun:if(pfunc->type==-1||pfunc->type==0||pfunc->type==2)return ErrVal;
|
||||||
if(pfunc->nvars==0)return 0.;
|
if(pfunc->nvars==0)return 0.;
|
||||||
else if(pfunc->op.NMembers()>1){
|
else if(pfunc->op.NMembers()>1){
|
||||||
j=pfunc->op.NMembers();
|
j=pfunc->op.NMembers();
|
||||||
|
@ -832,7 +975,7 @@ ROperation ROperation::Diff(const RVar& var) const
|
||||||
op2=ApplyOperator(pfunc->nvars,ppop1,&operator,);
|
op2=ApplyOperator(pfunc->nvars,ppop1,&operator,);
|
||||||
for(i=0;i<pfunc->nvars;i++)delete ppop1[i];
|
for(i=0;i<pfunc->nvars;i++)delete ppop1[i];
|
||||||
delete[]ppop1;
|
delete[]ppop1;
|
||||||
return op2;
|
return op2;
|
||||||
}else{
|
}else{
|
||||||
ppop1=new ROperation*[pfunc->nvars];
|
ppop1=new ROperation*[pfunc->nvars];
|
||||||
for(i=0;i<pfunc->nvars;i++){
|
for(i=0;i<pfunc->nvars;i++){
|
||||||
|
@ -844,7 +987,7 @@ ROperation ROperation::Diff(const RVar& var) const
|
||||||
op2=ApplyOperator(pfunc->nvars,ppop1,&::operator+);
|
op2=ApplyOperator(pfunc->nvars,ppop1,&::operator+);
|
||||||
for(i=0;i<pfunc->nvars;i++)delete ppop1[i];
|
for(i=0;i<pfunc->nvars;i++)delete ppop1[i];
|
||||||
delete[]ppop1;
|
delete[]ppop1;
|
||||||
return op2;
|
return op2;
|
||||||
// In the obtained expression, f' will have been replaced with its expression but f will remain pointing to itself ; this could cause some trouble if changing f afterwards
|
// In the obtained expression, f' will have been replaced with its expression but f will remain pointing to itself ; this could cause some trouble if changing f afterwards
|
||||||
}
|
}
|
||||||
default:return ErrVal;
|
default:return ErrVal;
|
||||||
|
@ -866,8 +1009,8 @@ char* ROperation::Expr() const
|
||||||
if(mmb2!=NULL){s2=mmb2->Expr();n+=strlen(s2);g=IsFunction(mmb2->op);}
|
if(mmb2!=NULL){s2=mmb2->Expr();n+=strlen(s2);g=IsFunction(mmb2->op);}
|
||||||
s=new char[n];
|
s=new char[n];
|
||||||
switch(op){
|
switch(op){
|
||||||
case Num:return ValToStr(ValC);
|
case Num:delete[]s;return ValToStr(ValC);
|
||||||
case Var:return CopyStr(pvar->name);
|
case Var:delete[]s;return CopyStr(pvar->name);
|
||||||
case Juxt:sprintf(s,"%s , %s",s1,s2);break;
|
case Juxt:sprintf(s,"%s , %s",s1,s2);break;
|
||||||
case Add:
|
case Add:
|
||||||
f=f||(mmb1->op==Juxt);
|
f=f||(mmb1->op==Juxt);
|
||||||
|
@ -982,7 +1125,7 @@ char* ROperation::Expr() const
|
||||||
case Fun:
|
case Fun:
|
||||||
sprintf(s,"%s(%s)",pfunc->name,s2);
|
sprintf(s,"%s(%s)",pfunc->name,s2);
|
||||||
break;
|
break;
|
||||||
default:return CopyStr("Error");
|
default:delete[]s;return CopyStr("Error");
|
||||||
};
|
};
|
||||||
if(s1!=NULL)delete[] s1;if(s2!=NULL)delete[] s2;
|
if(s1!=NULL)delete[] s1;if(s2!=NULL)delete[] s2;
|
||||||
return s;
|
return s;
|
||||||
|
@ -1063,7 +1206,7 @@ double ROperation::Val() const
|
||||||
{
|
{
|
||||||
pfoncld*p1=pinstr;double**p2=pvals,*p3=ppile-1;PRFunction*p4=pfuncpile;
|
pfoncld*p1=pinstr;double**p2=pvals,*p3=ppile-1;PRFunction*p4=pfuncpile;
|
||||||
for(;*p1!=NULL;p1++)
|
for(;*p1!=NULL;p1++)
|
||||||
if(*p1==&NextVal)*(++p3)=**(p2++);else
|
if(*p1==&NextVal)*(++p3)=**(p2++);else
|
||||||
if(*p1==&RFunc) ApplyRFunc(*(p4++),p3);
|
if(*p1==&RFunc) ApplyRFunc(*(p4++),p3);
|
||||||
else (**p1)(p3);
|
else (**p1)(p3);
|
||||||
return *p3;
|
return *p3;
|
||||||
|
@ -1158,6 +1301,7 @@ void ROperation::BuildCode()
|
||||||
if(pvals!=NULL){delete[]pvals;pvals=NULL;}//does not delete pvals[0] in case it was to be deleted... (no way to know)
|
if(pvals!=NULL){delete[]pvals;pvals=NULL;}//does not delete pvals[0] in case it was to be deleted... (no way to know)
|
||||||
if(ppile!=NULL){delete[]ppile;ppile=NULL;}
|
if(ppile!=NULL){delete[]ppile;ppile=NULL;}
|
||||||
if(pfuncpile!=NULL){delete[]pfuncpile;pfuncpile=NULL;}
|
if(pfuncpile!=NULL){delete[]pfuncpile;pfuncpile=NULL;}
|
||||||
|
|
||||||
switch(op){
|
switch(op){
|
||||||
case ErrOp:pinstr=new pfoncld[2];pinstr[0]=&NextVal;pinstr[1]=NULL;
|
case ErrOp:pinstr=new pfoncld[2];pinstr[0]=&NextVal;pinstr[1]=NULL;
|
||||||
pvals=new double*[2];pvals[0]=new double(ErrVal);pvals[1]=NULL;
|
pvals=new double*[2];pvals[0]=new double(ErrVal);pvals[1]=NULL;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
|
|
||||||
mathexpr.h version 2.0
|
mathexpr.h version 2.1
|
||||||
|
|
||||||
Copyright (c) 1997-2000 Yann OLLIVIER
|
Copyright (c) 1997-2000 Yann OLLIVIER
|
||||||
|
|
||||||
|
@ -12,6 +12,12 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* 2009 changes by Jean-Philippe Meuret <jpmeuret@free.fr> for Qatsh
|
||||||
|
- added EFunction class to support external function with any number of parameters
|
||||||
|
- ROperation::ROperation(const char*,int,PRVar*,int,PRFunction*) :
|
||||||
|
changed 1st arg from 'char*' to 'const char*' for GCC 4.2 (deprecated conversion)
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef _MATHEXPR_H
|
#ifndef _MATHEXPR_H
|
||||||
#define _MATHEXPR_H
|
#define _MATHEXPR_H
|
||||||
|
|
||||||
|
@ -79,7 +85,7 @@ class ROperation{
|
||||||
ROperation(const ROperation&);
|
ROperation(const ROperation&);
|
||||||
ROperation(double);
|
ROperation(double);
|
||||||
ROperation(const RVar&);
|
ROperation(const RVar&);
|
||||||
ROperation(char*sp,int nvarp=0,PRVar*ppvarp=NULL,int nfuncp=0,PRFunction*ppfuncp=NULL);
|
ROperation(const char*sp,int nvarp=0,PRVar*ppvarp=NULL,int nfuncp=0,PRFunction*ppfuncp=NULL);
|
||||||
~ROperation();
|
~ROperation();
|
||||||
double Val() const;
|
double Val() const;
|
||||||
signed char ContainVar(const RVar&) const;
|
signed char ContainVar(const RVar&) const;
|
||||||
|
@ -114,15 +120,30 @@ class ROperation{
|
||||||
ROperation Substitute(const RVar&,const ROperation&) const;
|
ROperation Substitute(const RVar&,const ROperation&) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class EFunction{
|
||||||
|
public:
|
||||||
|
unsigned nvars;
|
||||||
|
double* pvars;
|
||||||
|
EFunction(unsigned nvarsp);
|
||||||
|
virtual ~EFunction();
|
||||||
|
double operator()(double* pvarsp);
|
||||||
|
double operator()(double var1p, ...); // Warning: Only double vars supported
|
||||||
|
// Compute function value from pvars[] after operator () filled it
|
||||||
|
// => (re)implement only this function
|
||||||
|
virtual double Val() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
class RFunction{
|
class RFunction{
|
||||||
double*buf;
|
double*buf;
|
||||||
public:
|
public:
|
||||||
signed char type;
|
signed char type; //Compute the value through: 2=>pfuncobjval, 1=>op, 0=>pfuncval, -1=>Can't do it.
|
||||||
double ((*pfuncval)(double));
|
double ((*pfuncval)(double));
|
||||||
|
EFunction* pfuncobjval;
|
||||||
ROperation op;int nvars;RVar** ppvar;
|
ROperation op;int nvars;RVar** ppvar;
|
||||||
char*name;
|
char*name;
|
||||||
RFunction();
|
RFunction();
|
||||||
RFunction(double ((*)(double)));
|
RFunction(double ((*)(double)));
|
||||||
|
RFunction(EFunction& efunc);
|
||||||
RFunction(const ROperation& opp,RVar* pvarp);
|
RFunction(const ROperation& opp,RVar* pvarp);
|
||||||
RFunction(const ROperation& opp,int nvarsp,RVar**ppvarp);
|
RFunction(const ROperation& opp,int nvarsp,RVar**ppvarp);
|
||||||
RFunction(const RFunction&);
|
RFunction(const RFunction&);
|
||||||
|
|
Loading…
Reference in New Issue