| 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: