Commit 541e5bf6 authored by Jiri (George) Lebl's avatar Jiri (George) Lebl

Mon Aug 30 13:28:23 2010 Jiri (George) Lebl <jirka@5z.com>

	* src/graphing.c: Add "legend" style parameter to LinePlotDrawLine

	* lib/equation_solving/diffeqs.gel: Add RungeKuttaFull and
	  EulersMethodFull which return all points computed (and slightly
	  optimize Runge-Kutta)

	* src/geniustests.txt, help/C/*.xml: update
parent ead2b7fc
Mon Aug 30 13:28:23 2010 Jiri (George) Lebl <jirka@5z.com>
* src/graphing.c: Add "legend" style parameter to LinePlotDrawLine
* lib/equation_solving/diffeqs.gel: Add RungeKuttaFull and
EulersMethodFull which return all points computed (and slightly
optimize Runge-Kutta)
* src/geniustests.txt, help/C/*.xml: update
Mon Aug 30 10:23:49 2010 Jiri (George) Lebl <jirka@5z.com>
* src/gnome-genius.c: Patch from Vincent Untz to fix access to sealed
......
......@@ -4635,6 +4635,34 @@ and has period <userinput>b-a</userinput>.</para>
</listitem>
</varlistentry>
<varlistentry id="gel-function-EulersMethodFull">
<term>EulersMethodFull</term>
<listitem>
<synopsis>EulersMethodFull (f,x0,y0,x1,n)</synopsis>
<para>
Use classical Euler's method to numerically solve y'=f(x,y) for
initial <varname>x0</varname>, <varname>y0</varname> going to
<varname>x1</varname> with <varname>n</varname> increments,
returns a 2 by <userinput>n+1</userinput> matrix with the
<varname>x</varname> and <varname>y</varname> values. Suitable
for plugging into
<link linkend="gel-function-LinePlotDrawLine">LinePlotDrawLine</link>.
</para>
<para>
Systems can be solved by just having <varname>y</varname> be a
(column) vector everywhere. That is, <varname>y0</varname> can
be a vector in which case <varname>f</varname> should take a number
<varname>x</varname> and a vector of the same size for the second
argument and should return a vector of the same size.
</para>
<para>
See
<ulink url="http://mathworld.wolfram.com/EulerForwardMethod.html">Mathworld</ulink>, or
<ulink url="http://en.wikipedia.org/wiki/Eulers_method">Wikipedia</ulink> for more information.
</para>
</listitem>
</varlistentry>
<varlistentry id="gel-function-FindRootBisection">
<term>FindRootBisection</term>
<listitem>
......@@ -4764,6 +4792,36 @@ and has period <userinput>b-a</userinput>.</para>
</listitem>
</varlistentry>
<varlistentry id="gel-function-RungeKuttaFull">
<term>RungeKuttaFull</term>
<listitem>
<synopsis>RungeKuttaFull (f,x0,y0,x1,n)</synopsis>
<para>
Use classical non-adaptive fourth order Runge-Kutta method to
numerically solve
y'=f(x,y) for initial <varname>x0</varname>, <varname>y0</varname>
going to <varname>x1</varname> with <varname>n</varname>
increments,
returns a 2 by <userinput>n+1</userinput> matrix with the
<varname>x</varname> and <varname>y</varname> values. Suitable
for plugging into
<link linkend="gel-function-LinePlotDrawLine">LinePlotDrawLine</link>.
</para>
<para>
Systems can be solved by just having <varname>y</varname> be a
(column) vector everywhere. That is, <varname>y0</varname> can
be a vector in which case <varname>f</varname> should take a number
<varname>x</varname> and a vector of the same size for the second
argument and should return a vector of the same size.
</para>
<para>
See
<ulink url="http://mathworld.wolfram.com/Runge-KuttaMethod.html">Mathworld</ulink>, or
<ulink url="http://en.wikipedia.org/wiki/Runge-Kutta_methods">Wikipedia</ulink> for more information.
</para>
</listitem>
</varlistentry>
</variablelist>
</sect1>
......@@ -5212,13 +5270,16 @@ and has period <userinput>b-a</userinput>.</para>
<userinput>"window"</userinput> we can specify
<userinput>"fit"</userinput> rather than a vector in which case,
the x range will be set precisely and the y range will be set with
five percent borders around the line.
five percent borders around the line. Finally, the legend
can be specified by adding
<userinput>"legend"</userinput> and the string with the legend.
</para>
<para>
Examples:
<screen><prompt>genius></prompt> <userinput>LinePlotDrawLine(0,0,1,1,"color","blue","thickness",3)</userinput>
<prompt>genius></prompt> <userinput>LinePlotDrawLine([0,0;1,-1;-1,-1])</userinput>
<prompt>genius></prompt> <userinput>LinePlotDrawLine([0,0;1,1],"arrow","end")</userinput>
<prompt>genius></prompt> <userinput>LinePlotDrawLine(EulersMethodFull(`(x,y)=y,0,3,100),"color","blue","legend","The Solution")</userinput>
</screen>
</para>
</listitem>
......
......@@ -4,7 +4,7 @@
<!ENTITY app "<application>Genius Mathematics Tool</application>">
<!ENTITY appname "Genius">
<!ENTITY appversion "1.0.10">
<!ENTITY date "June 2010">
<!ENTITY date "August 2010">
<!ENTITY legal SYSTEM "legal.xml">
......
......@@ -14,8 +14,8 @@ function EulersMethod(f,x0,y0,x1,n) = (
else if not IsPositiveInteger(n) then
(error("EulersMethod: n must be a positive integer");bailout);
h := float(x1-x0) / n;
x := x0;
y := y0;
x := float(x0);
y := float(y0);
for k = 1 to n do (
y := y + h*f(x,y);
x := x + h
......@@ -23,6 +23,28 @@ function EulersMethod(f,x0,y0,x1,n) = (
y
)
SetHelp ("EulersMethodFull", "equation_solving",
"Use classical Euler's method to numerically solve y'=f(x,y) for initial x0,y0 going to x1 with n increments, returns an n+1 by 2 matrix of values")
function EulersMethodFull(f,x0,y0,x1,n) = (
local *;
# Note we can't check the 2 arguments, FIXME
if not IsFunction(f) then
(error("EulersMethodFull: f must be a function of two arguments");bailout)
else if not IsValue(x0) or (not IsValue(y0) and not IsVector(y0)) or not IsValue(x1) then
(error("EulersMethodFull: x0, y0 and x1 must be numbers (y0 can be a vector)");bailout)
else if not IsPositiveInteger(n) then
(error("EulersMethodFull: n must be a positive integer");bailout);
h := float(x1-x0) / n;
out := zeros(n+1,2);
out@(1,1) := x := float(x0);
out@(1,2) := y := float(y0);
for k = 2 to n+1 do (
out@(k,2) := y := y + h*f(x,y);
out@(k,1) := x := x + h
);
out
)
# See Handbook of Mathematics and Computational Science,
# John W.Harris, Horst Stocker
SetHelp ("RungeKutta", "equation_solving",
......@@ -37,22 +59,43 @@ function RungeKutta(f,x0,y0,x1,n) = (
else if not IsPositiveInteger(n) then
(error("RungeKutta: n must be a positive integer");bailout);
h := float(x1-x0) / n;
hover2 := h/2;
x := float(x0);
y := float(y0);
for k = 1 to n do (
# This is unoptimized
k1 := f(x,y);
x1 := x + h/2;
y1 := y + k1*h/2;
k2 := f(x1,y1);
x2 := x1;
y2 := y + k2*h/2;
k3 := f(x2,y2);
x3 := x + h;
y3 := y + k3*h;
k4 := f(x3,y3);
y := y + (1/6)*(k1 + 2*k2 + 2*k3 + k4)*h;
x := x + h
k2 := f(x + hover2,y + k1*hover2);
k3 := f(x + hover2,y + k2*hover2);
x := x + h;
k4 := f(x,y + k3*h);
y := y + (1/6)*(k1 + 2*k2 + 2*k3 + k4)*h
);
y
)
SetHelp ("RungeKuttaFull", "equation_solving",
"Use classical non-adaptive Runge-Kutta of fourth order method to numerically solve y'=f(x,y) for initial x0,y0 going to x1 with n increments, returns an n+1 by 2 matrix of values")
function RungeKuttaFull(f,x0,y0,x1,n) = (
local *;
# Note we can't check the 2 arguments, FIXME
if not IsFunction(f) then
(error("RungeKuttaFull: f must be a function of two arguments");bailout)
else if not IsValue(x0) or (not IsValue(y0) and not IsVector(y0)) or not IsValue(x1) then
(error("RungeKuttaFull: x0, y0 and x1 must be numbers (y0 can be a vector)");bailout)
else if not IsPositiveInteger(n) then
(error("RungeKuttaFull: n must be a positive integer");bailout);
h := float(x1-x0) / n;
hover2 := h/2;
out := zeros(n+1,2);
out@(1,1) := x := float(x0);
out@(1,2) := y := float(y0);
for k = 2 to n+1 do (
k1 := f(x,y);
k2 := f(x + hover2,y + k1*hover2);
k3 := f(x + hover2,y + k2*hover2);
out@(k,1) := x := x + h;
k4 := f(x,y + k3*h);
out@(k,2) := y := y + (1/6)*(k1 + 2*k2 + 2*k3 + k4)*h
);
out
)
......@@ -229,6 +229,7 @@ char *fake = N_("Convert degrees to radians");
char *fake = N_("Convert radians to degrees");
char *fake = N_("Find roots of a cubic polynomial (given as vector of coefficients)");
char *fake = N_("Use classical Euler's method to numerically solve y'=f(x,y) for initial x0,y0 going to x1 with n increments, returns y at x1");
char *fake = N_("Use classical Euler's method to numerically solve y'=f(x,y) for initial x0,y0 going to x1 with n increments, returns an n+1 by 2 matrix of values");
char *fake = N_("Find root of a function using the bisection method");
char *fake = N_("Find root of a function using the method of false position");
char *fake = N_("Find root of a function using the Muller's method");
......@@ -236,6 +237,7 @@ char *fake = N_("Find root of a function using the secant method");
char *fake = N_("Find roots of a polynomial (given as vector of coefficients)");
char *fake = N_("Find roots of a quartic polynomial (given as vector of coefficients)");
char *fake = N_("Use classical non-adaptive Runge-Kutta of fourth order method to numerically solve y'=f(x,y) for initial x0,y0 going to x1 with n increments, returns y at x1");
char *fake = N_("Use classical non-adaptive Runge-Kutta of fourth order method to numerically solve y'=f(x,y) for initial x0,y0 going to x1 with n increments, returns an n+1 by 2 matrix of values");
char *fake = N_("Calculate average of an entire matrix");
char *fake = N_("Integral of the GaussFunction from 0 to x (area under the normal curve)");
char *fake = N_("The normalized Gauss distribution function (the normal curve)");
......
......@@ -729,7 +729,16 @@ MoebiusMu(1) 1
MoebiusMu(4) 0
MoebiusMu(2*3) 1
RungeKutta (`(x,y) = 2*x+3,0,0,8,10) 88.0
v=RungeKuttaFull (`(x,y) = 2*x+3,0,0,8,10);v@(11,2) 88.0
v=RungeKuttaFull (`(x,y) = 2*x+3,0,0,8,10);v@(11,1) 8.0
v=RungeKuttaFull (`(x,y) = 2*x+3,0,0,8,10);v@(1,2) 0.0
v=RungeKuttaFull (`(x,y) = 2*x+3,0,0,8,10);v@(1,1) 0.0
EulersMethod (`(x,y) = 2*x+3,0,0,8,100) 87.36
v=EulersMethodFull (`(x,y) = 2*x+3,0,0,8,100);v@(101,2) 87.36
v=EulersMethodFull (`(x,y) = 2*x+3,0,0,8,100);v@(101,1) 8.0
v=EulersMethodFull (`(x,y) = 2*x+3,0,0,8,100);v@(1,2) 0.0
v=EulersMethodFull (`(x,y) = 2*x+3,0,0,8,100);v@(1,1) 0.0
EulersMethodFull (`(x,y) = y+1,0,0,2,2) [0,0;1.0,1.0;2.0,3.0]
SymbolicDerivative(sin) (`(x)=cos(x))
SymbolicDerivative(cos) (`(x)=(-sin(x)))
SymbolicDerivative(`(x)=10*x^3+x^2+88*x+100) (`(x)=(88+((30*(x^2))+(2*x))))
......
......@@ -3276,7 +3276,8 @@ parametric_get_value (double *x, double *y, double t)
}
static GtkPlotData *
draw_line (double *x, double *y, int len, int thickness, GdkColor *color)
draw_line (double *x, double *y, int len, int thickness, GdkColor *color,
char *legend)
{
GtkPlotData *data;
......@@ -3287,7 +3288,11 @@ draw_line (double *x, double *y, int len, int thickness, GdkColor *color)
g_object_set_data_full (G_OBJECT (data),
"y", y, (GDestroyNotify)g_free);
gtk_plot_add_data (GTK_PLOT (line_plot), data);
gtk_plot_data_hide_legend (data);
if (legend == NULL)
gtk_plot_data_hide_legend (data);
else
gtk_plot_data_set_legend (data,
legend);
color_alloc (color);
......@@ -3496,7 +3501,7 @@ slopefield_draw_solution (double x, double y, double dx)
/* Adjust ends */
/*clip_line_ends (xx, yy, len);*/
data = draw_line (xx, yy, len, 2 /* thickness */, &color);
data = draw_line (xx, yy, len, 2 /* thickness */, &color, NULL /*legend*/);
solutions_list = g_slist_prepend (solutions_list,
data);
g_signal_connect (G_OBJECT (data), "destroy",
......@@ -3580,7 +3585,7 @@ vectorfield_draw_solution (double x, double y, double dt, double tlen)
len = i;
data = draw_line (xx, yy, len, 2 /* thickness */, &color);
data = draw_line (xx, yy, len, 2 /* thickness */, &color, NULL /*legend*/);
solutions_list = g_slist_prepend (solutions_list,
data);
g_signal_connect (G_OBJECT (data), "destroy",
......@@ -7028,7 +7033,7 @@ draw_arrowhead (double xx1, double yy1, double xx2, double yy2,
ym - cos(angle)* /*aw*/5* thickness / 2.0,
& (ax[2]), & (ay[2]));
draw_line (ax, ay, 3, thickness, color);
draw_line (ax, ay, 3, thickness, color, NULL /*legend*/);
}
......@@ -7045,6 +7050,7 @@ LinePlotDrawLine_op (GelCtx *ctx, GelETree * * a, int *exception)
gboolean arrow_end = FALSE;
int i;
gboolean update = FALSE;
char *legend = NULL;
if G_UNLIKELY (plot_in_progress != 0) {
gel_errorout (_("%s: Plotting in progress, cannot call %s"),
......@@ -7101,6 +7107,7 @@ LinePlotDrawLine_op (GelCtx *ctx, GelETree * * a, int *exception)
static GelToken *endid = NULL;
static GelToken *bothid = NULL;
static GelToken *noneid = NULL;
static GelToken *legendid = NULL;
if (colorid == NULL) {
colorid = d_intern ("color");
......@@ -7112,6 +7119,7 @@ LinePlotDrawLine_op (GelCtx *ctx, GelETree * * a, int *exception)
endid = d_intern ("end");
bothid = d_intern ("both");
noneid = d_intern ("none");
legendid = d_intern ("legend");
}
if (a[i]->type == GEL_STRING_NODE)
......@@ -7122,6 +7130,7 @@ LinePlotDrawLine_op (GelCtx *ctx, GelETree * * a, int *exception)
if G_UNLIKELY (a[i+1] == NULL) {
gel_errorout (_("%s: No color specified"),
"LinePlotDrawLine");
g_free (legend);
g_free (x);
g_free (y);
return NULL;
......@@ -7134,6 +7143,7 @@ LinePlotDrawLine_op (GelCtx *ctx, GelETree * * a, int *exception)
} else {
gel_errorout (_("%s: Color must be a string"),
"LinePlotDrawLine");
g_free (legend);
g_free (x);
g_free (y);
return NULL;
......@@ -7143,12 +7153,14 @@ LinePlotDrawLine_op (GelCtx *ctx, GelETree * * a, int *exception)
if G_UNLIKELY (a[i+1] == NULL) {
gel_errorout (_("%s: No thickness specified"),
"LinePlotDrawLine");
g_free (legend);
g_free (x);
g_free (y);
return NULL;
}
if G_UNLIKELY ( ! check_argument_positive_integer (a, i+1,
"LinePlotDrawLine")) {
g_free (legend);
g_free (x);
g_free (y);
return NULL;
......@@ -7164,6 +7176,7 @@ LinePlotDrawLine_op (GelCtx *ctx, GelETree * * a, int *exception)
a[i+1]->type != GEL_MATRIX_NODE)) {
gel_errorout (_("%s: No window specified"),
"LinePlotDrawLine");
g_free (legend);
g_free (x);
g_free (y);
return NULL;
......@@ -7197,6 +7210,7 @@ LinePlotDrawLine_op (GelCtx *ctx, GelETree * * a, int *exception)
} else if (get_limits_from_matrix (a[i+1], &x1, &x2, &y1, &y2)) {
update = update_lineplot_window (x1, x2, y1, y2);
} else {
g_free (legend);
g_free (x);
g_free (y);
return NULL;
......@@ -7210,6 +7224,7 @@ LinePlotDrawLine_op (GelCtx *ctx, GelETree * * a, int *exception)
a[i+1]->type != GEL_IDENTIFIER_NODE)) {
gel_errorout (_("%s: arrow style should be \"origin\", \"end\", \"both\", or \"none\""),
"LinePlotDrawLine");
g_free (legend);
g_free (x);
g_free (y);
return NULL;
......@@ -7234,6 +7249,31 @@ LinePlotDrawLine_op (GelCtx *ctx, GelETree * * a, int *exception)
} else {
gel_errorout (_("%s: arrow style should be \"origin\", \"end\", \"both\", or \"none\""),
"LinePlotDrawLine");
g_free (legend);
g_free (x);
g_free (y);
return NULL;
}
i++;
} else if (id == legendid) {
if G_UNLIKELY (a[i+1] == NULL) {
gel_errorout (_("%s: No legend specified"),
"LinePlotDrawLine");
g_free (legend);
g_free (x);
g_free (y);
return NULL;
}
if (a[i+1]->type == GEL_STRING_NODE) {
g_free (legend);
legend = g_strdup (a[i+1]->str.str);
} else if (a[i+1]->type == GEL_IDENTIFIER_NODE) {
g_free (legend);
legend = g_strdup (a[i+1]->id.id->token);
} else {
gel_errorout (_("%s: Legend must be a string"),
"LinePlotDrawLine");
g_free (legend);
g_free (x);
g_free (y);
return NULL;
......@@ -7241,12 +7281,14 @@ LinePlotDrawLine_op (GelCtx *ctx, GelETree * * a, int *exception)
i++;
} else {
gel_errorout (_("%s: Unknown style"), "LinePlotDrawLine");
g_free (legend);
g_free (x);
g_free (y);
return NULL;
}
} else {
gel_errorout (_("%s: Bad parameter"), "LinePlotDrawLine");
g_free (legend);
g_free (x);
g_free (y);
return NULL;
......@@ -7273,7 +7315,7 @@ LinePlotDrawLine_op (GelCtx *ctx, GelETree * * a, int *exception)
plot_axis ();
}
draw_line (x, y, len, thickness, &color);
draw_line (x, y, len, thickness, &color, legend);
if (arrow_end && len > 1)
draw_arrowhead (x[len-2], y[len-2],
......@@ -7284,6 +7326,8 @@ LinePlotDrawLine_op (GelCtx *ctx, GelETree * * a, int *exception)
x[0], y[0],
thickness, &color);
g_free (legend);
return gel_makenum_null ();
}
......
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