[genius] Fri Jul 24 16:01:28 2009 Jiri (George) Lebl <jirka 5z com>
- From: George Lebl <jirka src gnome org>
- To: svn-commits-list gnome org
- Subject: [genius] Fri Jul 24 16:01:28 2009 Jiri (George) Lebl <jirka 5z com>
- Date: Fri, 24 Jul 2009 21:01:54 +0000 (UTC)
commit e54271704eb0566d95895bc32efac506e1db3afc
Author: Jiri (George) Lebl <jirka 5z com>
Date: Fri Jul 24 16:01:38 2009 -0500
Fri Jul 24 16:01:28 2009 Jiri (George) Lebl <jirka 5z com>
* src/calc.c, src/compil.c: Correctly compile/decompile all the new
function attributes
* src/calc.c: correctly print out the local stuff, handle local node
correctly when outside of functions
* src/funclib.c, src/graphing.c: handle eof errors from parsing
things correctly without dying.
* src/dict.c, src/eval.c, src/structs.h: is_local generally should
not be moved around with the function. Also correctly copy/free
all the other attributes when needed as well.
* src/eval.c: Set arguments BEFORE extradict. This should never
be an issue, but it feels more correct.
* src/dict.c: when the subst list becomes empty, remove from subst
list to avoid unnecessary lookups
* lib/*/*.gel: update and fix for the [] operator
* src/geniustests.txt: Add some testcases
* src/symbolic.c: just a comment change
ChangeLog | 27 +++++
TODO | 7 +
lib/calculus/differentiation.gel | 6 +-
lib/calculus/integration.gel | 5 +-
lib/calculus/limits.gel | 8 +-
lib/combinatorics/factorial.gel | 2 +-
lib/combinatorics/misc.gel | 6 +-
lib/linear_algebra/bilinear_forms.gel | 6 +-
lib/symbolic/differentiation.gel | 4 +-
src/calc.c | 199 ++++++++++++++++++++++++++++++---
src/compil.c | 61 +++++++++--
src/dict.c | 71 ++++++++++--
src/eval.c | 63 +++++------
src/funclib.c | 28 ++++-
src/geniustests.txt | 25 ++++
src/graphing.c | 8 ++
src/structs.h | 2 +
src/symbolic.c | 1 +
18 files changed, 439 insertions(+), 90 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 94093c8..5ad09a2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,30 @@
+Fri Jul 24 16:01:28 2009 Jiri (George) Lebl <jirka 5z com>
+
+ * src/calc.c, src/compil.c: Correctly compile/decompile all the new
+ function attributes
+
+ * src/calc.c: correctly print out the local stuff, handle local node
+ correctly when outside of functions
+
+ * src/funclib.c, src/graphing.c: handle eof errors from parsing
+ things correctly without dying.
+
+ * src/dict.c, src/eval.c, src/structs.h: is_local generally should
+ not be moved around with the function. Also correctly copy/free
+ all the other attributes when needed as well.
+
+ * src/eval.c: Set arguments BEFORE extradict. This should never
+ be an issue, but it feels more correct.
+
+ * src/dict.c: when the subst list becomes empty, remove from subst
+ list to avoid unnecessary lookups
+
+ * lib/*/*.gel: update and fix for the [] operator
+
+ * src/geniustests.txt: Add some testcases
+
+ * src/symbolic.c: just a comment change
+
Thu Jul 23 18:35:28 2009 Jiri (George) Lebl <jirka 5z com>
* src/parse.y, src/eval.c, src/dict.c, src/structs.h: Add an optional
diff --git a/TODO b/TODO
index 1338faa..ac86184 100644
--- a/TODO
+++ b/TODO
@@ -1,3 +1,10 @@
+-- check fourier stuff
+-- document new things in 1.0.7
+-- check modified functions in the library
+
+
+
+
* Logfiles and/or save session
* Whack the readline nonsense in the GUI
* Native polynomial operation
diff --git a/lib/calculus/differentiation.gel b/lib/calculus/differentiation.gel
index 10b934f..874917b 100644
--- a/lib/calculus/differentiation.gel
+++ b/lib/calculus/differentiation.gel
@@ -128,7 +128,7 @@ function NumericalDerivative(f,x0) =
(
local *;
# FIXME: perhaps check differentiability first, but then we're doing so many limits already
- NumericalLimitAtInfinity (`(n)=(TwoSidedFivePointFormula(f,x0,2.0^(-n))),
+ NumericalLimitAtInfinity (`(n)[f,x0]=(TwoSidedFivePointFormula(f,x0,2.0^(-n))),
Identity,
DerivativeTolerance,
DerivativeSFS,
@@ -141,7 +141,7 @@ NDerivative = NumericalDerivative
function NumericalLeftDerivative(f,x0) =
(
local *;
- NumericalLimitAtInfinity (`(n)=(OneSidedFivePointFormula(f,x0,-(2.0^(-n)))),
+ NumericalLimitAtInfinity (`(n)[f,x0]=(OneSidedFivePointFormula(f,x0,-(2.0^(-n)))),
Identity,
DerivativeTolerance,
DerivativeSFS,
@@ -152,7 +152,7 @@ SetHelp("NumericalLeftDerivative","calculus","Attempt to calculate numerical lef
function NumericalRightDerivative(f,x0) =
(
local *;
- NumericalLimitAtInfinity (`(n)=(OneSidedFivePointFormula(f,x0,2.0^(-n))),
+ NumericalLimitAtInfinity (`(n)[f,x0]=(OneSidedFivePointFormula(f,x0,2.0^(-n))),
Identity,
DerivativeTolerance,
DerivativeSFS,
diff --git a/lib/calculus/integration.gel b/lib/calculus/integration.gel
index 39cf3e6..537480e 100644
--- a/lib/calculus/integration.gel
+++ b/lib/calculus/integration.gel
@@ -65,4 +65,7 @@ SetHelp ("NumericalIntegralFunction", "parameters", "The function used for numer
parameter NumericalIntegralFunction = `CompositeSimpsonsRule
SetHelp ("NumericalIntegral", "calculus", "Integration by rule set in NumericalIntegralFunction of f from a to b using NumericalIntegralSteps steps")
-function NumericalIntegral(f,a,b) = (local *;NumericalIntegralFunction call (f,a,b,NumericalIntegralSteps))
+function NumericalIntegral(f,a,b) = (
+ local *;
+ NumericalIntegralFunction call (f,a,b,NumericalIntegralSteps)
+)
diff --git a/lib/calculus/limits.gel b/lib/calculus/limits.gel
index 9f717bc..fcb25b6 100644
--- a/lib/calculus/limits.gel
+++ b/lib/calculus/limits.gel
@@ -21,8 +21,8 @@
# Limits:
SetHelp ("NumericalLimitAtInfinity", "calculus", "Attempt to calculate the limit of f(step_fun(i)) as i goes from 1 to N")
-function NumericalLimitAtInfinity(_f,step_fun,tolerance,successive_for_success,N) =
-# this evaluates _f(step_fun(i)) as i goes from 1 to N.
+function NumericalLimitAtInfinity(f,step_fun,tolerance,successive_for_success,N) =
+# this evaluates f(step_fun(i)) as i goes from 1 to N.
# If s_f_s of the pairwise successive differences are less than tolerance, then
# it returns the last value; if this doesn't happen, it returns Null.
# INPUT: N had better be at least 1
@@ -30,10 +30,10 @@ function NumericalLimitAtInfinity(_f,step_fun,tolerance,successive_for_success,N
# bounded oscillation (like sin(x))
(
local *;
- current_limit = _f(step_fun(1));
+ current_limit = f(step_fun(1));
number_of_consecutive_differences_within_tolerance = 0;
for i = 2 to N do (
- new_limit = _f(step_fun(i));
+ new_limit = f(step_fun(i));
if (|new_limit-current_limit| < tolerance) then (
number_of_consecutive_differences_within_tolerance = number_of_consecutive_differences_within_tolerance+1
) else (
diff --git a/lib/combinatorics/factorial.gel b/lib/combinatorics/factorial.gel
index 934976e..9133087 100644
--- a/lib/combinatorics/factorial.gel
+++ b/lib/combinatorics/factorial.gel
@@ -96,7 +96,7 @@ function Multinomial(v,arg...) = (
else
m = [v, arg];
- MatrixSum(m)!/MatrixProduct(ApplyOverMatrix(m,`(x)=x!))
+ MatrixSum(m)!/MatrixProduct(ApplyOverMatrix(m,`(x)[]=x!))
)
SetHelp("Pascal","combinatorics","Get the pascal's triangle as a matrix");
diff --git a/lib/combinatorics/misc.gel b/lib/combinatorics/misc.gel
index 15439f0..0ce24a3 100644
--- a/lib/combinatorics/misc.gel
+++ b/lib/combinatorics/misc.gel
@@ -14,13 +14,13 @@ function Hofstadter(n) = (
(error("Hofstadter: argument not a positive integer");bailout);
# reason for doing this is that it's just plain faster then calling self
# again
- function _h (n) = (
+ function h (n) = (
if n <= 2 then
1
else
- _h(n - _h(n-1)) + _h(n - _h(n-2))
+ h(n - h(n-1)) + h(n - h(n-2))
);
- _h (n)
+ h (n)
)
diff --git a/lib/linear_algebra/bilinear_forms.gel b/lib/linear_algebra/bilinear_forms.gel
index 686cb50..2e5b8f1 100644
--- a/lib/linear_algebra/bilinear_forms.gel
+++ b/lib/linear_algebra/bilinear_forms.gel
@@ -30,10 +30,10 @@ function VectorAngle(v,w,B...) =
#FIXME: check parameters
SetHelp ("BilinearFormFunction", "linear_algebra", "Return a function that evaluates two vectors with respect to the bilinear form given by A")
-function BilinearFormFunction(A)=(`(v,w)=(v.'*A*w)@(1))
+function BilinearFormFunction(A)=(`(v,w)[A]=(v.'*A*w)@(1))
SetHelp ("SesquilinearFormFunction", "linear_algebra", "Return a function that evaluates two vectors with respect to the sesquilinear form given by A")
-function SesquilinearFormFunction(A)=(`(v,w)=(v'*A*w)@(1))
+function SesquilinearFormFunction(A)=(`(v,w)[A]=(v'*A*w)@(1))
# Projection onto a vector space
# Projection of vector v onto subspace W given a sesquilinear form B
@@ -65,7 +65,7 @@ function GramSchmidt(v,B...) =
# if you don't give anything, assume standard inner product
if IsNull(B) or IsNull(B@(1)) then P=HermitianProduct
# If it's a matrix, then use the sesquilinear form defined by that matrix
- else if IsMatrix(B@(1)) then (function P(u,w)=SesquilinearForm(u,B@(1),w))
+ else if IsMatrix(B@(1)) then (function P(u,w)[B]=SesquilinearForm(u,B@(1),w))
# If B is just some function, assume that it's an inner product
else if elements(B) > 1 or not IsFunction(B@(1)) then (error("GramSchmidt: argument B not a function or Matrix");bailout)
else P = B@(1);
diff --git a/lib/symbolic/differentiation.gel b/lib/symbolic/differentiation.gel
index d928e7c..59a0364 100644
--- a/lib/symbolic/differentiation.gel
+++ b/lib/symbolic/differentiation.gel
@@ -38,7 +38,7 @@ SetHelp("SymbolicNthDerivativeTry","symbolic","Attempt to symbolically different
function SymbolicTaylorApproximationFunction(f,x0,n) =
(
- local f,df,c,n,k;
+ local *;
if not IsFunction(f) then
(error("SymbolicTaylorApproximationFunction: argument 1 must be a function");bailout)
else if not IsValue(x0) then
@@ -58,6 +58,6 @@ function SymbolicTaylorApproximationFunction(f,x0,n) =
)
);
tp = PolyToFunction (c);
- `(x) = (tp call (x - x0))
+ `(x)[tp,x0] = (tp call (x - x0))
)
SetHelp("SymbolicTaylorApproximationFunction","symbolic","Attempt to construct the taylor approximation function around x0 to the nth degree.");
diff --git a/src/calc.c b/src/calc.c
index 7dddd4a..7e3ac4a 100644
--- a/src/calc.c
+++ b/src/calc.c
@@ -1318,12 +1318,29 @@ append_func (GelOutput *gelo, GelEFunc *f)
if (f->vararg)
gel_output_string (gelo, "...");
- if G_LIKELY (f->type==GEL_USER_FUNC) {
+ if G_LIKELY (f->type == GEL_USER_FUNC) {
gel_output_string(gelo,")=");
D_ENSURE_USER_BODY (f);
+ if (f->extra_dict != NULL ||
+ f->local_all ||
+ f->local_idents != NULL) {
+ gel_output_string(gelo,"(");
+ }
+ if (f->local_all) {
+ gel_output_string(gelo,"local *;");
+ } else if (f->local_idents != NULL) {
+ GSList *li;
+ gel_output_string(gelo,"local ");
+ for (li = f->local_idents; li != NULL; li = li->next) {
+ GelToken *tok = li->data;
+ if (li != f->local_idents)
+ gel_output_string(gelo,",");
+ gel_output_string (gelo, tok->token);
+ }
+ gel_output_string(gelo,";");
+ }
if (f->extra_dict != NULL) {
GSList *li;
- gel_output_string(gelo,"(");
for (li = f->extra_dict; li != NULL; li = li->next) {
GelEFunc *ff = li->data;
gel_output_string (gelo, ff->id->token);
@@ -1337,7 +1354,9 @@ append_func (GelOutput *gelo, GelEFunc *f)
}
}
gel_print_etree (gelo, f->data.user, FALSE);
- if (f->extra_dict != NULL) {
+ if (f->extra_dict != NULL ||
+ f->local_all ||
+ f->local_idents != NULL) {
gel_output_string(gelo,")");
}
gel_output_string(gelo,")");
@@ -1821,13 +1840,36 @@ compile_funcs_in_dict (FILE *outfile, GSList *dict, gboolean is_extra_dict)
}
if (func->type == GEL_USER_FUNC) {
fprintf (outfile,
- "%c;%d;%s;%s;%d;%d",
+ "%c;%d;%s;%s;n%d;v%d;p%d;o%d;l%d;e%d;b%d",
fs,
(int)strlen (body),
func->id->token,
func->symbolic_id ? func->symbolic_id->token : "*",
(int)func->nargs,
- (int)func->vararg);
+ (int)func->vararg,
+ (int)func->propagate_mod,
+ (int)func->no_mod_all_args,
+ (int)func->local_all,
+ (int)func->never_on_subst_list,
+ (int)func->built_subst_dict);
+ if (func->local_idents == NULL)
+ fprintf (outfile, ";-");
+ for (l = func->local_idents; l != NULL; l = l->next) {
+ GelToken *tok = l->data;
+ if (l != func->local_idents)
+ fprintf (outfile, ",%s", tok->token);
+ else
+ fprintf (outfile, ";%s", tok->token);
+ }
+ if (func->subst_dict == NULL)
+ fprintf (outfile, ";-");
+ for (l = func->subst_dict; l != NULL; l = l->next) {
+ GelToken *tok = l->data;
+ if (l != func->subst_dict)
+ fprintf (outfile, ",%s", tok->token);
+ else
+ fprintf (outfile, ";%s", tok->token);
+ }
for (l = func->named_args; l != NULL; l = l->next) {
GelToken *tok = l->data;
fprintf (outfile, ";%s", tok->token);
@@ -1902,6 +1944,8 @@ gel_compile_all_user_funcs (FILE *outfile)
g_slist_free (funcs);
}
+/* FIXME: function reading is almost identical to that for FUNCTION_NODEs
+ in compile.c We should really unify these! */
static void
load_compiled_fp (const char *file, FILE *fp)
{
@@ -1939,7 +1983,9 @@ load_compiled_fp (const char *file, FILE *fp)
char *p;
char *b2;
GelToken *tok, *symbolic_tok = NULL;
- int size, nargs, vararg;
+ int size, nargs, vararg, propagate_mod, no_mod_all_args;
+ int local_all, never_on_subst_list, built_subst_dict;
+ GSList *local_idents, *subst_dict;
gboolean extra_dict = FALSE;
gboolean parameter = FALSE;
int i;
@@ -2107,7 +2153,7 @@ load_compiled_fp (const char *file, FILE *fp)
continue;
}
nargs = -1;
- sscanf(p,"%d",&nargs);
+ sscanf(p,"n%d",&nargs);
if G_UNLIKELY (nargs == -1) {
gel_errorout (_("Badly formed record"));
continue;
@@ -2120,12 +2166,109 @@ load_compiled_fp (const char *file, FILE *fp)
continue;
}
vararg = -1;
- sscanf(p,"%d",&vararg);
+ sscanf(p,"v%d",&vararg);
if G_UNLIKELY (vararg == -1) {
gel_errorout (_("Badly formed record"));
continue;
}
+ /*propagate_mod*/
+ p = strtok_r (NULL,";", &ptrptr);
+ if (p == NULL) {
+ gel_errorout (_("Badly formed record"));
+ continue;
+ }
+ propagate_mod = -1;
+ sscanf(p,"p%d",&propagate_mod);
+ if G_UNLIKELY (propagate_mod == -1) {
+ gel_errorout (_("Badly formed record"));
+ continue;
+ }
+
+ /*no_mod_all_args*/
+ p = strtok_r (NULL,";", &ptrptr);
+ if (p == NULL) {
+ gel_errorout (_("Badly formed record"));
+ continue;
+ }
+ no_mod_all_args = -1;
+ sscanf(p,"o%d",&no_mod_all_args);
+ if G_UNLIKELY (no_mod_all_args == -1) {
+ gel_errorout (_("Badly formed record"));
+ continue;
+ }
+
+ /*local_all*/
+ p = strtok_r (NULL,";", &ptrptr);
+ if (p == NULL) {
+ gel_errorout (_("Badly formed record"));
+ continue;
+ }
+ local_all = -1;
+ sscanf(p,"l%d",&local_all);
+ if G_UNLIKELY (local_all == -1) {
+ gel_errorout (_("Badly formed record"));
+ continue;
+ }
+
+ /*never_on_subst_list*/
+ p = strtok_r (NULL,";", &ptrptr);
+ if (p == NULL) {
+ gel_errorout (_("Badly formed record"));
+ continue;
+ }
+ never_on_subst_list = -1;
+ sscanf(p,"e%d",&never_on_subst_list);
+ if G_UNLIKELY (never_on_subst_list == -1) {
+ gel_errorout (_("Badly formed record"));
+ continue;
+ }
+
+ /*built_subst_list*/
+ p = strtok_r (NULL,";", &ptrptr);
+ if (p == NULL) {
+ gel_errorout (_("Badly formed record"));
+ continue;
+ }
+ built_subst_dict = -1;
+ sscanf(p,"b%d",&built_subst_dict);
+ if G_UNLIKELY (built_subst_dict == -1) {
+ gel_errorout (_("Badly formed record"));
+ continue;
+ }
+
+ /*local_idents*/
+ p = strtok_r (NULL,";", &ptrptr);
+ if G_UNLIKELY (p == NULL) {
+ gel_errorout (_("Badly formed record"));
+ continue;
+ }
+ local_idents = NULL;
+ if (strcmp (p, "-") != 0) {
+ char **s;
+ s = g_strsplit (p, ",", -1);
+ for (i = 0; s[i] != NULL; i++) {
+ local_idents = g_slist_append (local_idents, d_intern (s[i]));
+ }
+ g_strfreev (s);
+ }
+
+ /*subst_dict*/
+ p = strtok_r (NULL,";", &ptrptr);
+ if G_UNLIKELY (p == NULL) {
+ gel_errorout (_("Badly formed record"));
+ continue;
+ }
+ subst_dict = NULL;
+ if (strcmp (p, "-") != 0) {
+ char **s;
+ s = g_strsplit (p, ",", -1);
+ for (i = 0; s[i] != NULL; i++) {
+ subst_dict = g_slist_append (subst_dict, d_intern (s[i]));
+ }
+ g_strfreev (s);
+ }
+
/*argument names*/
li = NULL;
for(i=0;i<nargs;i++) {
@@ -2170,6 +2313,13 @@ load_compiled_fp (const char *file, FILE *fp)
func = d_makeufunc (tok, NULL, li, nargs, NULL);
func->vararg = vararg ? 1 : 0;
func->symbolic_id = symbolic_tok;
+ func->propagate_mod = propagate_mod ? 1 : 0;
+ func->no_mod_all_args = no_mod_all_args ? 1 : 0;
+ func->local_all = local_all ? 1 : 0;
+ func->never_on_subst_list = never_on_subst_list ? 1 : 0;
+ func->built_subst_dict = built_subst_dict ? 1 : 0;
+ func->subst_dict = subst_dict;
+ func->local_idents = local_idents;
} else /*GEL_VARIABLE_FUNC*/ {
func = d_makevfunc (tok, NULL);
}
@@ -2186,6 +2336,13 @@ load_compiled_fp (const char *file, FILE *fp)
func = d_makeufunc (tok, NULL, li, nargs, NULL);
func->vararg = vararg ? 1 : 0;
func->symbolic_id = symbolic_tok;
+ func->propagate_mod = propagate_mod ? 1 : 0;
+ func->no_mod_all_args = no_mod_all_args ? 1 : 0;
+ func->local_all = local_all ? 1 : 0;
+ func->never_on_subst_list = never_on_subst_list ? 1 : 0;
+ func->built_subst_dict = built_subst_dict ? 1 : 0;
+ func->subst_dict = subst_dict;
+ func->local_idents = local_idents;
} else /*GEL_VARIABLE_FUNC*/ {
func = d_makevfunc(tok,NULL);
}
@@ -3140,18 +3297,32 @@ gel_parseexp (const char *str, FILE *infile, gboolean exec_commands,
stacklen = g_slist_length(gel_parsestack);
- if(stacklen==0) {
- if(finished) *finished = FALSE;
+ if (stacklen == 0) {
+ if (finished != NULL)
+ *finished = FALSE;
return NULL;
}
/*stack is supposed to have only ONE entry*/
- if(stacklen!=1) {
- while(gel_parsestack)
- gel_freetree(gel_stack_pop(&gel_parsestack));
+ if (stacklen != 1) {
+ while (gel_parsestack != NULL)
+ gel_freetree (gel_stack_pop (&gel_parsestack));
if G_UNLIKELY (!testparse)
gel_errorout (_("ERROR: Probably corrupt stack!"));
- if(finished) *finished = FALSE;
+ if (finished != NULL)
+ *finished = FALSE;
+ return NULL;
+ }
+ /* local nodes should not exist now, they should all
+ have been eaten */
+ if (gel_get_local_node (gel_parsestack->data,
+ FALSE /* first_arg */,
+ NULL,
+ NULL)) {
+ gel_freetree (gel_stack_pop (&gel_parsestack));
+ gel_errorout (_("ERROR: 'local' in a wrong place, can only be first statement in a function!"));
+ if (finished != NULL)
+ *finished = TRUE;
return NULL;
}
gel_replace_equals (gel_parsestack->data, FALSE /* in_expression */);
diff --git a/src/compil.c b/src/compil.c
index 8d84c05..0a6f630 100644
--- a/src/compil.c
+++ b/src/compil.c
@@ -136,23 +136,37 @@ gel_compile_node(GelETree *t,GString *gs)
case GEL_FUNCTION_NODE:
g_assert(t->func.func->type==GEL_USER_FUNC);
/*g_assert(t->func.func->id==NULL);*/
- g_string_append_printf (gs, ";%s;%s;%d;%d;%d;%d;%d;",
+ g_string_append_printf (gs,
+ ";%s;%s;n%d;v%d;p%d;o%d;l%d;e%d;b%d",
t->func.func->id ? t->func.func->id->token : "*",
t->func.func->symbolic_id ? t->func.func->symbolic_id->token : "*",
t->func.func->nargs,
t->func.func->vararg,
t->func.func->propagate_mod,
t->func.func->no_mod_all_args,
- t->func.func->local_all);
+ t->func.func->local_all,
+ t->func.func->never_on_subst_list,
+ t->func.func->built_subst_dict);
+ /* Make sure to also update calc compile_funcs_in_dict
+ * and related! */
if (t->func.func->local_idents == NULL)
- g_string_append (gs, "-");
+ g_string_append (gs, ";-");
for (li = t->func.func->local_idents; li != NULL; li = li->next) {
GelToken *tok = li->data;
if (li != t->func.func->local_idents)
g_string_append_printf (gs, ",%s", tok->token);
else
- g_string_append_printf (gs, "%s", tok->token);
+ g_string_append_printf (gs, ";%s", tok->token);
+ }
+ if (t->func.func->subst_dict == NULL)
+ g_string_append (gs, ";-");
+ for (li = t->func.func->subst_dict; li != NULL; li = li->next) {
+ GelToken *tok = li->data;
+ if (li != t->func.func->subst_dict)
+ g_string_append_printf (gs, ",%s", tok->token);
+ else
+ g_string_append_printf (gs, ";%s", tok->token);
}
for (li = t->func.func->named_args; li != NULL; li = li->next) {
GelToken *tok = li->data;
@@ -206,6 +220,8 @@ gel_decompile_node(char **ptrptr)
int propagate_mod = -1;
int no_mod_all_args = -1;
int local_all = -1;
+ int never_on_subst_list = -1;
+ int built_subst_dict = -1;
int quote;
int oper;
int i,j;
@@ -213,7 +229,7 @@ gel_decompile_node(char **ptrptr)
GelMatrixW *m;
GelETree *li = NULL;
GelETree *args;
- GSList *oli, *local_idents;
+ GSList *oli, *local_idents, *subst_dict;
GelEFunc *func;
mpw_t tmp;
@@ -351,31 +367,41 @@ gel_decompile_node(char **ptrptr)
p = strtok_r (NULL,";", ptrptr);
if G_UNLIKELY (!p) return NULL;
nargs = -1;
- sscanf(p,"%d",&nargs);
+ sscanf(p,"n%d",&nargs);
if G_UNLIKELY (nargs==-1) return NULL;
p = strtok_r (NULL,";", ptrptr);
if G_UNLIKELY (!p) return NULL;
- sscanf(p,"%d",&vararg);
+ sscanf(p,"v%d",&vararg);
if G_UNLIKELY (vararg == -1) return NULL;
p = strtok_r (NULL,";", ptrptr);
if G_UNLIKELY (!p) return NULL;
- sscanf(p,"%d",&propagate_mod);
+ sscanf(p,"p%d",&propagate_mod);
if G_UNLIKELY (propagate_mod == -1) return NULL;
p = strtok_r (NULL,";", ptrptr);
if G_UNLIKELY (!p) return NULL;
- sscanf(p,"%d",&no_mod_all_args);
+ sscanf(p,"o%d",&no_mod_all_args);
if G_UNLIKELY (no_mod_all_args == -1) return NULL;
p = strtok_r (NULL,";", ptrptr);
if G_UNLIKELY (p == NULL) return NULL;
- sscanf(p,"%d",&local_all);
+ sscanf(p,"l%d",&local_all);
if G_UNLIKELY (local_all == -1) return NULL;
p = strtok_r (NULL,";", ptrptr);
if G_UNLIKELY (p == NULL) return NULL;
+ sscanf(p,"e%d",&never_on_subst_list);
+ if G_UNLIKELY (never_on_subst_list == -1) return NULL;
+
+ p = strtok_r (NULL,";", ptrptr);
+ if G_UNLIKELY (p == NULL) return NULL;
+ sscanf(p,"b%d",&built_subst_dict);
+ if G_UNLIKELY (built_subst_dict == -1) return NULL;
+
+ p = strtok_r (NULL,";", ptrptr);
+ if G_UNLIKELY (p == NULL) return NULL;
local_idents = NULL;
if (strcmp (p, "-") != 0) {
char **s;
@@ -386,6 +412,18 @@ gel_decompile_node(char **ptrptr)
g_strfreev (s);
}
+ p = strtok_r (NULL,";", ptrptr);
+ if G_UNLIKELY (p == NULL) return NULL;
+ subst_dict = NULL;
+ if (strcmp (p, "-") != 0) {
+ char **s;
+ s = g_strsplit (p, ",", -1);
+ for (i = 0; s[i] != NULL; i++) {
+ subst_dict = g_slist_append (subst_dict, d_intern (s[i]));
+ }
+ g_strfreev (s);
+ }
+
oli = NULL;
for(i=0;i<nargs;i++) {
p = strtok_r (NULL,";", ptrptr);
@@ -412,7 +450,10 @@ gel_decompile_node(char **ptrptr)
func->propagate_mod = propagate_mod ? 1 : 0;
func->no_mod_all_args = no_mod_all_args ? 1 : 0;
func->local_all = local_all ? 1 : 0;
+ func->never_on_subst_list = never_on_subst_list ? 1 : 0;
+ func->built_subst_dict = built_subst_dict ? 1 : 0;
func->local_idents = local_idents;
+ func->subst_dict = subst_dict;
GEL_GET_NEW_NODE(n);
n->type = GEL_FUNCTION_NODE;
diff --git a/src/dict.c b/src/dict.c
index a2ff62e..617a90d 100644
--- a/src/dict.c
+++ b/src/dict.c
@@ -185,6 +185,7 @@ d_copyfunc(GelEFunc *o)
}
n->named_args = g_slist_copy (o->named_args);
n->local_idents = g_slist_copy (o->local_idents);
+ n->subst_dict = g_slist_copy (o->subst_dict);
n->extra_dict = g_slist_copy (o->extra_dict);
for (li = n->extra_dict; li != NULL; li = li->next)
@@ -206,6 +207,9 @@ d_makerealfunc(GelEFunc *o,GelToken *id, gboolean use)
n = g_slice_dup (GelEFunc, o);
+ /* never copy is_local! */
+ n->is_local = 0;
+
n->id = id;
if (o->symbolic_id == NULL)
n->symbolic_id = o->id;
@@ -226,6 +230,7 @@ d_makerealfunc(GelEFunc *o,GelToken *id, gboolean use)
o->extra_dict = NULL;
o->named_args = NULL;
o->local_idents = NULL;
+ o->subst_dict = NULL;
o->nargs = 0;
} else {
GSList *li;
@@ -234,6 +239,7 @@ d_makerealfunc(GelEFunc *o,GelToken *id, gboolean use)
li->data = d_copyfunc (li->data);
n->named_args = g_slist_copy (o->named_args);
n->local_idents = g_slist_copy (o->local_idents);
+ n->subst_dict = g_slist_copy (o->subst_dict);
}
if (n->on_subst_list) {
@@ -268,24 +274,34 @@ d_setrealfunc(GelEFunc *n,GelEFunc *fake, gboolean use)
n->data.user = gel_copynode(fake->data.user);
}
+ n->never_on_subst_list = fake->never_on_subst_list;
+ n->vararg = fake->vararg;
+ n->propagate_mod = fake->propagate_mod;
+ n->no_mod_all_args = fake->no_mod_all_args;
+ n->local_all = fake->local_all;
+ /* Never copy is_local */
+ n->built_subst_dict = fake->built_subst_dict;
+
if(use) {
n->named_args = fake->named_args;
n->local_idents = fake->local_idents;
+ n->subst_dict = fake->subst_dict;
n->nargs = fake->nargs;
fake->named_args = NULL;
fake->local_idents = NULL;
fake->nargs = 0;
- } else {
- n->named_args = g_slist_copy (fake->named_args);
- n->local_idents = g_slist_copy (fake->local_idents);
- n->nargs = fake->nargs;
- }
+ fake->subst_dict = NULL;
- if (use) {
n->extra_dict = fake->extra_dict;
fake->extra_dict = NULL;
} else {
GSList *li;
+
+ n->named_args = g_slist_copy (fake->named_args);
+ n->local_idents = g_slist_copy (fake->local_idents);
+ n->subst_dict = g_slist_copy (fake->subst_dict);
+ n->nargs = fake->nargs;
+
n->extra_dict = g_slist_copy (fake->extra_dict);
for (li = n->extra_dict; li != NULL; li = li->next)
li->data = d_copyfunc (li->data);
@@ -659,6 +675,7 @@ d_freefunc (GelEFunc *n)
g_slist_free (n->named_args);
g_slist_free (n->local_idents);
+ g_slist_free (n->subst_dict);
g_slice_free (GelEFunc, n);
}
@@ -692,6 +709,7 @@ d_replacefunc(GelEFunc *old,GelEFunc *_new)
g_slist_free (old->named_args);
g_slist_free (old->local_idents);
+ g_slist_free (old->subst_dict);
for (li = old->extra_dict; li != NULL; li = li->next) {
d_freefunc (li->data);
@@ -721,9 +739,18 @@ d_set_ref(GelEFunc *n,GelEFunc *ref)
n->type = GEL_REFERENCE_FUNC;
g_slist_free (n->named_args);
g_slist_free (n->local_idents);
+ g_slist_free (n->subst_dict);
n->nargs = 0;
n->named_args = NULL;
- n->local_idents = NULL;
+ n->subst_dict = NULL;
+
+ n->never_on_subst_list = 0;
+ n->vararg = 0;
+ n->propagate_mod = 0;
+ n->no_mod_all_args = 0;
+ n->local_all = 0;
+ /* don't touch is_local */
+ n->built_subst_dict = 0;
n->data.ref = ref;
}
@@ -740,10 +767,20 @@ d_set_value(GelEFunc *n,GelETree *value)
n->type = GEL_VARIABLE_FUNC;
g_slist_free (n->named_args);
g_slist_free (n->local_idents);
+ g_slist_free (n->subst_dict);
n->nargs = 0;
n->named_args = NULL;
n->local_idents = NULL;
-
+ n->subst_dict = NULL;
+
+ n->never_on_subst_list = 0;
+ n->vararg = 0;
+ n->propagate_mod = 0;
+ n->no_mod_all_args = 0;
+ n->local_all = 0;
+ /* don't touch is_local */
+ n->built_subst_dict = 0;
+
n->data.user = value;
}
@@ -776,7 +813,8 @@ d_popcontext (void)
GelContextFrame *of;
if (context.top != 0) {
- for (li = subst; li != NULL; li = li->next) {
+ li = subst;
+ while (li != NULL) {
GelEFunc *func = li->data;
if (context.top == 1)
func->on_subst_list = 0;
@@ -799,9 +837,24 @@ d_popcontext (void)
if (func->context >= context.top)
func->context = context.top - 1;
+ /* If subst_dict goes to NULL, we no
+ * longer need to keep this around on
+ * the subst_lists */
+ if (func->subst_dict == NULL) {
+ if (substlast != NULL) {
+ substlast = g_slist_remove_link (substlast, li);
+ li = substlast->next;
+ } else {
+ subst = g_slist_remove_link (subst, subst);
+ li = subst;
+ }
+ continue;
+ }
+
}
substlast = li;
+ li = li->next;
}
}
diff --git a/src/eval.c b/src/eval.c
index aca3f90..22f7711 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -1306,6 +1306,8 @@ get_func_call_node(GelEFunc *func, GelETree **args, int nargs)
GEL_GET_NEW_NODE(l);
l->type = GEL_FUNCTION_NODE;
l->func.func = d_copyfunc(func);
+ /* never copy is_local */
+ l->func.func->is_local = 0;
l->any.next = NULL;
GEL_GET_NEW_NODE(ret);
@@ -2600,6 +2602,8 @@ make_funccall (GelEFunc *a)
GEL_GET_NEW_NODE (nn);
nn->type = GEL_FUNCTION_NODE;
nn->func.func = d_copyfunc (a);
+ /* never copy is_local */
+ nn->func.func->is_local = 0;
if ( ! nn->func.func->on_subst_list)
nn->func.func->context = -1;
@@ -2798,6 +2802,8 @@ gel_function_from_function (GelEFunc *func, GelETree *l)
GEL_GET_NEW_NODE (n);
n->type = GEL_FUNCTION_NODE;
n->func.func = d_copyfunc (func);
+ /* never copy is_local */
+ n->func.func->is_local = 0;
if ( ! n->func.func->on_subst_list)
n->func.func->context = -1;
@@ -3310,17 +3316,11 @@ iter_do_var(GelCtx *ctx, GelETree *n, GelEFunc *f)
n->type = GEL_FUNCTION_NODE;
/* FIXME: are we ok with passing the token as well? */
- n->func.func = d_makeufunc (f->id /* FIXME: does this need to be NULL */,
- gel_copynode (f->data.user),
- g_slist_copy (f->named_args),
- f->nargs,
- f->extra_dict);
- n->func.func->context = -1;
- n->func.func->vararg = f->vararg;
- if ( ! f->never_on_subst_list &&
- f->on_subst_list &&
- d_curcontext () != 0)
- d_put_on_subst_list (n->func.func);
+ n->func.func = d_copyfunc (f);
+ /* The function can no longer be local */
+ n->func.func->is_local = 0;
+ if ( ! f->on_subst_list)
+ n->func.func->context = -1;
} else if(f->type == GEL_BUILTIN_FUNC) {
GelETree *ret;
gboolean exception = FALSE;
@@ -3332,7 +3332,6 @@ iter_do_var(GelCtx *ctx, GelETree *n, GelEFunc *f)
n->func.func = d_makerealfunc(f,f->id,FALSE);
if ( ! n->func.func->on_subst_list)
n->func.func->context = -1;
- n->func.func->vararg = f->vararg;
/* FIXME: no need for extra_dict right? */
return TRUE;
}
@@ -4549,30 +4548,20 @@ iter_funccallop(GelCtx *ctx, GelETree *n, gboolean *repushed)
d_addcontext (f);
- EDEBUG(" USER FUNC CONTEXT PUSHED TO ADD EXTRA DICT");
-
- /* add extra dictionary stuff */
- for (li = f->extra_dict; li != NULL; li = li->next) {
- GelEFunc *func = d_copyfunc (li->data);
- func->context = d_curcontext ();
- d_addfunc (func);
- }
-
- EDEBUG(" USER FUNC EXTRA DICT ADDED, TO PUSH ARGS ON CONTEXT STACK");
+ EDEBUG(" USER FUNC TO ADD ARGS TO DICT");
- /*push arguments on context stack*/
+ /*add arguments to dictionary*/
li = f->named_args;
for(ali = n->op.args->any.next;
ali != NULL;
ali = ali->any.next) {
- GelEFunc *vf;
if (li->next == NULL) {
last_arg = li->data;
if (f->vararg)
break;
}
if (ali->type == GEL_FUNCTION_NODE) {
- vf = d_addfunc(d_makerealfunc(ali->func.func,li->data,FALSE));
+ d_addfunc(d_makerealfunc(ali->func.func,li->data,FALSE));
} else if(ali->type == GEL_OPERATOR_NODE &&
ali->op.oper == GEL_E_REFERENCE) {
GelETree *t = ali->op.args;
@@ -4582,12 +4571,10 @@ iter_funccallop(GelCtx *ctx, GelETree *n, gboolean *repushed)
gel_errorout (_("Referencing an undefined variable %s!"), t->id.id->token);
goto funccall_done_ok;
}
- vf = d_addfunc(d_makereffunc(li->data,rf));
+ d_addfunc(d_makereffunc(li->data,rf));
} else {
- vf = d_addfunc(d_makevfunc(li->data,gel_copynode(ali)));
+ d_addfunc(d_makevfunc(li->data,gel_copynode(ali)));
}
- if (f->local_all)
- vf->is_local = 1;
li = li->next;
if (li == NULL)
break;
@@ -4596,7 +4583,6 @@ iter_funccallop(GelCtx *ctx, GelETree *n, gboolean *repushed)
EDEBUG(" USER FUNC ABOUT TO HANDLE VARARG");
if (f->vararg) {
- GelEFunc *vf;
if (last_arg == NULL) {
li = g_slist_last (f->named_args);
g_assert (li != NULL);
@@ -4604,7 +4590,7 @@ iter_funccallop(GelCtx *ctx, GelETree *n, gboolean *repushed)
}
/* no extra argument */
if (n->op.nargs == f->nargs) {
- vf = d_addfunc (d_makevfunc (last_arg, gel_makenum_null ()));
+ d_addfunc (d_makevfunc (last_arg, gel_makenum_null ()));
} else {
GelETree *nn;
GelMatrix *m;
@@ -4624,12 +4610,20 @@ iter_funccallop(GelCtx *ctx, GelETree *n, gboolean *repushed)
nn->mat.quoted = FALSE;
nn->mat.matrix = gel_matrixw_new_with_matrix (m);
- vf = d_addfunc (d_makevfunc (last_arg, nn));
+ d_addfunc (d_makevfunc (last_arg, nn));
}
- if (f->local_all)
- vf->is_local = 1;
}
+ EDEBUG(" USER FUNC CONTEXT PUSHED TO ADD EXTRA DICT");
+
+ /* add extra dictionary stuff */
+ for (li = f->extra_dict; li != NULL; li = li->next) {
+ GelEFunc *func = d_copyfunc (li->data);
+ func->context = d_curcontext ();
+ d_addfunc (func);
+ }
+
+
EDEBUG(" CREATING LOCAL VARS");
for (li = f->local_idents;
@@ -6759,6 +6753,7 @@ build_extradict (GSList *funclist, GSList *toklist)
GelEFunc *func = d_lookup_global (id);
if G_LIKELY (func != NULL) {
GelEFunc *f = d_copyfunc (func);
+ /* note that local stays local! */
if ( ! f->on_subst_list)
f->context = -1;
funclist = g_slist_prepend (funclist, f);
diff --git a/src/funclib.c b/src/funclib.c
index c920727..45098c4 100644
--- a/src/funclib.c
+++ b/src/funclib.c
@@ -5679,18 +5679,26 @@ end_of_simpson:
static GelETree *
Parse_op (GelCtx *ctx, GelETree * * a, gboolean *exception)
{
+ GelETree *r;
+
if (a[0]->type == GEL_NULL_NODE)
return gel_makenum_null ();
if G_UNLIKELY ( ! check_argument_string (a, 0, "Parse"))
return NULL;
- return gel_parseexp (a[0]->str.str,
- NULL /* infile */,
- FALSE /* exec_commands */,
- FALSE /* testparse */,
- NULL /* finished */,
- NULL /* dirprefix */);
+ r = gel_parseexp (a[0]->str.str,
+ NULL /* infile */,
+ FALSE /* exec_commands */,
+ FALSE /* testparse */,
+ NULL /* finished */,
+ NULL /* dirprefix */);
+
+ /* Have to reset the error here, else we may die */
+ gel_error_num = GEL_NO_ERROR;
+ gel_got_eof = FALSE;
+
+ return r;
}
static GelETree *
@@ -5711,6 +5719,14 @@ Evaluate_op (GelCtx *ctx, GelETree * * a, gboolean *exception)
NULL /* finished */,
NULL /* dirprefix */);
+ /* Have to reset the error here, else we may die */
+ gel_error_num = GEL_NO_ERROR;
+ gel_got_eof = FALSE;
+
+ if (et == NULL)
+ return NULL;
+
+
return gel_eval_etree (ctx, et);
}
diff --git a/src/geniustests.txt b/src/geniustests.txt
index 3b420c6..167838b 100644
--- a/src/geniustests.txt
+++ b/src/geniustests.txt
@@ -689,7 +689,10 @@ false == 0 true
|cos(pi+0.1i) +1| < 0.1 true
|sin(pi+0.1i)| < 0.11 true
NDerivative(`(x)=x^2,1) 2.0
+Derivative(`(x)=x^2,1) 2
NDerivative(`(x)=x^2,10) 20.0
+Derivative(`(x)=x^2,10) 20
+Derivative(`(x)=float(x)^2,10) 20.0
function f(x) = x^2 ; NDerivative(f,10) 20.0
function _f(x) = x^2 ; NDerivative(_f,10) 20.0
function f(x) = x^2 ; IsDifferentiable(f,10) true
@@ -944,6 +947,28 @@ a=7;(function f(x)=(b=9));f(8);UndefineAll();UserVariables()+0 ((null)+0)
parameter FloatPrecision = 888 (parameter FloatPrecision = 888)
parameter foo = 888 888
y=9;(function g(x)[y]=(y+1));y=0;g(0) 10
+a=9;function f(x)[a]=(local *;x+a) (`(x)=(local *;a=9;(x+a)))
+a=9;function f(x)[a]=(local x;x+a) (`(x)=(local x;a=9;(x+a)))
+a=9;function f(x)[a]=(local x,h,g;x+a) (`(x)=(local x,h,g;a=9;(x+a)))
+function f(x)=(local x,h,g;x+a) (`(x)=(local x,h,g;(x+a)))
+function f(x)=(local *;x+a) (`(x)=(local *;(x+a)))
+Parse("local *") Parse("local *")
+Evaluate("local *") Evaluate("local *")
+Parse("local *;x") Parse("local *;x")
+Evaluate("local *;x") Evaluate("local *;x")
+NumericalIntegral(`(x)=x^3,0,1) 0.25
+NumericalIntegral(`(x)=x^3,-1,1)+1 1.0
+NumericalLimitAtInfinity (atan,`(n)=2^n,10^(-20),10,10000) 1.57079632679
+LeftLimit (UnitStep,0) 0
+RightLimit (UnitStep,0) 1
+UnitStep(-1) 0
+UnitStep(1) 1
+Limit(UnitStep,0)+1 ((null)+1)
+Limit(UnitStep,1) 1
+Limit(UnitStep,-1) 0
+Limit (cos,pi) -1.0
+round(100*InfiniteSum(`(n)=2^(-n),1,1)) 100
+func=1;start=2;inc=3;round(100*InfiniteSum(`(n)=inc-func-start+2^(-n),1,1)) 100
load "nullspacetest.gel" true
load "longtest.gel" true
load "testprec.gel" true
diff --git a/src/graphing.c b/src/graphing.c
index 9b41b9f..8bc3318 100644
--- a/src/graphing.c
+++ b/src/graphing.c
@@ -4278,6 +4278,10 @@ function_from_expression (const char *e, const char *var, gboolean *ex)
NULL /* dirprefix */);
g_free (ce);
+ /* Have to reset the error here, else we may die */
+ gel_error_num = GEL_NO_ERROR;
+ gel_got_eof = FALSE;
+
/* FIXME: if "x" (var) not used try to evaluate and if it returns a function use that */
if (value != NULL) {
@@ -4329,6 +4333,10 @@ function_from_expression2 (const char *e, gboolean *ex)
NULL /* dirprefix */);
g_free (ce);
+ /* Have to reset the error here, else we may die */
+ gel_error_num = GEL_NO_ERROR;
+ gel_got_eof = FALSE;
+
/* FIXME: funcbody? I think it must be done. */
got_x = gel_eval_find_identifier (value, d_intern ("x"), TRUE /*funcbody*/);
got_y = gel_eval_find_identifier (value, d_intern ("y"), TRUE /*funcbody*/);
diff --git a/src/structs.h b/src/structs.h
index fee271d..a41dbde 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -138,6 +138,8 @@ struct _GelEFunc {
/* did we already build the subst_list */
guint32 built_subst_dict:1;
+
+ /* NOTE: Make sure! to update d_setrealfunc and others */
};
typedef enum {
diff --git a/src/symbolic.c b/src/symbolic.c
index bcc5492..8903f3c 100644
--- a/src/symbolic.c
+++ b/src/symbolic.c
@@ -64,6 +64,7 @@ static GelEFunc *
hack_parse_function (const char *expr)
{
GelEFunc *f;
+ /* FIXME: parseexp could set gel_error_num! */
f = d_makeufunc (NULL /* id */,
gel_parseexp(expr,
NULL, FALSE, FALSE,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]