[genius] Mon Aug 30 13:28:23 2010 Jiri (George) Lebl <jirka 5z com>
- From: George Lebl <jirka src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [genius] Mon Aug 30 13:28:23 2010 Jiri (George) Lebl <jirka 5z com>
- Date: Mon, 30 Aug 2010 20:30:00 +0000 (UTC)
commit 541e5bf6c958520a3dd29304cd41b636cb308a19
Author: Jiri (George) Lebl <jirka 5z com>
Date: Mon Aug 30 13:28:27 2010 -0700
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
ChangeLog | 10 +++++
help/C/gel-function-list.xml | 63 +++++++++++++++++++++++++++++++++-
help/C/genius.xml | 2 +-
lib/equation_solving/diffeqs.gel | 71 ++++++++++++++++++++++++++++++-------
lib/library-strings.c | 2 +
src/geniustests.txt | 9 +++++
src/graphing.c | 56 ++++++++++++++++++++++++++---
7 files changed, 191 insertions(+), 22 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 51b6906..a533f55 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+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
diff --git a/help/C/gel-function-list.xml b/help/C/gel-function-list.xml
index a89d86d..16e27e0 100644
--- a/help/C/gel-function-list.xml
+++ b/help/C/gel-function-list.xml
@@ -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>
diff --git a/help/C/genius.xml b/help/C/genius.xml
index 5563ca8..639095a 100644
--- a/help/C/genius.xml
+++ b/help/C/genius.xml
@@ -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">
diff --git a/lib/equation_solving/diffeqs.gel b/lib/equation_solving/diffeqs.gel
index 40bbabb..e90eaf9 100644
--- a/lib/equation_solving/diffeqs.gel
+++ b/lib/equation_solving/diffeqs.gel
@@ -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
+)
diff --git a/lib/library-strings.c b/lib/library-strings.c
index c3570f1..b6eb20d 100644
--- a/lib/library-strings.c
+++ b/lib/library-strings.c
@@ -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)");
diff --git a/src/geniustests.txt b/src/geniustests.txt
index 443b81c..9e5eace 100644
--- a/src/geniustests.txt
+++ b/src/geniustests.txt
@@ -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))))
diff --git a/src/graphing.c b/src/graphing.c
index 4ee7432..105a78d 100644
--- a/src/graphing.c
+++ b/src/graphing.c
@@ -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 ();
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]