84 #define MAX_CTABLE 255
86 #define STD_FNC_NUM 19
89 #define GET_VALUE_BUFSIZE 500
104 return( atan2(x, val) );
108 static double f_pow(
double x,
double val)
110 return( pow(x, val) );
114 static double f_gt(
double x,
double val)
116 return( x > val ? 1.0 : 0.0 );
120 static double f_lt(
double x,
double val)
122 return( x < val ? 1.0 : 0.0 );
126 static double f_eq(
double x,
double val)
128 return( fabs(x - val) <
EPSILON ? 1.0 : 0.0 );
132 static double f_min(
double a,
double b)
134 return( a < b ? a : b );
138 static double f_max(
double a,
double b)
140 return( a > b ? a : b );
162 static double f_fmod(
double x,
double val)
164 return( fmod(x, val) );
180 static double f_and(
double x,
double y)
182 return( x != 0.0 && y != 0.0 ? 1.0 : 0.0 );
186 static double f_or(
double x,
double y)
188 return( x != 0.0 || y != 0.0 ? 1.0 : 0.0 );
192 static double f_ifelse(
double condition,
double x,
double y)
194 return( condition ? x : y );
248 m_Formula.code = NULL;
249 m_Formula.ctable = NULL;
297 const int nOperators = 35;
301 {
"+" ,
_TL(
"Addition") },
302 {
"-" ,
_TL(
"Subtraction") },
303 {
"*" ,
_TL(
"Multiplication") },
304 {
"/" ,
_TL(
"Division") },
305 {
"abs(x)" ,
_TL(
"Absolute Value") },
306 {
"mod(x, y)" ,
_TL(
"Returns the floating point remainder of x/y") },
307 {
"int(x)" ,
_TL(
"Returns the integer part of floating point value x") },
308 {
"sqr(x)" ,
_TL(
"Square") },
309 {
"sqrt(x)" ,
_TL(
"Square Root") },
310 {
"exp(x)" ,
_TL(
"Exponential") },
311 {
"pow(x, y)" ,
_TL(
"Returns x raised to the power of y") },
312 {
"x ^ y" ,
_TL(
"Returns x raised to the power of y") },
313 {
"ln(x)" ,
_TL(
"Natural Logarithm") },
314 {
"log(x)" ,
_TL(
"Base 10 Logarithm") },
315 {
"pi()" ,
_TL(
"Returns the value of Pi") },
316 {
"sin(x)" ,
_TL(
"Sine, expects radians") },
317 {
"cos(x)" ,
_TL(
"Cosine, expects radians") },
318 {
"tan(x)" ,
_TL(
"Tangent, expects radians") },
319 {
"asin(x)" ,
_TL(
"Arcsine, returns radians") },
320 {
"acos(x)" ,
_TL(
"Arccosine, returns radians") },
321 {
"atan(x)" ,
_TL(
"Arctangent, returns radians") },
322 {
"atan2(x, y)" ,
_TL(
"Arctangent of x/y, returns radians") },
323 {
"min(x, y)" ,
_TL(
"Returns the minimum of values x and y") },
324 {
"max(x, y)" ,
_TL(
"Returns the maximum of values x and y") },
325 {
"gt(x, y)" ,
_TL(
"Returns true (1), if x is greater than y, else false (0)") },
326 {
"x > y" ,
_TL(
"Returns true (1), if x is greater than y, else false (0)") },
327 {
"lt(x, y)" ,
_TL(
"Returns true (1), if x is less than y, else false (0)") },
328 {
"x < y" ,
_TL(
"Returns true (1), if x is less than y, else false (0)") },
329 {
"eq(x, y)" ,
_TL(
"Returns true (1), if x equals y, else false (0)") },
330 {
"x = y" ,
_TL(
"Returns true (1), if x equals y, else false (0)") },
331 {
"and(x, y)" ,
_TL(
"Returns true (1), if both x and y are true (i.e. not 0)") },
332 {
"or(x, y)" ,
_TL(
"Returns true (1), if at least one of both x and y is true (i.e. not 0)") },
333 {
"ifelse(c, x, y)",
_TL(
"Returns x, if condition c is true (i.e. not 0), else y") },
334 {
"rand_u(x, y)" ,
_TL(
"Random number, uniform distribution with minimum x and maximum y") },
335 {
"rand_g(x, y)" ,
_TL(
"Random number, Gaussian distribution with mean x and standard deviation y") }
344 s +=
"<table border=\"0\">";
346 for(i=0; i<nOperators; i++)
350 s +=
"<tr><td><b>" + op +
"</b></td><td>" + Operators[i][1] +
"</td></tr>";
355 for(i=0; !Additional[i][0].
is_Empty(); i++)
359 s +=
"<tr><td><b>" + op +
"</b></td><td>" + Additional[i][1] +
"</td></tr>";
367 for(i=0; i<nOperators; i++)
369 s += Operators[i][0] +
" - " + Operators[i][1] +
"\n";
374 for(i=0; !Additional[i][0].
is_Empty(); i++)
376 s += Additional[i][0] +
" - " + Additional[i][1] +
"\n";
391 if( m_Error_Position < 0 || m_Error_Position >= (
int)m_sFormula.
Length() )
393 Message += m_sFormula;
397 Message += m_sFormula.
Left (m_Error_Position) +
" ["
398 + m_sFormula [m_Error_Position] +
"] "
399 + m_sFormula.
Right(m_sFormula.
Length() - (m_Error_Position + 1));
413 void CSG_Formula::_Set_Error(
const CSG_String &Error)
435 m_Parameters[Var -
'a'] = Value;
441 if( Formula.
Length() > 0 )
445 m_sFormula = Formula;
446 m_Formula = _Translate(Formula,
"abcdefghijklmnopqrstuvwxyz", &m_Length, &m_Error_Position);
448 if( m_Formula.code != NULL )
467 return( _Get_Value(m_Parameters, m_Formula) );
473 double Parameters[32];
475 memcpy(Parameters, m_Parameters, 32 *
sizeof(
double));
477 Parameters[
'x'-
'a'] = x;
479 return( _Get_Value(Parameters, m_Formula) );
491 double Parameters[32];
493 for(
int i=0; i<nValues; i++)
495 Parameters[i] = Values[i];
498 return( _Get_Value(Parameters, m_Formula) );
504 double Parameters[32];
512 Parameters[(*Args++) -
'a'] = va_arg(ap,
double);
517 return( _Get_Value(Parameters, m_Formula) );
521 double CSG_Formula::_Get_Value(
const double *Parameters, TSG_Formula func)
const
525 double *bufp = buffer;
526 char *
function = func.code;
527 double *ctable = func.ctable;
537 switch( *
function++ )
543 *bufp++ = ctable[*
function++];
547 *bufp++ = Parameters[(*
function++) -
'a'];
557 result = y + *(--bufp);
563 result = *(--bufp) - y;
569 result = *(--bufp) * y;
575 result = *(--bufp) / y;
581 result = pow(*(--bufp), y);
587 result = y == *(--bufp) ? 1.0 : 0.0;
593 result = y < *(--bufp) ? 1.0 : 0.0;
599 result = y > *(--bufp) ? 1.0 : 0.0;
605 result = y && *(--bufp) ? 1.0 : 0.0;
611 result = y || *(--bufp) ? 1.0 : 0.0;
616 switch (m_Functions[*
function].nParameters)
669 for(
int i=0; i<
'z'-
'a'; i++)
671 if( m_Vars_Used[i] ==
true )
673 ret.
Append((
char)(i +
'a'));
696 if( nParameters < 0 || nParameters > 3 )
698 _Set_Error(
_TL(
"invalid number of parameters"));
705 for(pFunction=m_Functions; pFunction->
Function && strcmp(Name, pFunction->
Name); pFunction++)
719 if( (pFunction - m_Functions) >=
MAX_CTABLE - 1 )
721 _Set_Error(
_TL(
"function table full"));
726 pFunction->
Name = Name;
742 int CSG_Formula::_Get_Function(
int i,
char *Name,
int *nParameters,
int *bVarying)
744 if( !m_Functions[i].Function )
746 _Set_Error(
_TL(
"index out of bounds"));
751 strcpy(Name , m_Functions[i].Name);
753 *bVarying = m_Functions[i].
bVarying ? 1 : 0;
764 int CSG_Formula::_Get_Function(
const char *Name)
768 for(pFunction=m_Functions; pFunction->Function && strcmp(Name, pFunction->Name); pFunction++)
771 if( pFunction->Function == NULL )
773 _Set_Error(
_TL(
"function not found"));
780 return( (
int)(pFunction - m_Functions) );
791 inline int CSG_Formula::_is_Operand(
char c)
807 inline int CSG_Formula::_is_Operand_Code(
char c)
824 inline int CSG_Formula::_is_Number(
char c)
826 return( isdigit(c) || c ==
'.' || c ==
'E' );
841 CSG_Formula::TSG_Formula CSG_Formula::_Translate(
const char *sourc,
const char *args,
int *leng,
int *error)
843 const char *scan, *scarg;
844 char *result, *source, *code, *nfunc;
847 TSG_Formula returned;
853 returned.code = NULL;
854 returned.ctable = NULL;
857 source = (
char *)
SG_Malloc((strlen(sourc) + 1) *
sizeof(char));
861 _Set_Error(
_TL(
"no memory"));
866 strcpy(source, sourc);
868 for(scan=source; *scan!=
'\0'; scan++)
870 if( islower(*scan) && !isalpha(*(scan + 1)) && (scan == source || !isalpha(*(scan - 1))) )
872 for(scarg=args; *scarg!=
'\0' && *scarg != *scan; scarg++)
877 _Set_Error(
_TL(
"undeclared parameter"));
880 *error = (int)(m_error - source);
890 size_estim = _max_size(source);
892 if( !(code = (
char *)
SG_Malloc(size_estim)) )
894 _Set_Error(
_TL(
"no memory"));
909 _Set_Error(
_TL(
"no memory"));
924 result = _i_trans(code, (
char *)source, (
char *)source + strlen(source));
926 if( !result || m_bError )
928 *error = (int)(m_error ? m_error - source : -1);
940 *leng = (int)(result - code);
942 if( ((*leng) + 1) *
sizeof(char) > size_estim )
944 _Set_Error(
_TL(
"I4: size estimate too small"));
950 else if( ((*leng) + 1) *
sizeof(
char) < size_estim )
952 nfunc = (
char *)
SG_Malloc(((*leng) + 1) *
sizeof(char));
956 memcpy(nfunc, code, ((*leng) + 1) *
sizeof(
char));
964 ctable = (
double *)
SG_Malloc(m_pctable *
sizeof(
double));
968 memcpy(ctable, m_ctable, m_pctable *
sizeof(
double));
982 returned.code = code;
983 returned.ctable = ctable;
1001 char * CSG_Formula::_i_trans(
char *
function,
char *begin,
char *end)
1003 char tempch, *scan, *endf, *tempu, *temp3, *temps = NULL, *par_buf, *paramstr[
MAX_PARMS];
1004 int i, pars, space, n_function;
1009 _Set_Error(
_TL(
"missing operand"));
1014 for(pars = 0, scan = begin; scan < end && pars >= 0; scan++)
1016 if( *scan ==
'(' ) { pars++; }
else
1017 if( *scan ==
')' ) { pars--; }
1020 if( pars < 0 || pars > 0 )
1022 _Set_Error(
_TL(
"unmatched parentheses"));
1027 for(pars = 0, scan = end - 1; scan >= begin; scan--)
1029 if( *scan ==
'(' ) pars++;
else
1030 if( *scan ==
')' ) pars--;
else
1031 if( !pars && (*scan ==
'+' || ((*scan ==
'-') && scan != begin)) && (scan == begin || *(scan - 1) !=
'E') )
1037 if ((tempu = _i_trans(
function, begin, scan)) &&
1038 (temp3 = _i_trans(tempu, scan + 1, end)))
1041 temp3 = _comp_time(
function, temp3, 2);
1051 for (pars = 0, scan = end - 1; scan >= begin; scan--)
1053 if (*scan ==
'(') pars++;
1054 else if (*scan ==
')')
1056 else if (!pars &&(*scan ==
'*' || *scan ==
'/'))
1061 if ((tempu = _i_trans(
function, begin, scan)) &&
1062 (temp3 = _i_trans(tempu, scan + 1, end)))
1065 temp3 = _comp_time(
function, temp3, 2);
1078 tempu = _i_trans(
function, begin + 1, end);
1082 tempu = _comp_time(
function, tempu, 1);
1092 for (pars = 0, scan = end - 1; scan >= begin; scan--)
1094 if (*scan ==
'(') pars++;
1095 else if (*scan ==
')')
1097 else if (!pars &&(*scan ==
'^'))
1099 else if (!pars &&(*scan ==
'='))
1101 else if (!pars &&(*scan ==
'>'))
1103 else if (!pars &&(*scan ==
'<'))
1105 else if (!pars &&(*scan ==
'&'))
1107 else if (!pars &&(*scan ==
'|'))
1113 if ((tempu = _i_trans(
function, begin, scan)) &&
1114 (temp3 = _i_trans(tempu, scan + 1, end)))
1117 temp3 = _comp_time(
function, temp3, 2);
1128 while (isspace(*begin))
1130 while (isspace(*(end - 1)))
1133 if (*begin ==
'(' && *(end - 1) ==
')')
1134 return _i_trans(
function, begin + 1, end - 1);
1136 if (end == begin + 1 && islower(*begin))
1139 *
function++ = *begin;
1145 tempd = strtod(begin, (
char **)&tempu);
1148 if( (
char *)tempu == end )
1153 m_ctable[m_pctable] = tempd;
1154 *
function++ = (char)m_pctable++;
1158 _Set_Error(
_TL(
"too many constants"));
1166 if (!isalpha(*begin) && *begin !=
'_')
1168 _Set_Error(
_TL(
"syntax error"));
1173 for(endf = begin + 1; endf < end &&(isalnum(*endf) || *endf ==
'_'); endf++)
1178 if ((n_function = _Get_Function(begin)) == -1)
1185 if (*endf !=
'(' || *(end - 1) !=
')')
1187 _Set_Error(
_TL(
"improper function syntax"));
1192 if( m_Functions[n_function].nParameters == 0 )
1196 for (scan = endf + 1; scan <(end - 1); scan++)
1197 if (!isspace(*scan))
1202 *
function++ = n_function;
1203 function = _comp_time(
function - 2,
function, 0);
1212 _Set_Error(
_TL(
"too many parameters"));
1218 tempch = *(end - 1);
1220 par_buf = (
char *)
SG_Malloc(
sizeof(
char) * (strlen(endf + 1) + 1));
1224 _Set_Error(
_TL(
"no memory"));
1229 strcpy(par_buf, endf + 1);
1230 *(end - 1) = tempch;
1232 for (i = 0; i < m_Functions[n_function].
nParameters; i++)
1234 if ((temps = _my_strtok((i == 0) ? par_buf : NULL)) == NULL)
1236 paramstr[i] = temps;
1243 _Set_Error(
_TL(
"too few parameters"));
1247 if ((temps = _my_strtok(NULL)) != NULL)
1250 m_error =(temps - par_buf) +(endf + 1);
1251 _Set_Error(
_TL(
"too many parameters"));
1256 for (i = 0; i < m_Functions[n_function].
nParameters; i++)
1257 if( !(tempu = _i_trans(tempu, paramstr[i], paramstr[i] + strlen(paramstr[i]))) )
1259 m_error =(m_error - par_buf) +(endf + 1);
1268 *tempu++ = n_function;
1269 tempu = _comp_time(
function, tempu, m_Functions[n_function].nParameters);
1278 char * CSG_Formula::_comp_time(
char *
function,
char *fend,
int npars)
1286 for (i = 0; i < npars; i++)
1293 if (!((scan == fend -(
sizeof((
char)
'F') +
sizeof(
char))
1294 && *(fend - 2) ==
'F' && m_Functions[*(fend - 1)].bVarying == 0) ||
1295 (scan == fend -
sizeof(
char)
1296 && _is_Operand_Code(*(fend - 1))))
1303 trans.code =
function;
1304 trans.ctable = m_ctable;
1305 tempd = _Get_Value(m_Parameters, trans);
1309 *
function++ =(char) m_pctable;
1310 m_ctable[m_pctable++] = tempd;
1316 int CSG_Formula::_max_size(
const char *source)
1323 const size_t var_size = 2 *
sizeof(char);
1324 const size_t num_size =
sizeof(char) +
sizeof(
double);
1325 const size_t op_size =
sizeof(char);
1326 const size_t end_size =
sizeof(
'\0');
1328 for(
int i=0; i<
'z'-
'a'; i++)
1330 m_Vars_Used[i] =
false;
1333 for(
const char *scan=source; *scan; scan++)
1335 if( isalpha(*scan) && (*scan !=
'E') )
1337 if( isalpha(*(scan + 1)) || isdigit(*(scan + 1)) )
1341 else if( *(scan + 1) ==
'(' )
1348 m_Vars_Used[(int)(*scan -
'a')] =
true;
1353 if( _is_Operand(*source) )
1358 if( *source !=
'\0' )
1360 for(
const char *scan=source+1; *scan; scan++)
1362 if( _is_Operand(*scan) && *(scan - 1) !=
'E' )
1369 const char *scan = source;
1373 if( _is_Number(*scan) || ((*scan ==
'+' || *scan ==
'-') && scan > source && *(scan - 1) ==
'E') )
1378 while( _is_Number(*scan) ||((*scan ==
'+' || *scan ==
'-') && scan > source && *(scan - 1) ==
'E') )
1387 return( numbers*num_size + operators*op_size + functions*num_size + variables*var_size + end_size );
1391 char * CSG_Formula::_my_strtok(
char *s)
1393 static char *token = NULL;
1397 else if( token != NULL )
1402 for(
int pars=0; *s !=
'\0' && (*s !=
',' || pars != 0); s++)
1404 if (*s ==
'(') ++pars;
1405 if (*s ==
')') --pars;
1416 char *next_token = s + 1;