Juhana Sadeharju on Fri, 31 Aug 2001 22:12:40 +0300


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

plotminmax written/query for Jacobian functions


Hello. I'm not in Pari-Gp development list but I follow the archives.
By the way, would you please set up digested versions of Pari/GP
mailing lists? They are useful if the lists are of only secondary
importance. While GP is only calculator I use frequently, I don't
have time to receive every mail separately.

 -*-

Are there any plans to add Jacobi's elliptic functions and their
inverses to GP? I didn't found them. I could give a try if nobody
else has written them.

 -*-

I wrote an alternative for plot() which could be named plotminmax().
The code is include at bottom, and it belongs to file "plotport.c".

I wrote plotminmax() because plot() most often only gives wrong curves.
The following example shows why I consider plotminmax() to be greatly
better -- but my implementation could be improved; see the code comments.

Magnitude of the frequency response of comb filter is given by h():
  f(x,g,k) = x^(-k)/(1 - g*x^(-k));
  h(t)=norm(f(exp(I*t),-0.7,10.0));
Which is then plotted with
  plot(t=0.0,Pi,h(t))
and
  plotminmax(t=0.0,Pi,h(t)).


plot() function:

10.900334 |''''''''''''''''''"''''''''''''''''''''''''"''''''''''''''''''|
          |                  :                        :                  |
          |                  :                        :                  |
          |     "            :                        :            "     |
          |     :            :                        :            :     |
          |     :            :                        :            :     |
          |     :            :           __           :            :     |
          |     ::          ::           ::           ::          ::     |
          |     ::          : :          ::          : :          ::     |
          |     ::          : :          ::          : :          ::     |
          |    : x          : :          ::          : :          x :    |
          |    : :          : :          ::          : :          : :    |
          |    : :          : :         :  :         : :          : :    |
          |    : :          " :         :  :         : "          : :    |
          |    :  :         : :         :  :         : :         :  :    |
          |    :  :         : "         :  :         " :         :  :    |
          |    x  :        :  :         :  :         :  :        :  x    |
          |    :  :        :   :        x  x        :   :        :  :    |
          |   :   "        _   :                    :   _        "   :   |
          |   x                "       _    _       "                x   |
          | _x     "_    _"     x_   __      __   _x     "_    _"     x_ |
        0 "",,,,,,,,,"""",,,,,,,,,""",,,,,,,,,,""",,,,,,,,,"""",,,,,,,,,""
          0                                                       3.141593


plotminmax() function:

11.111111 |'''''*''''''''''''*'''''''''''**'''''''''''*''''''''''''*'''''|
          |     *           **           **           **           *     |
          |     *           **           **           **           *     |
          |     *           **           **           **           *     |
          |     *           **           **           **           *     |
          |    **           **           **           **           **    |
          |    **           **           **           **           **    |
          |    **           **           **           **           **    |
          |    ***          **           **           **          ***    |
          |    * *          **           **           **          * *    |
          |    * *          **           **           **          * *    |
          |    * *          ***          **          ***          * *    |
          |    * *          * *          **          * *          * *    |
          |    * *          * *          **          * *          * *    |
          |    * *          * *         ****         * *          * *    |
          |    * *         ** *         *  *         * **         * *    |
          |   ** *         *  *         *  *         *  *         * **   |
          |   *  **        *  *         *  *         *  *        **  *   |
          |   *   *        *  **       **  **       **  *        *   *   |
          |  **   **      **   **      *    *      **   **      **   **  |
          ****     ********     ********    ********     ********     ****
        0 |..............................................................|
          0                                                       3.141593


The plotminmax() shows both where the peaks are located and what are
their peak values, but plot() shows only the locations. plot() also
gives a misleading idea about the peak values, and that is not a good
thing at all.

So, finally you have someone who actually do use the crude plot()
function.  ;-)

Best regards,

Juhana Sadeharju

PS. I'm that Juhana Kouhia in authors file; I implemented the initial
64-bit support. You could change the name, or at least remove the
invalid e-mail address.

 ==code for plotminmax()==
/*
  In plotminmax() the function is heavily oversampled with respect to
  screen resolution, and then minmax vertical lines are actually drawn
  to screen. This plot style is more practical than the one used in
  plot() which renders pretty much unusable due aliasing errors.

  I render only with '*' characters now but plot()-style renderition
  would work too. However, if we would plot to an image file, then we
  could use an image-to-ascii converter program to downscale the image
  to ascii text format with antialiasing.
*/

/* Oversampling ratio; it could be given as parameter to plotminmax()
 * because 64 could be sometimes too much and sometimes too less.
 */
#define OSRATIO 64

/* fill_vertical() draws a vertical bar between min and max values
 * within one column.
 */
static void
fill_vertical(screen scr, long i, int osmin, int osmax)
{
  int j;

  for(j = osmin; j <= osmax; j++) scr[i][j] = '*';
}

void
plotminmax(entree *ep, GEN a, GEN b, char *ch,GEN ysmlu,GEN ybigu, long prec)
{
  long av = avma, av2,limite,j,i,sig;
  GEN p1,p2,ysml,ybig,x,diff,dyj,dx,*y;
  screen scr;
  char buf[80];
  int k,osmin,osmax;

  y = (GEN *)malloc((OSRATIO*ISCR+2)*sizeof(GEN)); /* 2 includes one extra
						     sample */
  sig=gcmp(b,a); if (!sig) return;
  if (sig<0) { x=a; a=b; b=x; }
  x = cgetr(prec); gaffect(a,x); push_val(ep, x);
  for (i=1; i<=OSRATIO*ISCR+1; i++) y[i]=cgetr(3);
  p1 = gdivgs(gsub(b,a), OSRATIO*ISCR); /* change done due one extra sample */
  dx = cgetr(prec); gaffect(p1, dx);

  /* NOTE: setting ysml and ybig this way leaves zero axis visible,
   * and user is not able to use true min/max values for drawing range;
   * it could be better to set ysml = +infty and ybig = -infty
   * because then user is always able to set the other limit to
   * zero;
   * I have not done the change now. I wait for comments.
   */
  ysml=gzero; ybig=gzero;
  for (j=1; j<=JSCR; j++) scr[1][j]=scr[ISCR][j]=YY;
  for (i=2; i<ISCR; i++)
  {
    scr[i][1] = XX_LOWER;
    scr[i][JSCR]=XX_UPPER;
    for (j=2; j<JSCR; j++) scr[i][j]=BLANK;
  }
  av2=avma; limite=stack_lim(av2,1);

  /* NOTE: y[1] = f(a) and y[OSRATIO*ISCR+1] = f(b) */
  for (i=1; i<=OSRATIO*ISCR+1; i++)
  {
    gaffect(READ_EXPR(ch),y[i]);
    if (gcmp(y[i],ysml)<0) ysml=y[i];
    if (gcmp(y[i],ybig)>0) ybig=y[i];
    x = addrr(x,dx);
    if (low_stack(limite, stack_lim(av2,1)))
    {
      long tetpil=avma;
      if (DEBUGMEM>1) err(warnmem,"plot");
      x = gerepile(av2,tetpil,rcopy(x));
    }
    ep->value = (void*)x;
  }
  if (ysmlu) ysml=ysmlu;
  if (ybigu) ybig=ybigu;
  avma=av2; diff=gsub(ybig,ysml);
  if (gcmp0(diff)) { ybig=gaddsg(1,ybig); diff=gun; }
  dyj = gdivsg(JSCR-1,diff);
  av2=avma;
  for (i=1; i<=ISCR; i++)
  {
    /* first character column spans values y[1] to y[OSRATIO+1];
     * second character column spans values y[OSRATIO+1] to
     * y[2*OSRATIO+1];
     * last character column ISCR spans values y[(ISCR-1)*OSRATIO+1]
     * to y[ISCR*OSRATIO+1]
     *
     * That is, there is one sample overlap between columns because
     * the drawing should be continuous.
     */
    osmin = 1000; /* unit is a screen character */
    osmax = -1000;
    for(k=(i-1)*OSRATIO+1; k<=i*OSRATIO+1; k++)
    {
      j = 1+gtolong(gmul(gsub(y[k],ysml),dyj));
      if (osmin > j) osmin = j;
      if (osmax < j) osmax = j;
    }
    fill_vertical(scr, i, osmin, osmax);
    avma = av2;
  }
  p1=cgetr(3); gaffect(ybig,p1); pariputc('\n');
  pariputsf("%s ", dsprintf9(rtodbl(p1), buf));
  for (i=1; i<=ISCR; i++) pariputc(scr[i][JSCR]);
  pariputc('\n');
  for (j=(JSCR-1); j>=2; j--)
  {
    pariputs("          ");
    for (i=1; i<=ISCR; i++) pariputc(scr[i][j]);
    pariputc('\n');
  }
  p1=cgetr(3); gaffect(ysml,p1);
  pariputsf("%s ", dsprintf9(rtodbl(p1), buf));
  for (i=1; i<=ISCR; i++)  pariputc(scr[i][1]);
  pariputc('\n');
  p1=cgetr(3); gaffect(a,p1);
  p2=cgetr(3); gaffect(b,p2);
  pariputsf("%10s%-9.7g%*.7g\n"," ",rtodbl(p1),ISCR-9,rtodbl(p2));
  pop_val(ep); avma=av;
  free(y);
}
 ==end==