Commit f8ee5a1b authored by Jiri (George) Lebl's avatar Jiri (George) Lebl Committed by George Lebl

add many derivative tests


Fri Jun 24 16:23:01 2005  George Lebl <jirka@5z.com>

	* src/longtest.gel: add many derivative tests

	* src/funclib.c: add IsFunctionOrIdentifier

	* lib/calculus/differentiation.gel: accept identifiers for all
	  functions and not just functions

	* help/C/gel-function-list.xml: add IsFunctionOrIdentifier

	* src/eval.c: Allow identifier + string to make a string

	* src/symbolic.c: fix some derivative definitions

	* src/eval.c: fixup nargs when creating new operator nodes in
	  simplification
parent 2aedb0c0
Fri Jun 24 16:23:01 2005 George Lebl <jirka@5z.com>
* src/longtest.gel: add many derivative tests
* src/funclib.c: add IsFunctionOrIdentifier
* lib/calculus/differentiation.gel: accept identifiers for all
functions and not just functions
* help/C/gel-function-list.xml: add IsFunctionOrIdentifier
* src/eval.c: Allow identifier + string to make a string
* src/symbolic.c: fix some derivative definitions
* src/eval.c: fixup nargs when creating new operator nodes in
simplification
Fri Jun 24 15:42:09 2005 George Lebl <jirka@5z.com>
* src/mpwrap.[ch]: add symbolic equality (respects types)
......
......@@ -142,6 +142,11 @@ PKG_CHECK_MODULES(GENIUS_NOGUI, glib-2.0 >= $GLIB_REQUIRED gmodule-2.0 >= $GLIB_
AC_SUBST(GENIUS_NOGUI_CFLAGS)
AC_SUBST(GENIUS_NOGUI_LIBS)
# glib
PKG_CHECK_MODULES(GLIB, glib-2.0 >= $GLIB_REQUIRED)
AC_SUBST(GLIB_CFLAGS)
AC_SUBST(GLIB_LIBS)
GENIUS_MODULES="gtk+-2.0 >= $GTK_REQUIRED libgnome-2.0 >= $LIBGNOME_REQUIRED libgnomeui-2.0 >= $LIBGNOMEUI_REQUIRED vte >= $VTE_REQUIRED gtksourceview-1.0 >= $GTKSOURCEVIEW_REQUIRED libglade-2.0 >= $LIBGLADE_REQUIRED"
GENIUS_MODULES_NOSRCVIEW="gtk+-2.0 >= $GTK_REQUIRED libgnome-2.0 >= $LIBGNOME_REQUIRED libgnomeui-2.0 >= $LIBGNOMEUI_REQUIRED vte >= $VTE_REQUIRED libglade-2.0 >= $LIBGLADE_REQUIRED"
......
......@@ -132,6 +132,14 @@ To get help on a specific function from the console type:
</listitem>
</varlistentry>
<varlistentry id="gel-function-IsFunctionOrIdentifier">
<term>IsFunctionOrIdentifier</term>
<listitem>
<synopsis>IsFunctionOrIdentifier (arg)</synopsis>
<para>Check if argument is a function or identifier</para>
</listitem>
</varlistentry>
<varlistentry id="gel-function-IsFunctionRef">
<term>IsFunctionRef</term>
<listitem>
......
......@@ -32,7 +32,7 @@ function OneSidedThreePointFormula(f,x0,h) =
(
# check arguments
## check types
if not IsFunction(f) then
if not IsFunctionOrIdentifier(f) then
(error("OneSidedThreePointFormula: argument 1 must be a function");bailout)
else if not IsReal(h) then
(error("OneSidedThreePointFormula: argument 2 must be real values");bailout);
......@@ -41,7 +41,7 @@ function OneSidedThreePointFormula(f,x0,h) =
(error("OneSidedThreePointFormula: argument 2 must be non-zero (negative for left-handed derivative, positive for right-handed)");bailout);
# Start calculating
(-3*f(x0)+4*f(x0+h)-f(x0+2*h))/(2*h)
(-3*f(x0)+4*(f call (x0+h))-(f call (x0+2*h)))/(2*h)
)
SetHelp("OneSidedThreePointFormula","calculus","Compute one-sided derivative using three-point formula");
protect("OneSidedThreePointFormula");
......@@ -52,7 +52,7 @@ function TwoSidedThreePointFormula(f,x0,h) =
(
# check arguments
## check types
if not IsFunction(f) then
if not IsFunctionOrIdentifier(f) then
(error("TwoSidedThreePointFormula: argument 1 must be a function");bailout)
else if not IsReal(h) then
(error("TwoSidedThreePointFormula: argument 2 must be real values");bailout);
......@@ -60,7 +60,7 @@ function TwoSidedThreePointFormula(f,x0,h) =
if h==0 then (error("TwoSidedThreePointFormula: argument 2 must be non-zero");bailout);
# Start calculating
(f(x0+h)-f(x0-h))/(2*h)
((f call (x0+h))-(f call (x0-h)))/(2*h)
)
SetHelp("TwoSidedThreePointFormula","calculus","Compute two-sided derivative using three-point formula");
protect("TwoSidedThreePointFormula");
......@@ -71,7 +71,7 @@ function OneSidedFivePointFormula(f,x0,h) =
(
# check arguments
## check types
if not IsFunction(f) then
if not IsFunctionOrIdentifier(f) then
(error("OneSidedFivePointFormula: argument 1 must be a function");bailout)
else if not IsReal(h) then
(error("OneSidedFivePointFormula: argument 2 must be real values");bailout);
......@@ -79,7 +79,7 @@ function OneSidedFivePointFormula(f,x0,h) =
if h==0 then (error("OneSidedFivePointFormula: argument 2 must be non-zero (negative for left-handed derivative, positive for right-handed)");bailout);
# Start calculating
(-25*f(x0)+48*f(x0+h)-36*f(x0+2*h)+16*f(x0+3*h)-3*f(x0+4*h))/(12*h)
(-25*(f call (x0))+48*(f call (x0+h))-36*(f call (x0+2*h))+16*(f call (x0+3*h))-3*(f call (x0+4*h)))/(12*h)
)
SetHelp("OneSidedFivePointFormula","calculus","Compute one-sided derivative using five point formula");
protect("OneSidedFivePointFormula");
......@@ -90,7 +90,7 @@ function TwoSidedFivePointFormula(f,x0,h) =
(
# check arguments
## check types
if(not IsFunction(f)) then
if(not IsFunctionOrIdentifier(f)) then
(error("TwoSidedFivePointFormula: argument 1 must be a function");bailout)
else if(not IsReal(h)) then
(error("TwoSidedFivePointFormula: argument 2 must be a real value");bailout);
......@@ -98,7 +98,7 @@ function TwoSidedFivePointFormula(f,x0,h) =
if(h==0) then (error("TwoSidedFivePointFormula: argument 2 must be non-zero");bailout);
# Start calculating
(f(x0-2*h)-8*f(x0-h)+8*f(x0+h)-f(x0+2*h))/(12*h)
((f call (x0-2*h))-8*(f call (x0-h))+8*(f call (x0+h))-(f call (x0+2*h)))/(12*h)
)
SetHelp("TwoSidedFivePointFormula","calculus","Compute two-sided derivative using five-point formula");
protect("TwoSidedFivePointFormula");
......@@ -171,27 +171,3 @@ function Derivative(f,x0) =
)
SetHelp("Derivative","calculus","Attempt to calculate derivative by trying first symbolically and then numerically");
protect("Derivative");
#function TaylorApproximationFunction(f,x0,n) =
#(
# if not IsFunction(f) then
# (error("TaylorApproximationFunction: argument 1 must be a function");bailout)
# else if not IsValue(x0) then
# (error("TaylorApproximationFunction: argument 2 must be a value");bailout)
# else if not IsPositiveInteger(n) then
# (error("TaylorApproximationFunction: argument 3 must be a positive integer");bailout);
#
# df = f;
#
# for k=0 to n do (
# c[k] = df(x0)/(k!);
# df = SymbolicDerivativeTry (f);
#
# c = null;
#
# if IsNull(df) then (
# ) else (
# )
#)
#SetHelp("TaylorApproximationFunction","calculus","Attempt to construct the taylor approximation function around x0 to the nth degree.");
#protect("TaylorApproximationFunction");
......@@ -2405,11 +2405,17 @@ string_concat (GelCtx *ctx, GelETree *n, GelETree *l, GelETree *r)
if (l->type == STRING_NODE &&
r->type == STRING_NODE) {
s = g_strconcat (l->str.str, r->str.str, NULL);
} else if(l->type == STRING_NODE) {
} else if (l->type == STRING_NODE &&
r->type == IDENTIFIER_NODE) {
s = g_strconcat (l->str.str, r->id.id->token, NULL);
} else if (r->type == STRING_NODE &&
l->type == IDENTIFIER_NODE) {
s = g_strconcat (l->id.id->token, r->str.str, NULL);
} else if (l->type == STRING_NODE) {
char *t = gel_string_print_etree (r);
s = g_strconcat (l->str.str, t, NULL);
g_free (t);
} else if(r->type == STRING_NODE) {
} else if (r->type == STRING_NODE) {
char *t = gel_string_print_etree (l);
s = g_strconcat (t, r->str.str, NULL);
g_free (t);
......@@ -2823,9 +2829,9 @@ static const GelOper prim_table[E_OPER_LAST] = {
{{GO_MATRIX,GO_MATRIX,0},(GelEvalFunc)pure_matrix_eltbyelt_op},
{{GO_VALUE|GO_MATRIX,GO_VALUE|GO_MATRIX,0},
(GelEvalFunc)matrix_addsub_scalar_matrix_op},
{{GO_VALUE|GO_MATRIX|GO_FUNCTION|GO_STRING,GO_STRING,0},
{{GO_VALUE|GO_MATRIX|GO_FUNCTION|GO_IDENTIFIER|GO_STRING,GO_STRING,0},
(GelEvalFunc)string_concat},
{{GO_STRING,GO_VALUE|GO_MATRIX|GO_FUNCTION|GO_STRING,0},
{{GO_STRING,GO_VALUE|GO_MATRIX|GO_FUNCTION|GO_IDENTIFIER|GO_STRING,0},
(GelEvalFunc)string_concat},
{{GO_FUNCTION|GO_IDENTIFIER,GO_FUNCTION|GO_IDENTIFIER,0},
(GelEvalFunc)function_bin_op},
......@@ -7550,6 +7556,7 @@ oper_reshufle (GelETree *n, int oper)
GET_NEW_NODE (l);
l->type = OPERATOR_NODE;
l->op.oper = oper;
l->op.nargs = 2;
l->op.args = a;
a->any.next = b;
b->any.next = NULL;
......@@ -7646,6 +7653,7 @@ resimplify:
GET_NEW_NODE (e);
e->type = OPERATOR_NODE;
e->op.oper = E_PLUS;
e->op.nargs = 2;
if (le == NULL) {
e->op.args = gel_makenum_ui (1);
} else {
......@@ -7666,6 +7674,7 @@ resimplify:
GET_NEW_NODE (nn);
nn->type = OPERATOR_NODE;
nn->op.oper = E_EXP;
nn->op.nargs = 2;
nn->op.args = ll;
ll->any.next = e;
......@@ -7708,6 +7717,7 @@ resimplify:
GET_NEW_NODE (e);
e->type = OPERATOR_NODE;
e->op.oper = E_PLUS;
e->op.nargs = 2;
if (le == NULL) {
e->op.args = gel_makenum_ui (1);
} else {
......@@ -7728,6 +7738,7 @@ resimplify:
GET_NEW_NODE (nn);
nn->type = OPERATOR_NODE;
nn->op.oper = E_MUL;
nn->op.nargs = 2;
nn->op.args = e;
e->any.next = ll;
......@@ -7832,11 +7843,11 @@ resimplify:
GET_NEW_NODE (nn);
nn->type = OPERATOR_NODE;
nn->op.oper = E_MUL;
nn->op.nargs = 2;
nn->op.args = v;
v->any.next = w;
w->any.next = NULL;
nn->op.nargs = 2;
n->op.args = x;
x->any.next = nn;
......
......@@ -1181,6 +1181,14 @@ IsFunction_op(GelCtx *ctx, GelETree * * a, gboolean *exception)
return gel_makenum_bool (0);
}
static GelETree *
IsFunctionOrIdentifier_op(GelCtx *ctx, GelETree * * a, gboolean *exception)
{
if (a[0]->type == FUNCTION_NODE || a[0]->type == IDENTIFIER_NODE)
return gel_makenum_bool (1);
else
return gel_makenum_bool (0);
}
static GelETree *
IsFunctionRef_op(GelCtx *ctx, GelETree * * a, gboolean *exception)
{
if(a[0]->type==OPERATOR_NODE &&
......@@ -4820,6 +4828,7 @@ gel_funclib_addall(void)
FUNC (IsString, 1, "arg", "basic", N_("Check if argument is a text string"));
FUNC (IsMatrix, 1, "arg", "basic", N_("Check if argument is a matrix"));
FUNC (IsFunction, 1, "arg", "basic", N_("Check if argument is a function"));
FUNC (IsFunctionOrIdentifier, 1, "arg", "basic", N_("Check if argument is a function or an identifier"));
FUNC (IsFunctionRef, 1, "arg", "basic", N_("Check if argument is a function reference"));
FUNC (IsComplex, 1, "num", "numeric", N_("Check if argument is a complex (non-real) number"));
......
......@@ -41,6 +41,30 @@ function randtest2() = (
true
);
function derivtest() = (
epsilon = 0.0001;
for n in [`asin,`asinh,`acos,`acosh,`acsc,`acsch,`asec,`asech,`atan,`atanh,`acot,`acoth,`sin,`sinh,`cos,`cosh,`csc,`csch,`sec,`sech,`tan,`tanh,`cot,`coth,`sqrt,`ln,`log2,`log10,`exp,`cis] do (
d = SymbolicDerivative(n);
for x in [0.1,0.2,0.15,0.3,0.4] do (
y = (d call (x)) - NDerivative (n,x);
if (not IsValue (y)) or abs(y) > epsilon then (
error ("Bad derivative on " + n + " at " + x + "!");
return false
)
)
);
f = SymbolicNthDerivative(atan,4);
d = SymbolicDerivative(f);
for x in [0.1,0.2,0.15,0.3,0.4] do (
y = (d call (x)) - NDerivative (f,x);
if (not IsValue (y)) or abs(y) > epsilon then (
error ("Bad derivative on 5th atan deriv at " + x + "!");
return false
)
);
true
);
function LongTest() = (
errors = 0;
......@@ -65,6 +89,9 @@ function LongTest() = (
#random test 2
if not randtest2() then (error("error on random test 2");errors = errors + 1);
#derivative test
if not derivtest() then (error("error on deriv test");errors = errors + 1);
# We print instead of return since we normally use load to run this
# and load doesn't output the return value
if errors > 0 then
......
......@@ -130,16 +130,16 @@ gel_differentiate_func1_expr (GelToken *tok)
DERIVATIVE_ENTRY_ALIAS ("asinh", "arcsinh", "1/sqrt(1+x^2)");
DERIVATIVE_ENTRY_ALIAS ("acos", "arccos", "-1/sqrt(1-x^2)");
DERIVATIVE_ENTRY_ALIAS ("acosh", "arccosh", "1/sqrt(x^2-1)");
DERIVATIVE_ENTRY_ALIAS ("acsc", "arccsc", "-1/(u*sqrt(x^2-1))");
DERIVATIVE_ENTRY_ALIAS ("acsch", "arccsch", "-1/(u*sqrt(x^2+1))");
DERIVATIVE_ENTRY_ALIAS ("asec", "arcsec", "1/(u*sqrt(x^2-1))");
DERIVATIVE_ENTRY_ALIAS ("asech", "arcsech", "-1/(u*sqrt(1-x^2))");
DERIVATIVE_ENTRY_ALIAS ("acsc", "arccsc", "-1/(x*sqrt(x^2-1))");
DERIVATIVE_ENTRY_ALIAS ("acsch", "arccsch", "-1/(x*sqrt(x^2+1))");
DERIVATIVE_ENTRY_ALIAS ("asec", "arcsec", "1/(x*sqrt(x^2-1))");
DERIVATIVE_ENTRY_ALIAS ("asech", "arcsech", "-1/(x*sqrt(1-x^2))");
DERIVATIVE_ENTRY_ALIAS ("atan", "arctan", "1/(1+x^2)");
DERIVATIVE_ENTRY_ALIAS ("atanh", "arctanh", "1/(1-x^2)");
DERIVATIVE_ENTRY_ALIAS ("acot", "arccot", "-1/(x^2+1)");
DERIVATIVE_ENTRY_ALIAS ("acoth", "arccoth", "-1/(x^2-1)");
DERIVATIVE_ENTRY ("cis", "-cos(x)+1i*cos(x)");
DERIVATIVE_ENTRY ("cis", "-sin(x)+1i*cos(x)");
DERIVATIVE_ENTRY_ALIAS ("sqrt", "SquareRoot", "1/(2*sqrt(x))");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment