[genius] Mon Aug 30 13:28:23 2010 Jiri (George) Lebl <jirka 5z com>



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]