Ilya Zakharevich on Sun, 8 Nov 1998 18:26:56 -0500 (EST)


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

2.0.12: half-baked support of splines in plotting


This patch:

  a) when gaffect(non_constant, constant_type), calls geval() on non_constant
	if this will not lead to an obvious loop;
  b) Implements (in some situations) new plotting flag 256 to use splines.
	Try
	    ploth(x=0,3,x^4,128+256,5)

(It should be applied after my previous patch, to have PLOT_SPLINES defined.)

However, it contains a bug.  Look for #ifdef I_KNOW_HOW_TO_DO_THIS

I want to have a named variable, then delete it without a trace.
I know how to do creating part (up to some extend - I think it will fail if
the var#1 was previously deleled), but the part in #ifdef fails: apparently
delete_var() is a NOP.

Can somebody fix this?  I need a named variable to pass its name to
highlevel plotting functions (due to "a" above, now
    y = x^17
    ploth(x=2,5,y)
works).

Ilya

P.S. A year ago I had some Perl code to make Math::Pari to
     autosubdivide so that splines will give necessary precision
     (similar to current recursive linear approximation).  Now, when
     PARI proper is not that much behind Math::Pari module in plotting
     support, maybe I could reimplement it in PARI.

--- ./src/graph/plotport.c~	Sun Nov  8 04:22:06 1998
+++ ./src/graph/plotport.c	Sun Nov  8 17:56:08 1998
@@ -1037,6 +1037,68 @@ rectplothin(entree *ep, GEN a, GEN b, ch
   return pl;
 }
 
+/* Uses highlevel functions to implement splines in low-level functions.
+
+   Most probably one does not need to make varn==0 into pure variable,
+   since plotting functions should take care of this. */
+static void
+rectsplines(long ne, double *x, double *y, long lx, long flag)
+{
+  long i, j, oldavma = avma, dokill = 0;
+  GEN xa = cgetg(lx + 1, t_VEC), ya = cgetg(lx + 1, t_VEC);
+  GEN xas = cgetg(4 + 1, t_VEC), yas = cgetg(4 + 1, t_VEC);
+  void *old1;
+  entree *var0 = varentries[ordvar[0]], *var1 = varentries[ordvar[1]];
+  char *name = 0;
+  static const char * const fakename = "splines__";
+  
+  if (!var1) {
+      GEN res = lisexpr((char*)fakename);
+      dokill = 1;
+      var1 = varentries[ordvar[1]];
+      if (!var1 || !(name = var1->name) && strcmp(name, fakename))
+	  err(talker, "panic: no new var in splines");
+  }
+  if (lx < 4)
+      err(talker, "Too few points (%ld) for spline plot", lx);
+  old1 = var1->value;
+  if (!name)
+      name = var1->name;
+  for (i = 1; i <= lx; i++) {
+      xa[i] = (long) dbltor(x[i-1]);
+      ya[i] = (long) dbltor(y[i-1]);      
+  }
+  for (i = 0; i <= lx - 4; i++) {
+      long oavma = avma;
+      GEN poly;
+
+      for (j = 1; j <= 4; j++) {
+	  xas[j] = xa[i + j];
+	  yas[j] = ya[i + j];      
+      }
+      poly = polint(xas, yas, polx[0], NULL);
+      var1->value = (void*)poly;	/* Temporary make it into expr */
+      rectploth( ne, var0, 
+		 (GEN)(i==0 ? xa[1] : xa[i+2]),
+		 (GEN)(i==lx-4 ? xa[lx] : xa[i+3]),
+		 name, 4,		/* XXXX precision */
+		 (PLOT_RECURSIVE | PLOT_NO_RESCALE | PLOT_NO_FRAME
+		  | PLOT_NO_AXE_Y | PLOT_NO_AXE_X),
+		 2);			/* Start with 3 points */
+      avma = oavma;
+  }
+  var1->value = old1;			/* Restore the old value */
+
+#ifdef I_KNOW_HOW_TO_DO_THIS			/* XXXX Does not work??? */
+  if (dokill) {
+      kill0(var1);
+      manage_var(1,NULL);
+  }
+#endif  
+
+  avma = oldavma;
+}
+
 /*
  * Plot a dblPointList. Complete with axes, bounding box, etc.
  * We use two drawing rectangles: one for strings, another
@@ -1153,7 +1215,10 @@ rectplothrawin(long stringrect, long dra
     }
     if ((flags & PLOT_POINTS_LINES) || !(flags & PLOT_POINTS)) {
 	rectlinetype(drawrect, rectline_itype + ltype); 	/* Graphs. */
-	rectlines0(drawrect,x.d,y.d,nbpoints,0);
+	if ((flags & PLOT_PARAMETRIC) || !(flags & PLOT_SPLINES))
+	    rectlines0(drawrect,x.d,y.d,nbpoints,0);
+	else
+	    rectsplines(drawrect,x.d,y.d,nbpoints,0);
     }
     ltype++;				/* Graphs. */
   }
--- ./src/basemath/gen2.c~	Fri Nov  6 10:08:14 1998
+++ ./src/basemath/gen2.c	Sun Nov  8 16:47:22 1998
@@ -1453,7 +1453,33 @@ gaffect(GEN x, GEN y)
     return;
   }
 
-  if (is_const_t(ty)) err(assignerf,tx,ty);
+  if (is_const_t(ty)) {
+      /* initial_value macro is not defined now... */
+#define initial_value(ep) ((ep)+1)
+      if (tx == t_POL) {
+	  entree *var = varentries[ordvar[varn(x)]];
+	  /* Is a bound expression, thus should not loop: */
+	  if (var && var->value != (void*)initial_value(var)) {
+	      gaffect(geval(x),y);
+	      return;
+	  }	  
+      } else if (is_rfrac_t(tx)) {
+	  GEN num = (GEN)x[1], den = (GEN)x[2];
+	  entree *varnum = varentries[ordvar[varn(num)]];
+	  entree *varden = varentries[ordvar[varn(den)]];
+
+	  /* Are bound expressions, thus should not loop: */
+	  if (varnum && varnum->value != (void*)initial_value(varnum)
+	      && varden && varden->value !=
+	      (void*)initial_value(varden)) {
+	      gaffect(geval(x),y);
+	      return;
+	  }
+      }
+#undef initial_value
+      err(assignerf,tx,ty);
+  }
+  
   switch(tx)
   {
     case t_POL: