Code coverage tests

This page documents the degree to which the PARI/GP source code is tested by our public test suite, distributed with the source distribution in directory src/test/. This is measured by the gcov utility; we then process gcov output using the lcov frond-end.

We test a few variants depending on Configure flags on the pari.math.u-bordeaux.fr machine (x86_64 architecture), and agregate them in the final report:

The target is 90% coverage for all mathematical modules (given that branches depending on DEBUGLEVEL or DEBUGMEM are not covered). This script is run to produce the results below.

LCOV - code coverage report
Current view: top level - graph - plotport.c (source / functions) Hit Total Coverage
Test: PARI/GP v2.8.0 lcov report (development 19242-33fa882) Lines: 844 1177 71.7 %
Date: 2016-07-31 07:11:10 Functions: 76 90 84.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* Copyright (C) 2000  The PARI group.
       2             : 
       3             : This file is part of the PARI/GP package.
       4             : 
       5             : PARI/GP is free software; you can redistribute it and/or modify it under the
       6             : terms of the GNU General Public License as published by the Free Software
       7             : Foundation. It is distributed in the hope that it will be useful, but WITHOUT
       8             : ANY WARRANTY WHATSOEVER.
       9             : 
      10             : Check the License for details. You should have received a copy of it, along
      11             : with the package; see the file 'COPYING'. If not, write to the Free Software
      12             : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
      13             : 
      14             : /*******************************************************************/
      15             : /*                                                                 */
      16             : /*                         PLOT ROUTINES                           */
      17             : /*                                                                 */
      18             : /*******************************************************************/
      19             : #include "pari.h"
      20             : #include "paripriv.h"
      21             : #include "rect.h"
      22             : 
      23             : void postdraw0(long *w, long *x, long *y, long lw, long scale);
      24             : static void PARI_get_psplot(void);
      25             : 
      26             : /* no need for THREAD: OK to share this */
      27             : static hashtable *rgb_colors = NULL;
      28             : PariRect *rectgraph[18]; /*NUMRECT*/
      29             : 
      30             : /* no need for THREAD: gp-specific */
      31             : static long current_color[18]; /*NUMRECT*/
      32             : 
      33             : PARI_plot pari_plot, pari_psplot;
      34             : PARI_plot *pari_plot_engine = &pari_plot;
      35             : long rectpoint_itype = 0, rectline_itype  = 0;
      36             : 
      37             : const long NUMRECT = 18;
      38             : const long RECUR_MAXDEPTH = 10;
      39             : const double RECUR_PREC = 0.001;
      40             : const long DEFAULT_COLOR = 1, AXIS_COLOR = 2;
      41             : 
      42             : INLINE long
      43     2180528 : DTOL(double t) { return (long)(t + 0.5); }
      44             : 
      45             : static GEN
      46     3654690 : READ_EXPR(GEN code, GEN x) {
      47     3654690 :   if (typ(code)!=t_CLOSURE) return gsubst(code,0,x);
      48     3654690 :   set_lex(-1, x); return closure_evalgen(code);
      49             : }
      50             : 
      51             : /********************************************************************/
      52             : /**                                                                **/
      53             : /**                      RECTPLOT FUNCTIONS                        **/
      54             : /**                                                                **/
      55             : /********************************************************************/
      56             : void
      57        1836 : init_graph(void)
      58             : {
      59             :   long n;
      60       34884 :   for (n=0; n<NUMRECT; n++)
      61             :   {
      62       33048 :     PariRect *e = (PariRect*) pari_malloc(sizeof(PariRect));
      63       33048 :     e->head = e->tail = NULL;
      64       33048 :     e->sizex = e->sizey = 0;
      65       33048 :     current_color[n] = DEFAULT_COLOR;
      66       33048 :     rectgraph[n] = e;
      67             :   }
      68        1836 : }
      69             : 
      70             : void
      71        1836 : free_graph(void)
      72             : {
      73             :   int i;
      74       34884 :   for (i=0; i<NUMRECT; i++)
      75             :   {
      76       33048 :     PariRect *e = rectgraph[i];
      77       33048 :     if (RHead(e)) killrect(i);
      78       33048 :     pari_free((void *)e);
      79             :   }
      80        1836 :   if (rgb_colors)
      81             :   {
      82         519 :     pari_free((void*)rgb_colors->table);
      83         519 :     pari_free((void*)rgb_colors);
      84             :   }
      85        1836 :   if (GP_DATA->colormap) pari_free(GP_DATA->colormap);
      86        1836 :   if (GP_DATA->graphcolors) pari_free(GP_DATA->graphcolors);
      87        1836 : }
      88             : 
      89             : static PariRect *
      90       50490 : check_rect(long ne)
      91             : {
      92       50490 :   const long m = NUMRECT-1;
      93       50490 :   if (ne < 0)
      94         512 :     pari_err_DOMAIN("graphic function", "rectwindow", "<", gen_0, stoi(ne));
      95       49978 :   if (ne > m)
      96         512 :     pari_err_DOMAIN("graphic function", "rectwindow", ">", stoi(m), stoi(ne));
      97       49466 :   return rectgraph[ne];
      98             : }
      99             : 
     100             : static PariRect *
     101       41681 : check_rect_init(long ne)
     102             : {
     103       41681 :   PariRect *e = check_rect(ne);
     104       40657 :   if (!RHead(e))
     105       12288 :     pari_err_TYPE("graphic function [use plotinit() first]", stoi(ne));
     106       28369 :   return e;
     107             : }
     108             : 
     109             : static long
     110        3626 : initrect_get_arg(GEN x, long flag, long *dft)
     111             : { /* FIXME: gequal0(x) undocumented backward compatibility hack */
     112        3626 :   if (!x || gequal0(x) || flag) { PARI_get_plot(); return *dft - 1; }
     113          42 :   if (typ(x) != t_INT) pari_err_TYPE("initrect",x);
     114          42 :   return itos(x);
     115             : }
     116             : void
     117        3605 : initrect_gen(long ne, GEN x, GEN y, long flag)
     118             : {
     119        3605 :   const long m = NUMRECT-3;
     120             :   long xi, yi;
     121             : 
     122        3605 :   xi = initrect_get_arg(x, flag, &pari_plot.width);
     123          21 :   yi = initrect_get_arg(y, flag, &pari_plot.height);
     124          21 :   if (flag) {
     125           0 :     if (x) xi = DTOL(xi * gtodouble(x));
     126           0 :     if (y) yi = DTOL(yi * gtodouble(y));
     127             :   }
     128          21 :   if (ne > m)
     129           0 :     pari_err_DOMAIN("graphic function", "rectwindow", ">", stoi(m), stoi(ne));
     130          21 :   initrect(ne, xi, yi);
     131          21 : }
     132             : 
     133             : static void
     134      170202 : Rchain(PariRect *e, RectObj *z)
     135             : {
     136      170202 :   if (!RHead(e)) RHead(e) = z; else RoNext(RTail(e)) = z;
     137      170202 :   RTail(e) = z;
     138      170202 :   RoNext(z) = NULL;
     139      170202 : }
     140             : 
     141             : void
     142        2111 : initrect(long ne, long x, long y)
     143             : {
     144             :   PariRect *e;
     145             :   RectObj *z;
     146             : 
     147        2111 :   if (x <= 1) pari_err_DOMAIN("initrect", "x", "<=", gen_1, stoi(x));
     148        2111 :   if (y <= 1) pari_err_DOMAIN("initrect", "y", "<=", gen_1, stoi(y));
     149        2111 :   e = check_rect(ne); if (RHead(e)) killrect(ne);
     150             : 
     151        2111 :   z = (RectObj*) pari_malloc(sizeof(RectObj));
     152        2111 :   RoType(z) = ROt_NULL;
     153        2111 :   Rchain(e, z);
     154        2111 :   RXsize(e) = x; RXcursor(e) = 0;
     155        2111 :   RYsize(e) = y; RYcursor(e) = 0;
     156        2111 :   RXscale(e) = 1; RXshift(e) = 0;
     157        2111 :   RYscale(e) = 1; RYshift(e) = 0;
     158        2111 :   RHasGraph(e) = 0;
     159        2111 : }
     160             : 
     161             : GEN
     162         547 : rectcursor(long ne)
     163             : {
     164         547 :   PariRect *e = check_rect_init(ne);
     165          35 :   return mkvec2s((long)RXcursor(e), (long)RYcursor(e));
     166             : }
     167             : 
     168             : static void
     169        1564 : rectscale0(long ne, double x1, double x2, double y1, double y2)
     170             : {
     171        1564 :   PariRect *e = check_rect_init(ne);
     172             :   double x, y;
     173             : 
     174        1052 :   x = RXshift(e) + RXscale(e) * RXcursor(e);
     175        1052 :   y = RYshift(e) + RYscale(e) * RYcursor(e);
     176        1052 :   RXscale(e) = RXsize(e)/(x2-x1); RXshift(e) = -x1*RXscale(e);
     177        1052 :   RYscale(e) = RYsize(e)/(y1-y2); RYshift(e) = -y2*RYscale(e);
     178        1052 :   RXcursor(e) = (x - RXshift(e)) / RXscale(e);
     179        1052 :   RYcursor(e) = (y - RYshift(e)) / RYscale(e);
     180        1052 : }
     181             : 
     182             : void
     183         519 : rectscale(long ne, GEN x1, GEN x2, GEN y1, GEN y2)
     184             : {
     185         519 :   rectscale0(ne, gtodouble(x1), gtodouble(x2), gtodouble(y1), gtodouble(y2));
     186           7 : }
     187             : 
     188             : static void
     189       11453 : rectmove0(long ne, double x, double y, long relative)
     190             : {
     191       11453 :   PariRect *e = check_rect_init(ne);
     192        7357 :   RectObj *z = (RectObj*) pari_malloc(sizeof(RectObj1P));
     193             : 
     194        7357 :   if (relative) { RXcursor(e) += x; RYcursor(e) += y; }
     195        7350 :   else          { RXcursor(e) = x; RYcursor(e) = y; }
     196        7357 :   RoType(z) = ROt_MV;
     197        7357 :   RoMVx(z) = RXcursor(e) * RXscale(e) + RXshift(e);
     198        7357 :   RoMVy(z) = RYcursor(e) * RYscale(e) + RYshift(e);
     199        7357 :   Rchain(e, z);
     200        7357 : }
     201             : 
     202             : void
     203        3633 : rectmove(long ne, GEN x, GEN y)
     204             : {
     205        3633 :   rectmove0(ne,gtodouble(x),gtodouble(y),0);
     206          49 : }
     207             : 
     208             : void
     209         519 : rectrmove(long ne, GEN x, GEN y)
     210             : {
     211         519 :   rectmove0(ne,gtodouble(x),gtodouble(y),1);
     212           7 : }
     213             : 
     214             : void
     215        1038 : rectpoint0(long ne, double x, double y,long relative) /* code = ROt_MV/ROt_PT */
     216             : {
     217        1038 :   PariRect *e = check_rect_init(ne);
     218          14 :   RectObj *z = (RectObj*) pari_malloc(sizeof(RectObj1P));
     219             : 
     220          14 :   if (relative) { RXcursor(e) += x; RYcursor(e) += y; }
     221           7 :   else          { RXcursor(e) = x; RYcursor(e) = y; }
     222          14 :   RoPTx(z) = RXcursor(e)*RXscale(e) + RXshift(e);
     223          14 :   RoPTy(z) = RYcursor(e)*RYscale(e) + RYshift(e);
     224          28 :   RoType(z) = ( DTOL(RoPTx(z)) < 0
     225          14 :                 || DTOL(RoPTy(z)) < 0 || DTOL(RoPTx(z)) > RXsize(e)
     226          26 :                 || DTOL(RoPTy(z)) > RYsize(e) ) ? ROt_MV : ROt_PT;
     227          14 :   Rchain(e, z);
     228          14 :   RoCol(z) = current_color[ne];
     229          14 : }
     230             : 
     231             : void
     232         519 : rectpoint(long ne, GEN x, GEN y)
     233             : {
     234         519 :   rectpoint0(ne,gtodouble(x),gtodouble(y),0);
     235           7 : }
     236             : 
     237             : void
     238         519 : rectrpoint(long ne, GEN x, GEN y)
     239             : {
     240         519 :   rectpoint0(ne,gtodouble(x),gtodouble(y),1);
     241           7 : }
     242             : 
     243             : void
     244        1024 : rectcolor(long ne, long c)
     245             : {
     246        1024 :   long n = lg(GP_DATA->colormap)-2;
     247        1024 :   check_rect(ne);
     248        1024 :   if (c < 1) pari_err_DOMAIN("rectcolor", "color", "<", gen_1, stoi(c));
     249        1024 :   if (c > n) pari_err_DOMAIN("rectcolor", "color", ">", stoi(n), stoi(c));
     250        1024 :   current_color[ne] = c;
     251        1024 : }
     252             : 
     253             : void
     254        2602 : rectline0(long ne, double gx2, double gy2, long relative) /* code = ROt_MV/ROt_LN */
     255             : {
     256             :   double dx,dy,dxy,xmin,xmax,ymin,ymax,x1,y1,x2,y2;
     257        2602 :   PariRect *e = check_rect_init(ne);
     258        2090 :   RectObj *z = (RectObj*) pari_malloc(sizeof(RectObj2P));
     259        2090 :   const double c = 1 + 1e-10;
     260             : 
     261        2090 :   x1 = RXcursor(e)*RXscale(e) + RXshift(e);
     262        2090 :   y1 = RYcursor(e)*RYscale(e) + RYshift(e);
     263        2090 :   if (relative)
     264           7 :     { RXcursor(e)+=gx2; RYcursor(e)+=gy2; }
     265             :   else
     266        2083 :     { RXcursor(e)=gx2; RYcursor(e)=gy2; }
     267        2090 :   x2 = RXcursor(e)*RXscale(e) + RXshift(e);
     268        2090 :   y2 = RYcursor(e)*RYscale(e) + RYshift(e);
     269        2090 :   xmin = maxdd(mindd(x1,x2),0); xmax = mindd(maxdd(x1,x2),RXsize(e));
     270        2090 :   ymin = maxdd(mindd(y1,y2),0); ymax = mindd(maxdd(y1,y2),RYsize(e));
     271        2090 :   dxy = x1*y2 - y1*x2; dx = x2-x1; dy = y2-y1;
     272        2090 :   if (dy)
     273             :   {
     274        1052 :     if (dx*dy<0)
     275           7 :       { xmin = maxdd(xmin,(dxy+RYsize(e)*dx)/dy); xmax=mindd(xmax,dxy/dy); }
     276             :     else
     277        1045 :       { xmin=maxdd(xmin,dxy/dy); xmax=mindd(xmax,(dxy+RYsize(e)*dx)/dy); }
     278             :   }
     279        2090 :   if (dx)
     280             :   {
     281        1052 :     if (dx*dy<0)
     282           7 :       { ymin=maxdd(ymin,(RXsize(e)*dy-dxy)/dx); ymax=mindd(ymax,-dxy/dx); }
     283             :     else
     284        1045 :       { ymin=maxdd(ymin,-dxy/dx); ymax=mindd(ymax,(RXsize(e)*dy-dxy)/dx); }
     285             :   }
     286        2090 :   RoLNx1(z) = xmin; RoLNx2(z) = xmax;
     287        2090 :   if (dx*dy<0) { RoLNy1(z) = ymax; RoLNy2(z) = ymin; }
     288        2083 :   else         { RoLNy1(z) = ymin; RoLNy2(z) = ymax; }
     289        2090 :   RoType(z) = (xmin>xmax*c || ymin>ymax*c) ? ROt_MV : ROt_LN;
     290        2090 :   Rchain(e, z);
     291        2090 :   RoCol(z) = current_color[ne];
     292        2090 : }
     293             : 
     294             : /* Given coordinates of ends of a line, and labels l1 l2 attached to the
     295             :    ends, plot ticks where the label coordinate takes "round" values */
     296             : 
     297             : static void
     298        4180 : rectticks(PARI_plot *WW, long ne,
     299             :           double dx1, double dy1, double dx2, double dy2,
     300             :           double l1, double l2, long flags)
     301             : {
     302             :   long dx,dy,dxy,dxy1,x1,y1,x2,y2,nticks,n,n1,dn;
     303             :   double minstep, maxstep, step, l_min, l_max, minl, maxl, dl, dtx, dty, x, y;
     304             :   double ddx, ddy;
     305        4180 :   const double mult[3] = { 2./1., 5./2., 10./5. };
     306        4180 :   PariRect *e = check_rect_init(ne);
     307        4180 :   int do_double = !(flags & TICKS_NODOUBLE);
     308             : 
     309        4180 :   x1 = DTOL(dx1*RXscale(e) + RXshift(e));
     310        4180 :   y1 = DTOL(dy1*RYscale(e) + RYshift(e));
     311        4180 :   x2 = DTOL(dx2*RXscale(e) + RXshift(e));
     312        4180 :   y2 = DTOL(dy2*RYscale(e) + RYshift(e));
     313        4180 :   dx = x2 - x1;
     314        4180 :   dy = y2 - y1;
     315        4180 :   if (dx < 0) dx = -dx;
     316        4180 :   if (dy < 0) dy = -dy;
     317        4180 :   dxy1 = maxss(dx, dy);
     318        4180 :   dx /= WW->hunit;
     319        4180 :   dy /= WW->vunit;
     320        4180 :   if (dx > 1000 || dy > 1000)
     321           0 :     dxy = 1000; /* avoid overflow */
     322             :   else
     323        4180 :     dxy = usqrt(dx*dx + dy*dy);
     324        4180 :   nticks = (long) ((dxy + 2.5)/4);
     325        4180 :   if (!nticks) return;
     326             : 
     327             :   /* Now we want to find nticks (or less) "round" numbers between l1 and l2.
     328             :      For our purpose round numbers have "last significant" digit either
     329             :         *) any;
     330             :         *) even;
     331             :         *) divisible by 5.
     332             :      We need to choose which alternative is better.
     333             :    */
     334        4180 :   if (l1 < l2)
     335        2090 :     l_min = l1, l_max = l2;
     336             :   else
     337        2090 :     l_min = l2, l_max = l1;
     338        4180 :   minstep = (l_max - l_min)/(nticks + 1);
     339        4180 :   maxstep = 2.5*(l_max - l_min);
     340        4180 :   step = exp(log(10.) * floor(log10(minstep)));
     341        4180 :   if (!(flags & TICKS_ENDSTOO)) {
     342        4180 :     double d = 2*(l_max - l_min)/dxy1;        /* Two pixels off */
     343             : 
     344        4180 :     l_min += d;
     345        4180 :     l_max -= d;
     346             :   }
     347       12540 :   for (n = 0; ; n++) {
     348       12540 :     if (step >= maxstep) return;
     349             : 
     350       12540 :     if (step >= minstep) {
     351        4180 :       minl = ceil(l_min/step);
     352        4180 :       maxl = floor(l_max/step);
     353        4180 :       if (minl <= maxl && maxl - minl + 1 <= nticks) {
     354        4180 :         nticks = (long) (maxl - minl + 1);
     355        4180 :         l_min = minl * step;
     356        4180 :         l_max = maxl * step; break;
     357             :       }
     358             :     }
     359        8360 :     step *= mult[ n % 3 ];
     360        8360 :   }
     361             :   /* Where to position doubleticks, variants:
     362             :      small: each 5, double: each 10        (n===2 mod 3)
     363             :      small: each 2, double: each 10        (n===1 mod 3)
     364             :      small: each 1, double: each  5 */
     365        4180 :   dn = (n % 3 == 2)? 2: 5;
     366        4180 :   n1 = ((long)minl) % dn; /* unused if do_double = FALSE */
     367             : 
     368             :   /* now l_min and l_max keep min/max values of l with ticks, and nticks is
     369             :      the number of ticks to draw. */
     370        4180 :   if (nticks == 1) ddx = ddy = 0; /* unused: for lint */
     371             :   else {
     372        4180 :     dl = (l_max - l_min)/(nticks - 1);
     373        4180 :     ddx = (dx2 - dx1) * dl / (l2 - l1);
     374        4180 :     ddy = (dy2 - dy1) * dl / (l2 - l1);
     375             :   }
     376        4180 :   x = dx1 + (dx2 - dx1) * (l_min - l1) / (l2 - l1);
     377        4180 :   y = dy1 + (dy2 - dy1) * (l_min - l1) / (l2 - l1);
     378             :   /* assume hunit and vunit form a square.  For clockwise ticks: */
     379        4180 :   dtx = WW->hunit * dy/dxy * (y2 > y1 ? 1 : -1);        /* y-coord runs down */
     380        4180 :   dty = WW->vunit * dx/dxy * (x2 > x1 ? 1 : -1);
     381      151280 :   for (n = 0; n < nticks; n++) {
     382      147100 :     RectObj *z = (RectObj*) pari_malloc(sizeof(RectObj2P));
     383      147100 :     double lunit = WW->hunit > 1 ? 1.5 : 2;
     384      147100 :     double l = (do_double && (n + n1) % dn == 0) ? lunit: 1;
     385             : 
     386      147100 :     RoLNx1(z) = RoLNx2(z) = x*RXscale(e) + RXshift(e);
     387      147100 :     RoLNy1(z) = RoLNy2(z) = y*RYscale(e) + RYshift(e);
     388             : 
     389      147100 :     if (flags & TICKS_CLOCKW) {
     390      147100 :       RoLNx1(z) += dtx*l;
     391      147100 :       RoLNy1(z) -= dty*l; /* y-coord runs down */
     392             :     }
     393      147100 :     if (flags & TICKS_ACLOCKW) {
     394           0 :       RoLNx2(z) -= dtx*l;
     395           0 :       RoLNy2(z) += dty*l; /* y-coord runs down */
     396             :     }
     397      147100 :     RoType(z) = ROt_LN;
     398             : 
     399      147100 :     Rchain(e, z);
     400      147100 :     RoCol(z) = current_color[ne];
     401      147100 :     x += ddx;
     402      147100 :     y += ddy;
     403             :   }
     404             : }
     405             : 
     406             : void
     407           7 : rectline(long ne, GEN gx2, GEN gy2)
     408             : {
     409           7 :   rectline0(ne, gtodouble(gx2), gtodouble(gy2),0);
     410           7 : }
     411             : 
     412             : void
     413         519 : rectrline(long ne, GEN gx2, GEN gy2)
     414             : {
     415         519 :   rectline0(ne, gtodouble(gx2), gtodouble(gy2),1);
     416           7 : }
     417             : 
     418             : void
     419        1571 : rectbox0(long ne, double gx2, double gy2, long relative)
     420             : {
     421             :   double x1,y1,x2,y2,xmin,ymin,xmax,ymax;
     422             :   double xx,yy;
     423        1571 :   PariRect *e = check_rect_init(ne);
     424        1059 :   RectObj *z = (RectObj*) pari_malloc(sizeof(RectObj2P));
     425             : 
     426        1059 :   x1 = RXcursor(e)*RXscale(e) + RXshift(e);
     427        1059 :   y1 = RYcursor(e)*RYscale(e) + RYshift(e);
     428        1059 :   if (relative)
     429           7 :   { xx = RXcursor(e)+gx2; yy = RYcursor(e)+gy2; }
     430             :   else
     431        1052 :   {  xx = gx2; yy = gy2; }
     432        1059 :   x2 = xx*RXscale(e) + RXshift(e);
     433        1059 :   y2 = yy*RYscale(e) + RYshift(e);
     434        1059 :   xmin = maxdd(mindd(x1,x2),0); xmax = mindd(maxdd(x1,x2),RXsize(e));
     435        1059 :   ymin = maxdd(mindd(y1,y2),0); ymax = mindd(maxdd(y1,y2),RYsize(e));
     436             : 
     437        1059 :   RoType(z) = ROt_BX;
     438        1059 :   RoBXx1(z) = xmin; RoBXy1(z) = ymin;
     439        1059 :   RoBXx2(z) = xmax; RoBXy2(z) = ymax;
     440        1059 :   Rchain(e, z);
     441        1059 :   RoCol(z) = current_color[ne];
     442        1059 : }
     443             : 
     444             : void
     445         519 : rectbox(long ne, GEN gx2, GEN gy2)
     446             : {
     447         519 :   rectbox0(ne, gtodouble(gx2), gtodouble(gy2), 0);
     448           7 : }
     449             : 
     450             : void
     451           7 : rectrbox(long ne, GEN gx2, GEN gy2)
     452             : {
     453           7 :   rectbox0(ne, gtodouble(gx2), gtodouble(gy2), 1);
     454           7 : }
     455             : 
     456             : static void
     457      170202 : freeobj(RectObj *z) {
     458      170202 :   switch(RoType(z)) {
     459             :     case ROt_MP: case ROt_ML:
     460        1059 :       pari_free(RoMPxs(z));
     461        1059 :       pari_free(RoMPys(z)); break;
     462             :     case ROt_ST:
     463        4194 :       pari_free(RoSTs(z)); break;
     464             :   }
     465      170202 :   pari_free(z);
     466      170202 : }
     467             : 
     468             : 
     469             : void
     470        4159 : killrect(long ne)
     471             : {
     472             :   RectObj *z, *t;
     473        4159 :   PariRect *e = check_rect_init(ne);
     474             : 
     475        2111 :   current_color[ne]=DEFAULT_COLOR;
     476        2111 :   z=RHead(e);
     477        2111 :   RHead(e) = RTail(e) = NULL;
     478        2111 :   RXsize(e) = RYsize(e) = 0;
     479        2111 :   RXcursor(e) = RYcursor(e) = 0;
     480        2111 :   RXscale(e) = RYscale(e) = 1;
     481        2111 :   RXshift(e) = RYshift(e) = 0;
     482        2111 :   while (z) { t = RoNext(z); freeobj(z); z = t; }
     483        2111 : }
     484             : 
     485             : void
     486         526 : rectpoints0(long ne, double *listx, double *listy, long lx) /* code = ROt_MP */
     487             : {
     488             :   double *ptx, *pty, x, y;
     489         526 :   long i, cp=0;
     490         526 :   PariRect *e = check_rect_init(ne);
     491          14 :   RectObj *z = (RectObj*) pari_malloc(sizeof(RectObjMP));
     492             : 
     493          14 :   RoMPxs(z) = ptx = (double*) pari_malloc(lx*sizeof(double));
     494          14 :   RoMPys(z) = pty = (double*) pari_malloc(lx*sizeof(double));
     495         784 :   for (i=0; i<lx; i++)
     496             :   {
     497         770 :     x = RXscale(e)*listx[i] + RXshift(e);
     498         770 :     y = RYscale(e)*listy[i] + RYshift(e);
     499         770 :     if (x>=0 && y>=0 && x<=RXsize(e) && y<=RYsize(e))
     500             :     {
     501         769 :       ptx[cp]=x; pty[cp]=y; cp++;
     502             :     }
     503             :   }
     504          14 :   RoType(z) = ROt_MP;
     505          14 :   RoMPcnt(z) = cp;
     506          14 :   Rchain(e, z);
     507          14 :   RoCol(z) = current_color[ne];
     508          14 : }
     509             : 
     510             : void
     511        1038 : rectpoints(long ne, GEN listx, GEN listy)
     512             : {
     513        1038 :   long i,lx, tx=typ(listx), ty=typ(listy);
     514             :   double *px,*py;
     515             : 
     516        1038 :   if (!is_matvec_t(tx) || !is_matvec_t(ty)) {
     517         519 :     rectpoint(ne, listx, listy); return;
     518             :   }
     519         519 :   lx = lg(listx);
     520         519 :   if (tx == t_MAT) pari_err_TYPE("rectpoints",listx);
     521         519 :   if (ty == t_MAT) pari_err_TYPE("rectpoints",listy);
     522         519 :   if (lg(listy) != lx) pari_err_DIM("rectpoints");
     523         519 :   lx--; if (!lx) return;
     524             : 
     525         519 :   px = (double*) pari_malloc(lx*sizeof(double)); listx++;
     526         519 :   py = (double*) pari_malloc(lx*sizeof(double)); listy++;
     527        5709 :   for (i=0; i<lx; i++)
     528             :   {
     529        5190 :     px[i] = gtodouble(gel(listx,i));
     530        5190 :     py[i] = gtodouble(gel(listy,i));
     531             :   }
     532         519 :   rectpoints0(ne,px,py,lx);
     533           7 :   pari_free(px); pari_free(py);
     534             : }
     535             : 
     536             : void
     537        1557 : rectlines0(long ne, double *x, double *y, long lx, long flag) /* code = ROt_ML */
     538             : {
     539             :   long i,I;
     540             :   double *ptx,*pty;
     541        1557 :   PariRect *e = check_rect_init(ne);
     542        1045 :   RectObj *z = (RectObj*) pari_malloc(sizeof(RectObj2P));
     543             : 
     544        1045 :   I = flag ? lx+1 : lx;
     545        1045 :   ptx = (double*) pari_malloc(I*sizeof(double));
     546        1045 :   pty = (double*) pari_malloc(I*sizeof(double));
     547      777292 :   for (i=0; i<lx; i++)
     548             :   {
     549      776247 :     ptx[i] = RXscale(e)*x[i] + RXshift(e);
     550      776247 :     pty[i] = RYscale(e)*y[i] + RYshift(e);
     551             :   }
     552        1045 :   if (flag)
     553             :   {
     554           0 :     ptx[i] = RXscale(e)*x[0] + RXshift(e);
     555           0 :     pty[i] = RYscale(e)*y[0] + RYshift(e);
     556             :   }
     557        1045 :   Rchain(e, z);
     558        1045 :   RoType(z) = ROt_ML;
     559        1045 :   RoMLcnt(z) = lx;
     560        1045 :   RoMLxs(z) = ptx;
     561        1045 :   RoMLys(z) = pty;
     562        1045 :   RoCol(z) = current_color[ne];
     563        1045 : }
     564             : 
     565             : void
     566         526 : rectlines(long ne, GEN listx, GEN listy, long flag)
     567             : {
     568         526 :   long tx=typ(listx), ty=typ(listy), lx=lg(listx), i;
     569             :   double *x, *y;
     570             : 
     571         526 :   if (!is_matvec_t(tx) || !is_matvec_t(ty))
     572             :   {
     573           7 :     rectline(ne, listx, listy); return;
     574             :   }
     575         519 :   if (tx == t_MAT) pari_err_TYPE("rectlines",listx);
     576         519 :   if (ty == t_MAT) pari_err_TYPE("rectlines",listy);
     577         519 :   if (lg(listy) != lx) pari_err_DIM("rectlines");
     578         519 :   lx--; if (!lx) return;
     579             : 
     580         519 :   x = (double*) pari_malloc(lx*sizeof(double));
     581         519 :   y = (double*) pari_malloc(lx*sizeof(double));
     582        3114 :   for (i=0; i<lx; i++)
     583             :   {
     584        2595 :     x[i] = gtodouble(gel(listx,i+1));
     585        2595 :     y[i] = gtodouble(gel(listy,i+1));
     586             :   }
     587         519 :   rectlines0(ne,x,y,lx,flag);
     588           7 :   pari_free(x); pari_free(y);
     589             : }
     590             : 
     591             : static void
     592        4180 : put_label(long ne, long x, long y, double d, long dir)
     593             : {
     594             :   char c[16];
     595        4180 :   sprintf(c,"%.5g", d);
     596        4180 :   rectmove0(ne,(double)x,(double)y,0);
     597        4180 :   rectstring3(ne, c, dir);
     598        4180 : }
     599             : 
     600             : void
     601           0 : rectstring(long ne, char *str)
     602             : {
     603           0 :   rectstring3(ne,str,RoSTdirLEFT);
     604           0 : }
     605             : 
     606             : /* Allocate memory, then put string */
     607             : void
     608        4194 : rectstring3(long ne, char *str, long dir) /* code = ROt_ST */
     609             : {
     610        4194 :   PariRect *e = check_rect_init(ne);
     611        4194 :   RectObj *z = (RectObj*) pari_malloc(sizeof(RectObjST));
     612        4194 :   long l = strlen(str);
     613        4194 :   char *s = (char *) pari_malloc(l+1);
     614             : 
     615        4194 :   memcpy(s,str,l+1);
     616        4194 :   RoType(z) = ROt_ST;
     617        4194 :   RoSTl(z) = l;
     618        4194 :   RoSTs(z) = s;
     619        4194 :   RoSTx(z) = RXscale(e)*RXcursor(e)+RXshift(e);
     620        4194 :   RoSTy(z) = RYscale(e)*RYcursor(e)+RYshift(e);
     621        4194 :   RoSTdir(z) = dir;
     622        4194 :   Rchain(e, z);
     623        4194 :   RoCol(z) = current_color[ne];
     624        4194 : }
     625             : 
     626             : void
     627           7 : rectpointtype(long ne, long type) /* code = ROt_PTT */
     628             : {
     629           7 :  if (ne == -1) {
     630           0 :    rectpoint_itype = type;
     631             :  } else {
     632           7 :    PariRect *e = check_rect_init(ne);
     633           7 :    RectObj *z = (RectObj*) pari_malloc(sizeof(RectObjPN));
     634             : 
     635           7 :    RoType(z) = ROt_PTT;
     636           7 :    RoPTTpen(z) = type;
     637           7 :    Rchain(e, z);
     638             :  }
     639           7 : }
     640             : 
     641             : /*FIXME: this function is a noop, since no graphic driver implement
     642             :  * the ROt_PTS code. ne==-1 is a legacy, meaningless value. */
     643             : void
     644           0 : rectpointsize(long ne, GEN size) /* code = ROt_PTS */
     645             : {
     646           0 :  if (ne == -1) { /*do nothing*/ }
     647             :  else {
     648           0 :    PariRect *e = check_rect_init(ne);
     649           0 :    RectObj *z = (RectObj*) pari_malloc(sizeof(RectObjPS));
     650             : 
     651           0 :    RoType(z) = ROt_PTS;
     652           0 :    RoPTSsize(z) = gtodouble(size);
     653           0 :    Rchain(e, z);
     654             :  }
     655           0 : }
     656             : 
     657             : void
     658        5211 : rectlinetype(long ne, long type)
     659             : {
     660        5211 :  if (ne == -1) {
     661           0 :    rectline_itype = type;
     662             :  } else {
     663        5211 :    PariRect *e = check_rect_init(ne);
     664        5211 :    RectObj *z = (RectObj*) pari_malloc(sizeof(RectObjPN));
     665             : 
     666        5211 :    RoType(z) = ROt_LNT;
     667        5211 :    RoLNTpen(z) = type;
     668        5211 :    Rchain(e, z);
     669             :  }
     670        5211 : }
     671             : 
     672             : void
     673        4608 : rectcopy_gen(long source, long dest, GEN xoff, GEN yoff, long flag)
     674             : {
     675             :   long xi, yi;
     676        4608 :   if (flag & RECT_CP_RELATIVE) {
     677        4096 :     double xd = gtodouble(xoff), yd = gtodouble(yoff);
     678        4096 :     if (xd > 1) pari_err_DOMAIN("plotcopy","dx",">",gen_1,xoff);
     679        3584 :     if (xd < 0) pari_err_DOMAIN("plotcopy","dx","<",gen_0,xoff);
     680        3072 :     if (yd > 1) pari_err_DOMAIN("plotcopy","dy",">",gen_1,yoff);
     681        2560 :     if (yd < 0) pari_err_DOMAIN("plotcopy","dy","<",gen_0,yoff);
     682        2048 :     PARI_get_plot();
     683           0 :     xi = pari_plot.width - 1;
     684           0 :     yi = pari_plot.height - 1;
     685           0 :     xi = DTOL(xd*xi);
     686           0 :     yi = DTOL(yd*yi);
     687             :   } else {
     688         512 :     if (typ(xoff) != t_INT) pari_err_TYPE("plotcopy",xoff);
     689         512 :     if (typ(yoff) != t_INT) pari_err_TYPE("plotcopy",yoff);
     690         512 :     xi = itos(xoff);
     691         512 :     yi = itos(yoff);
     692             :   }
     693         512 :   if (flag & ~RECT_CP_RELATIVE) {
     694           0 :     PariRect *s = check_rect_init(source), *d = check_rect_init(dest);
     695             : 
     696           0 :     switch (flag & ~RECT_CP_RELATIVE) {
     697             :       case RECT_CP_NW:
     698           0 :         break;
     699             :       case RECT_CP_SW:
     700           0 :         yi = RYsize(d) - RYsize(s) - yi;
     701           0 :         break;
     702             :       case RECT_CP_SE:
     703           0 :         yi = RYsize(d) - RYsize(s) - yi;
     704             :         /* FALL THROUGH */
     705             :       case RECT_CP_NE:
     706           0 :         xi = RXsize(d) - RXsize(s) - xi;
     707           0 :         break;
     708             :     }
     709             :   }
     710         512 :   rectcopy(source, dest, xi, yi);
     711           0 : }
     712             : 
     713             : static void*
     714           0 : cp(void* R, size_t t)
     715           0 : { void *o = pari_malloc(t); memcpy(o,R,t); return o; }
     716             : 
     717             : void
     718         512 : rectcopy(long source, long dest, long x, long y)
     719             : {
     720         512 :   PariRect *s = check_rect_init(source), *d = check_rect_init(dest);
     721           0 :   RectObj *R, *tail = RTail(d);
     722             :   long i;
     723             : 
     724           0 :   for (R = RHead(s); R; R = RoNext(R))
     725             :   {
     726             :     RectObj *o;
     727           0 :     switch(RoType(R))
     728             :     {
     729             :       case ROt_PT:
     730           0 :         o = (RectObj*)cp(R, sizeof(RectObj1P));
     731           0 :         RoPTx(o) += x; RoPTy(o) += y;
     732           0 :         break;
     733             :       case ROt_LN: case ROt_BX:
     734           0 :         o = (RectObj*)cp(R, sizeof(RectObj2P));
     735           0 :         RoLNx1(o) += x; RoLNy1(o) += y;
     736           0 :         RoLNx2(o) += x; RoLNy2(o) += y;
     737           0 :         break;
     738             :       case ROt_MP: case ROt_ML:
     739           0 :         o = (RectObj*)cp(R, sizeof(RectObjMP));
     740           0 :         RoMPxs(o) = (double*)cp(RoMPxs(R), sizeof(double)*RoMPcnt(o));
     741           0 :         RoMPys(o) = (double*)cp(RoMPys(R), sizeof(double)*RoMPcnt(o));
     742           0 :         for (i=0; i<RoMPcnt(o); i++) { RoMPxs(o)[i] += x; RoMPys(o)[i] += y; }
     743           0 :         break;
     744             :       case ROt_ST:
     745           0 :         o = (RectObj*)cp(R, sizeof(RectObjST));
     746           0 :         RoSTs(o) = (char*)cp(RoSTs(R),RoSTl(R)+1);
     747           0 :         RoSTx(o) += x; RoSTy(o) += y;
     748           0 :         break;
     749             :       default: /* ROt_PTT, ROt_LNT, ROt_PTS */
     750           0 :         o = (RectObj*)cp(R, sizeof(RectObjPN));
     751           0 :         break;
     752             :     }
     753           0 :     RoNext(tail) = o; tail = o;
     754             :   }
     755           0 :   RoNext(tail) = NULL; RTail(d) = tail;
     756           0 : }
     757             : 
     758             : enum {CLIPLINE_NONEMPTY = 1, CLIPLINE_CLIP_1 = 2, CLIPLINE_CLIP_2 = 4};
     759             : /* A simpler way is to clip by 4 half-planes */
     760             : static int
     761           0 : clipline(double xmin, double xmax, double ymin, double ymax,
     762             :          double *x1p, double *y1p, double *x2p, double *y2p)
     763             : {
     764           0 :   int xy_exch = 0, rc = CLIPLINE_NONEMPTY;
     765             :   double t, sl;
     766             :   double xi, xmn, xmx;
     767             :   double yi, ymn, ymx;
     768             :   int x1_is_ymn, x1_is_xmn;
     769           0 :   double x1 = *x1p, x2 = *x2p, y1 = *y1p, y2 = *y2p;
     770             : 
     771           0 :   if ((x1 < xmin &&  x2 < xmin) || (x1 > xmax && x2 > xmax))
     772           0 :     return 0;
     773           0 :   if (fabs(x1 - x2) < fabs(y1 - y2)) { /* Exchange x and y */
     774           0 :     xy_exch = 1;
     775           0 :     dswap(xmin, ymin); dswap(x1, y1);
     776           0 :     dswap(xmax, ymax); dswap(x2, y2);
     777             :   }
     778             : 
     779             :   /* Build y as a function of x */
     780           0 :   xi = x1;
     781           0 :   yi = y1;
     782           0 :   sl = x1==x2? 0: (y2 - yi)/(x2 - xi);
     783             : 
     784           0 :   if (x1 > x2) {
     785           0 :     x1_is_xmn = 0;
     786           0 :     xmn = x2;
     787           0 :     xmx = x1;
     788             :   } else {
     789           0 :     x1_is_xmn = 1;
     790           0 :     xmn = x1;
     791           0 :     xmx = x2;
     792             :   }
     793             : 
     794           0 :   if (xmn < xmin) {
     795           0 :     xmn = xmin;
     796           0 :     rc |= x1_is_xmn? CLIPLINE_CLIP_1: CLIPLINE_CLIP_2;
     797             :   }
     798           0 :   if (xmx > xmax) {
     799           0 :     xmx = xmax;
     800           0 :     rc |= x1_is_xmn? CLIPLINE_CLIP_2: CLIPLINE_CLIP_1;
     801             :   }
     802           0 :   if (xmn > xmx) return 0;
     803             : 
     804           0 :   ymn = yi + (xmn - xi)*sl;
     805           0 :   ymx = yi + (xmx - xi)*sl;
     806             : 
     807           0 :   if (sl < 0) t = ymn, ymn = ymx, ymx = t;
     808           0 :   if (ymn > ymax || ymx < ymin) return 0;
     809             : 
     810           0 :   if (rc & CLIPLINE_CLIP_1) x1 = x1_is_xmn? xmn: xmx;
     811           0 :   if (rc & CLIPLINE_CLIP_2) x2 = x1_is_xmn? xmx: xmn;
     812             : 
     813             :   /* Now we know there is an intersection, need to move x1 and x2 */
     814           0 :   x1_is_ymn = ((sl >= 0) == (x1 < x2));
     815           0 :   if (ymn < ymin) {
     816           0 :     double x = (ymin - yi)/sl + xi; /* slope != 0  ! */
     817           0 :     if (x1_is_ymn) x1 = x, rc |= CLIPLINE_CLIP_1;
     818           0 :     else           x2 = x, rc |= CLIPLINE_CLIP_2;
     819             :   }
     820           0 :   if (ymx > ymax) {
     821           0 :     double x = (ymax - yi)/sl + xi; /* slope != 0  ! */
     822           0 :     if (x1_is_ymn) x2 = x, rc |= CLIPLINE_CLIP_2;
     823           0 :     else           x1 = x, rc |= CLIPLINE_CLIP_1;
     824             :   }
     825           0 :   if (rc & CLIPLINE_CLIP_1) y1 = yi + (x1 - xi)*sl;
     826           0 :   if (rc & CLIPLINE_CLIP_2) y2 = yi + (x2 - xi)*sl;
     827           0 :   if (xy_exch) /* Exchange x and y */
     828           0 :     *x1p = y1, *x2p = y2, *y1p = x1, *y2p = x2;
     829             :   else
     830           0 :     *x1p = x1, *x2p = x2, *y1p = y1, *y2p = y2;
     831           0 :   return rc;
     832             : }
     833             : 
     834             : void
     835        2560 : rectclip(long rect)
     836             : {
     837        2560 :   PariRect *s = check_rect_init(rect);
     838           0 :   RectObj *next, *R = RHead(s), **prevp = &RHead(s);
     839           0 :   double xmin = 0, xmax = RXsize(s);
     840           0 :   double ymin = 0, ymax = RYsize(s);
     841             : 
     842           0 :   for (; R; R = next) {
     843           0 :     int did_clip = 0;
     844             : #define REMOVE() { *prevp = next; freeobj(R); break; }
     845             : #define NEXT() { prevp = &RoNext(R); break; }
     846             : 
     847           0 :     next = RoNext(R);
     848           0 :     switch(RoType(R)) {
     849             :       case ROt_PT:
     850           0 :         if ( DTOL(RoPTx(R)) < xmin || DTOL(RoPTx(R)) > xmax
     851           0 :           || DTOL(RoPTy(R)) < ymin || DTOL(RoPTy(R)) > ymax) REMOVE();
     852           0 :         NEXT();
     853             :       case ROt_BX:
     854           0 :         if (RoLNx1(R) < xmin) RoLNx1(R) = xmin, did_clip = 1;
     855           0 :         if (RoLNx2(R) < xmin) RoLNx2(R) = xmin, did_clip = 1;
     856           0 :         if (RoLNy1(R) < ymin) RoLNy1(R) = ymin, did_clip = 1;
     857           0 :         if (RoLNy2(R) < ymin) RoLNy2(R) = ymin, did_clip = 1;
     858           0 :         if (RoLNx1(R) > xmax) RoLNx1(R) = xmax, did_clip = 1;
     859           0 :         if (RoLNx2(R) > xmax) RoLNx2(R) = xmax, did_clip = 1;
     860           0 :         if (RoLNy1(R) > ymax) RoLNy1(R) = ymax, did_clip = 1;
     861           0 :         if (RoLNy2(R) > ymax) RoLNy2(R) = ymax, did_clip = 1;
     862             :         /* Remove zero-size clipped boxes */
     863           0 :         if (did_clip && RoLNx1(R) == RoLNx2(R)
     864           0 :                      && RoLNy1(R) == RoLNy2(R)) REMOVE();
     865           0 :         NEXT();
     866             :       case ROt_LN:
     867           0 :         if (!clipline(xmin, xmax, ymin, ymax,
     868             :                       &RoLNx1(R), &RoLNy1(R),
     869           0 :                       &RoLNx2(R), &RoLNy2(R))) REMOVE();
     870           0 :         NEXT();
     871             :       case ROt_MP: {
     872           0 :         int c = RoMPcnt(R), f = 0, t = 0;
     873             : 
     874           0 :         while (f < c) {
     875           0 :           if ( DTOL(RoMPxs(R)[f]) >= xmin && DTOL(RoMPxs(R)[f]) <= xmax
     876           0 :             && DTOL(RoMPys(R)[f]) >= ymin && DTOL(RoMPys(R)[f]) <= ymax) {
     877           0 :             if (t != f) {
     878           0 :               RoMPxs(R)[t] = RoMPxs(R)[f];
     879           0 :               RoMPys(R)[t] = RoMPys(R)[f];
     880             :             }
     881           0 :             t++;
     882             :           }
     883           0 :           f++;
     884             :         }
     885           0 :         if (t == 0) REMOVE();
     886           0 :         RoMPcnt(R) = t;
     887           0 :         NEXT();
     888             :       }
     889             :       case ROt_ML: {
     890             :         /* Hard case. Break a multiline into several pieces
     891             :          * if some part is clipped. */
     892           0 :         int c = RoMPcnt(R) - 1;
     893           0 :         int f = 0, t = 0, had_lines = 0, had_hole = 0, rc;
     894           0 :         double ox = RoMLxs(R)[0], oy = RoMLys(R)[0], oxn, oyn;
     895             : 
     896           0 :         while (f < c) {
     897             :         /* Endpoint of this segment is startpoint of next one: need to
     898             :          * preserve it if it is clipped. */
     899           0 :           oxn = RoMLxs(R)[f+1];
     900           0 :           oyn = RoMLys(R)[f+1];
     901           0 :           rc = clipline(xmin, xmax, ymin, ymax,
     902             :                   &ox, &oy, /* &RoMLxs(R)[f], &RoMLys(R)[f], */
     903           0 :                   &RoMLxs(R)[f+1], &RoMLys(R)[f+1]);
     904           0 :           RoMLxs(R)[f] = ox; ox = oxn;
     905           0 :           RoMLys(R)[f] = oy; oy = oyn;
     906           0 :           if (!rc) {
     907           0 :             if (had_lines) had_hole = 1;
     908           0 :             f++; continue;
     909             :           }
     910             : 
     911           0 :           if (!had_lines || (!(rc & CLIPLINE_CLIP_1) && !had_hole) ) {
     912             :             /* Continuous */
     913           0 :             had_lines = 1;
     914           0 :             if (t != f) {
     915           0 :               if (t == 0) {
     916           0 :                 RoMPxs(R)[t] = RoMPxs(R)[f];
     917           0 :                 RoMPys(R)[t] = RoMPys(R)[f];
     918             :               }
     919           0 :               RoMPxs(R)[t+1] = RoMPxs(R)[f+1];
     920           0 :               RoMPys(R)[t+1] = RoMPys(R)[f+1];
     921             :             }
     922           0 :             t++;
     923           0 :             f++;
     924           0 :             if (rc & CLIPLINE_CLIP_2) had_hole = 1, RoMLcnt(R) = t+1;
     925           0 :             continue;
     926             :           }
     927             :           /* Is not continuous, automatically R is not pari_free()ed.  */
     928           0 :           t++;
     929           0 :           RoMLcnt(R) = t;
     930           0 :           if (rc & CLIPLINE_CLIP_2) { /* Needs separate entry */
     931           0 :             RectObj *n = (RectObj*) pari_malloc(sizeof(RectObj2P));
     932             : 
     933           0 :             RoType(n) = ROt_LN;
     934           0 :             RoCol(n) = RoCol(R);
     935           0 :             RoLNx1(n) = RoMLxs(R)[f];        RoLNy1(n) = RoMLys(R)[f];
     936           0 :             RoLNx2(n) = RoMLxs(R)[f+1];        RoLNy2(n) = RoMLys(R)[f+1];
     937           0 :             RoNext(n) = next;
     938           0 :             RoNext(R) = n;
     939             :             /* Restore the unclipped value: */
     940           0 :             RoMLxs(R)[f+1] = oxn;        RoMLys(R)[f+1] = oyn;
     941           0 :             f++;
     942           0 :             prevp = &RoNext(n);
     943             :           }
     944           0 :           if (f + 1 < c) {                /* Are other lines */
     945           0 :             RectObj *n = (RectObj*) pari_malloc(sizeof(RectObjMP));
     946           0 :             RoType(n) = ROt_ML;
     947           0 :             RoCol(n) = RoCol(R);
     948           0 :             RoMLcnt(n) = c - f;
     949           0 :             RoMLxs(n) = (double*) pari_malloc(sizeof(double)*(c - f));
     950           0 :             RoMLys(n) = (double*) pari_malloc(sizeof(double)*(c - f));
     951           0 :             memcpy(RoMPxs(n),RoMPxs(R) + f, sizeof(double)*(c - f));
     952           0 :             memcpy(RoMPys(n),RoMPys(R) + f, sizeof(double)*(c - f));
     953           0 :             RoMPxs(n)[0] = oxn;
     954           0 :             RoMPys(n)[0] = oyn;
     955           0 :             RoNext(n) = next;
     956           0 :             RoNext(R) = n;
     957           0 :             next = n;
     958             :           }
     959           0 :           break;
     960             :         }
     961           0 :         if (t == 0) REMOVE();
     962           0 :         NEXT();
     963             :       }
     964             :     }
     965             : #undef REMOVE
     966             : #undef NEXT
     967             :   }
     968           0 : }
     969             : 
     970             : /********************************************************************/
     971             : /**                                                                **/
     972             : /**                        HI-RES PLOT                             **/
     973             : /**                                                                **/
     974             : /********************************************************************/
     975             : void
     976           0 : Printx(dblPointList *f)
     977             : {
     978             :   long i;
     979           0 :   printf("x: [%0.5g,%0.5g], y: [%0.5g,%0.5g]\n",
     980             :          f->xsml, f->xbig, f->ysml, f->ybig);
     981           0 :   for (i = 0; i < f->nb; i++) printf("%0.5g ", f->d[i]);
     982           0 :   printf("\n");
     983           0 : }
     984             : 
     985             : static void
     986     1268924 : Appendx(dblPointList *f, dblPointList *l,double x)
     987             : {
     988     1268924 :   (l->d)[l->nb++]=x;
     989     1268924 :   if (x < f->xsml) f->xsml = x;
     990     1268924 :   if (x > f->xbig) f->xbig = x;
     991     1268924 : }
     992             : 
     993             : static void
     994     3835924 : Appendy(dblPointList *f, dblPointList *l,double y)
     995             : {
     996     3835924 :   (l->d)[l->nb++]=y;
     997     3835924 :   if (y < f->ysml) f->ysml = y;
     998     3835924 :   if (y > f->ybig) f->ybig = y;
     999     3835924 : }
    1000             : 
    1001             : static void
    1002      651776 : get_xy(long cplx, GEN t, double *x, double *y)
    1003             : {
    1004      651776 :   if (cplx)
    1005             :   {
    1006           0 :     if (typ(t) == t_VEC)
    1007             :     {
    1008           0 :       if (lg(t) != 2) pari_err_DIM("get_xy");
    1009           0 :       t = gel(t,1);
    1010             :     }
    1011           0 :     *x = gtodouble( real_i(t) );
    1012           0 :     *y = gtodouble( imag_i(t) );
    1013             :   }
    1014             :   else
    1015             :   {
    1016      651776 :     if (typ(t) != t_VEC || lg(t) != 3) pari_err_DIM("get_xy");
    1017      651776 :     *x = gtodouble( gel(t,1) );
    1018      651776 :     *y = gtodouble( gel(t,2) );
    1019             :   }
    1020      651776 : }
    1021             : /* t a t_VEC (possibly a scalar if cplx), get next (x,y) coordinate starting
    1022             :  * at index *i [update i] */
    1023             : static void
    1024      942268 : get_xy_from_vec(long cplx, GEN t, long *i, double *x, double *y)
    1025             : {
    1026      942268 :   if (cplx)
    1027             :   {
    1028             :     GEN z;
    1029           0 :     if (typ(t) == t_VEC) z = gel(t,(*i)++); else { z = t; (*i)++; }
    1030           0 :     *x = gtodouble( real_i(z) );
    1031           0 :     *y = gtodouble( imag_i(z) );
    1032             :   }
    1033             :   else
    1034             :   {
    1035      942268 :     *x = gtodouble( gel(t, (*i)++) );
    1036      942268 :     *y = gtodouble( gel(t, (*i)++) );
    1037             :   }
    1038      942268 : }
    1039             : /* X,Y t_VEC, get next (x,y) coordinate starting at index i
    1040             :  * Y ignored if (cplx) */
    1041             : static void
    1042      770236 : get_xy_from_vec2(long cplx, GEN X, GEN Y, long i, double *x, double *y)
    1043             : {
    1044      770236 :   if (cplx)
    1045             :   {
    1046           0 :     GEN z = gel(X,i);
    1047           0 :     *x = gtodouble( real_i(z) );
    1048           0 :     *y = gtodouble( imag_i(z) );
    1049             :   }
    1050             :   else
    1051             :   {
    1052      770236 :     *x = gtodouble( gel(X, i) );
    1053      770236 :     *y = gtodouble( gel(Y, i) );
    1054             :   }
    1055      770236 : }
    1056             : 
    1057             : /* Convert data from GEN to double before we call rectplothrawin. */
    1058             : static dblPointList*
    1059        1543 : gtodblList(GEN data, long flags)
    1060             : {
    1061             :   dblPointList *l;
    1062             :   double xsml, xbig, ysml, ybig;
    1063        1543 :   long nl=lg(data)-1, lx1, i, j;
    1064        1543 :   const long param = (flags & (PLOT_PARAMETRIC|PLOT_COMPLEX));
    1065        1543 :   const long cplx = (flags & PLOT_COMPLEX);
    1066             : 
    1067        1543 :   if (! is_vec_t(typ(data))) pari_err_TYPE("gtodblList",data);
    1068        1543 :   if (!nl) return NULL;
    1069        1543 :   lx1 = lg(gel(data,1));
    1070        1543 :   if (!param && lx1 == 1) return NULL;
    1071             : 
    1072        1543 :   if (nl == 1 && !cplx) pari_err_DIM("gtodblList");
    1073             :   /* Allocate memory, then convert coord. to double */
    1074        1543 :   l = (dblPointList*)pari_malloc((cplx? 2*nl: nl)*sizeof(dblPointList));
    1075        3086 :   for (i=0; i<nl; i += (cplx? 1: 2))
    1076             :   {
    1077        1543 :     dblPointList *LX = l + i, *LY = l + (i+1);
    1078        1543 :     GEN x = gel(data,i+1), y;
    1079        1543 :     long lx = lg(x);
    1080        1543 :     if (!is_vec_t(typ(x))) pari_err_TYPE("gtodblList",x);
    1081        1543 :     if (cplx) y = NULL;
    1082             :     else
    1083             :     {
    1084        1543 :       y = gel(data,i+2);
    1085        1543 :       if (!is_vec_t(typ(y))) pari_err_TYPE("gtodblList",y);
    1086        1543 :       if (lg(y) != lx || (!param && lx != lx1)) pari_err_DIM("gtodblList");
    1087             :     }
    1088             : 
    1089        1543 :     lx--;
    1090        1543 :     LX->d = (double*)pari_malloc(lx*sizeof(double));
    1091        1543 :     LY->d = (double*)pari_malloc(lx*sizeof(double));
    1092      771779 :     for (j=1; j<=lx; j++)
    1093             :     {
    1094             :       double xx, yy;
    1095      770236 :       get_xy_from_vec2(cplx, x,y, j, &xx,&yy);
    1096      770236 :       LX->d[j-1] = xx;
    1097      770236 :       LY->d[j-1] = yy;
    1098             :     }
    1099        1543 :     LX->nb = LY->nb = lx;
    1100             :   }
    1101             : 
    1102             :   /* Now compute extremas */
    1103        1543 :   if (param)
    1104             :   {
    1105        1543 :     l[0].nb = cplx? nl: nl/2;
    1106        1543 :     for (i=0; i < l[0].nb; i+=2)
    1107        1543 :       if (l[i+1].nb) break;
    1108        1543 :     if (i >= l[0].nb) { pari_free(l); return NULL; }
    1109        1543 :     xsml = xbig = l[i  ].d[0];
    1110        1543 :     ysml = ybig = l[i+1].d[0];
    1111        3086 :     for (; i < l[0].nb; i+=2)
    1112             :     {
    1113        1543 :       dblPointList *LX = l + i, *LY = l + (i+1);
    1114      771779 :       for (j=0; j < LY->nb; j++)
    1115             :       {
    1116      770236 :         double x = LX->d[j], y = LY->d[j];
    1117      770236 :         if (x < xsml) xsml = x; else if (x > xbig) xbig = x;
    1118      770236 :         if (y < ysml) ysml = y; else if (y > ybig) ybig = y;
    1119             :       }
    1120             :     }
    1121             :   }
    1122             :   else
    1123             :   {
    1124           0 :     l[0].nb = nl-1;
    1125           0 :     xsml = xbig = l[0].d[0];
    1126           0 :     ysml = ybig = l[1].d[0];
    1127           0 :     for (j=0; j < l[1].nb; j++)
    1128             :     {
    1129           0 :       double x = l[0].d[j];
    1130           0 :       if (x < xsml) xsml = x; else if (x > xbig) xbig = x;
    1131             :     }
    1132           0 :     for (i=1; i <= l[0].nb; i++)
    1133           0 :       for (j=0; j < l[i].nb; j++)
    1134             :       {
    1135           0 :         double y = l[i].d[j];
    1136           0 :         if (y < ysml) ysml = y; else if (y > ybig) ybig = y;
    1137             :       }
    1138             :   }
    1139        1543 :   l[0].xsml = xsml; l[0].xbig = xbig;
    1140        1543 :   l[0].ysml = ysml; l[0].ybig = ybig; return l;
    1141             : }
    1142             : 
    1143             : /* (x+y)/2 */
    1144             : static GEN
    1145      600576 : rmiddle(GEN x, GEN y) { GEN z = addrr(x,y); shiftr_inplace(z,-1); return z; }
    1146             : 
    1147             : static void
    1148           0 : single_recursion(dblPointList *pl,GEN code,GEN xleft,double yleft,
    1149             :   GEN xright,double yright,long depth)
    1150             : {
    1151             :   GEN xx;
    1152           0 :   pari_sp av = avma;
    1153           0 :   double yy, dy=pl[0].ybig - pl[0].ysml;
    1154             : 
    1155           0 :   if (depth==RECUR_MAXDEPTH) return;
    1156             : 
    1157           0 :   xx = rmiddle(xleft,xright);
    1158           0 :   yy = gtodouble(READ_EXPR(code,xx));
    1159             : 
    1160           0 :   if (dy && fabs(yleft+yright-2*yy)< dy*RECUR_PREC) return;
    1161           0 :   single_recursion(pl,code, xleft,yleft, xx,yy, depth+1);
    1162             : 
    1163           0 :   Appendx(&pl[0],&pl[0],rtodbl(xx));
    1164           0 :   Appendy(&pl[0],&pl[1],yy);
    1165             : 
    1166           0 :   single_recursion(pl,code, xx,yy, xright,yright, depth+1);
    1167           0 :   avma = av;
    1168             : }
    1169             : 
    1170             : static void
    1171      601600 : param_recursion(long cplx, dblPointList *pl,GEN code,GEN tleft,double xleft,
    1172             :   double yleft, GEN tright,double xright,double yright, long depth)
    1173             : {
    1174             :   GEN tt, p1;
    1175      601600 :   pari_sp av=avma;
    1176      601600 :   double xx, dy=pl[0].ybig - pl[0].ysml;
    1177      601600 :   double yy, dx=pl[0].xbig - pl[0].xsml;
    1178             : 
    1179      927744 :   if (depth==RECUR_MAXDEPTH) return;
    1180             : 
    1181      600576 :   tt = rmiddle(tleft,tright);
    1182      600576 :   p1 = READ_EXPR(code,tt);
    1183      600576 :   get_xy(cplx, p1, &xx,&yy);
    1184             : 
    1185      600576 :   if (dx && dy && fabs(xleft+xright-2*xx) < dx*RECUR_PREC
    1186      450048 :                && fabs(yleft+yright-2*yy) < dy*RECUR_PREC) return;
    1187      275456 :   param_recursion(cplx, pl,code, tleft,xleft,yleft, tt,xx,yy, depth+1);
    1188             : 
    1189      275456 :   Appendx(&pl[0],&pl[0],xx);
    1190      275456 :   Appendy(&pl[0],&pl[1],yy);
    1191             : 
    1192      275456 :   param_recursion(cplx, pl,code, tt,xx,yy, tright,xright,yright, depth+1);
    1193      275456 :   avma = av;
    1194             : }
    1195             : 
    1196             : /* Graph 'code' for parameter values in [a,b], using 'testpoints' sample
    1197             :  * points (0 = use a default value); code is either a t_CLOSURE (from GP:
    1198             :  * ploth, etc.) or a t_POL/t_VEC of two t_POLs from rectsplines. Returns a
    1199             :  * dblPointList of (absolute) coordinates. */
    1200             : static dblPointList *
    1201        5646 : rectplothin(GEN a, GEN b, GEN code, long prec, ulong flags, long testpoints)
    1202             : {
    1203        5646 :   const double INF = 1./0.;
    1204        5646 :   const long param = flags & (PLOT_PARAMETRIC|PLOT_COMPLEX);
    1205        5646 :   const long recur = flags & PLOT_RECURSIVE;
    1206        5646 :   const long cplx = flags & PLOT_COMPLEX;
    1207             :   GEN t,dx,x;
    1208             :   dblPointList *pl;
    1209        5646 :   long tx, i, j, sig, nc, nl, ncoords, nbpoints, non_vec = 0;
    1210        5646 :   pari_sp av = avma;
    1211             : 
    1212        5646 :   sig = gcmp(b,a); if (!sig) return NULL;
    1213        5646 :   if (sig < 0) swap(a, b);
    1214        5646 :   if (testpoints)
    1215             :   {
    1216        2055 :     if (testpoints < 2)
    1217         512 :       pari_err_DOMAIN("ploth", "#points", "<", gen_2, stoi(testpoints));
    1218             :   }
    1219             :   else
    1220             :   {
    1221        3591 :     if (recur) testpoints = 8;
    1222        3591 :     else       testpoints = param? 1500: 1000;
    1223             :   }
    1224             :   /* compute F(a) to determine nc = #curves; nl = #coord. lists */
    1225        5134 :   x = gtofp(a, prec);
    1226        5134 :   if (typ(code) == t_CLOSURE) push_lex(x, code);
    1227        5134 :   t = READ_EXPR(code,x); tx = typ(t);
    1228        5134 :   if (param)
    1229             :   {
    1230        2567 :     if (cplx) nc = nl = (tx == t_VEC)? lg(t)-1: 1;
    1231             :     else
    1232             :     {
    1233        2567 :       if (tx != t_VEC)
    1234         512 :         pari_err_TYPE("ploth [not a t_VEC with PLOT_PARAMETRIC]", t);
    1235        2055 :       nl = lg(t)-1;
    1236        2055 :       nc = nl/2;
    1237        2055 :       if (odd(nl))
    1238           0 :         pari_err_TYPE("ploth [parametric ploc with odd # of components]",t);
    1239             :     }
    1240             :   }
    1241             :   else
    1242             :   {
    1243        2567 :     if (!is_matvec_t(tx)) { nl = 2; non_vec = 1; }
    1244             :     else
    1245             :     {
    1246        1024 :       if (tx != t_VEC) pari_err_TYPE("ploth [not a t_VEC]",t);
    1247        1024 :       nl = lg(t);
    1248             :     }
    1249        2567 :     nc = nl-1;
    1250             :   }
    1251        4622 :   if (!nc) { avma = av; return NULL; }
    1252        4622 :   if (recur && nc > 1)
    1253         512 :     pari_err_TYPE("ploth [multi-curves cannot be plot recursively]",t);
    1254             : 
    1255        4110 :   ncoords = cplx? 2*nl: nl;
    1256        4110 :   nbpoints = recur? testpoints << RECUR_MAXDEPTH: testpoints;
    1257        4110 :   pl=(dblPointList*) pari_malloc(ncoords*sizeof(dblPointList));
    1258             :   /* set [xy]sml,[xy]big to default values */
    1259        4110 :   if (param)
    1260             :   {
    1261        2055 :     pl[0].xsml = INF;
    1262        2055 :     pl[0].xbig =-INF;
    1263             :   } else {
    1264        2055 :     pl[0].xsml = gtodouble(a);
    1265        2055 :     pl[0].xbig = gtodouble(b);
    1266             :   }
    1267        4110 :   pl[0].ysml = INF;
    1268        4110 :   pl[0].ybig =-INF;
    1269       12842 :   for (i = 0; i < ncoords; i++)
    1270             :   {
    1271        8732 :     pl[i].d = (double*)pari_malloc((nbpoints+1)*sizeof(double));
    1272        8732 :     pl[i].nb=0;
    1273             :   }
    1274        4110 :   dx = divru(gtofp(gsub(b,a),prec), testpoints-1);
    1275        4110 :   if (recur) /* recursive plot */
    1276             :   {
    1277         512 :     double yleft, yright = 0;
    1278         512 :     if (param)
    1279             :     {
    1280         512 :       GEN tleft = cgetr(prec), tright = cgetr(prec);
    1281         512 :       double xleft, xright = 0;
    1282         512 :       pari_sp av2 = avma;
    1283         512 :       affgr(a,tleft);
    1284         512 :       t = READ_EXPR(code,tleft);
    1285         512 :       get_xy(cplx,t, &xleft,&yleft);
    1286       51200 :       for (i=0; i<testpoints-1; i++, avma = av2)
    1287             :       {
    1288       50688 :         if (i) { affrr(tright,tleft); xleft = xright; yleft = yright; }
    1289       50688 :         addrrz(tleft,dx,tright);
    1290       50688 :         t = READ_EXPR(code,tright);
    1291       50688 :         get_xy(cplx,t, &xright,&yright);
    1292       50688 :         Appendx(&pl[0],&pl[0],xleft);
    1293       50688 :         Appendy(&pl[0],&pl[1],yleft);
    1294       50688 :         param_recursion(cplx, pl,code, tleft,xleft,yleft, tright,xright,yright, 0);
    1295             :       }
    1296         512 :       Appendx(&pl[0],&pl[0],xright);
    1297         512 :       Appendy(&pl[0],&pl[1],yright);
    1298             :     }
    1299             :     else /* single curve */
    1300             :     {
    1301           0 :       GEN xleft = cgetr(prec), xright = cgetr(prec);
    1302           0 :       pari_sp av2 = avma;
    1303           0 :       affgr(a,xleft);
    1304           0 :       yleft = gtodouble(READ_EXPR(code,xleft));
    1305           0 :       for (i=0; i<testpoints-1; i++, avma = av2)
    1306             :       {
    1307           0 :         addrrz(xleft,dx,xright);
    1308           0 :         yright = gtodouble(READ_EXPR(code,xright));
    1309             : 
    1310           0 :         Appendx(&pl[0],&pl[0],rtodbl(xleft));
    1311           0 :         Appendy(&pl[0],&pl[1],yleft);
    1312             : 
    1313           0 :         single_recursion(pl,code,xleft,yleft,xright,yright,0);
    1314           0 :         affrr(xright,xleft); yleft = yright;
    1315             :       }
    1316           0 :       Appendx(&pl[0],&pl[0],rtodbl(xright));
    1317           0 :       Appendy(&pl[0],&pl[1],yright);
    1318             :     }
    1319             :   }
    1320             :   else /* non-recursive plot */
    1321             :   {
    1322        3598 :     pari_sp av2 = avma;
    1323        3598 :     if (param)
    1324             :     {
    1325      943811 :       for (i=0; i<testpoints; i++, affrr(addrr(x,dx), x), avma = av2)
    1326             :       {
    1327             :         long k, nt;
    1328      942780 :         t = READ_EXPR(code,x);
    1329      942780 :         if (typ(t) != t_VEC)
    1330             :         {
    1331         512 :           if (cplx) nt = 1;
    1332         512 :           else nt = 0; /* trigger error */
    1333             :         }
    1334             :         else
    1335      942268 :           nt = lg(t)-1;
    1336      942780 :         if (nt != nl) pari_err_DIM("rectploth");
    1337      942268 :         k = 0; j = 1;
    1338     2826804 :         while (j <= nl)
    1339             :         {
    1340             :           double xx, yy;
    1341      942268 :           get_xy_from_vec(cplx, t, &j, &xx, &yy);
    1342      942268 :           Appendx(&pl[0], &pl[k++], xx);
    1343      942268 :           Appendy(&pl[0], &pl[k++], yy);
    1344             :         }
    1345             :       }
    1346             :     }
    1347        2055 :     else if (non_vec)
    1348     1544543 :       for (i=0; i<testpoints; i++, affrr(addrr(x,dx), x), avma = av2)
    1349             :       {
    1350     1543000 :         t = READ_EXPR(code,x);
    1351     1543000 :         pl[0].d[i] = gtodouble(x);
    1352     1543000 :         Appendy(&pl[0],&pl[1], gtodouble(t));
    1353             :       }
    1354             :     else /* vector of non-parametric curves */
    1355      512512 :       for (i=0; i<testpoints; i++, affrr(addrr(x,dx), x), avma = av2)
    1356             :       {
    1357      512000 :         t = READ_EXPR(code,x);
    1358      512000 :         if (typ(t) != t_VEC || lg(t) != nl) pari_err_DIM("rectploth");
    1359      512000 :         pl[0].d[i] = gtodouble(x);
    1360      512000 :         for (j=1; j<nl; j++) Appendy(&pl[0],&pl[j], gtodouble(gel(t,j)));
    1361             :       }
    1362             :   }
    1363        3598 :   if (typ(code) == t_CLOSURE) pop_lex(1);
    1364        3598 :   pl[0].nb = nc; avma = av; return pl;
    1365             : }
    1366             : 
    1367             : /* Uses highlevel plotting functions to implement splines as
    1368             :    a low-level plotting function. */
    1369             : static void
    1370           0 : rectsplines(long ne, double *x, double *y, long lx, long flag)
    1371             : {
    1372             :   long i, j;
    1373           0 :   pari_sp av0 = avma;
    1374           0 :   GEN X = pol_x(0), xa = cgetg(lx+1, t_VEC), ya = cgetg(lx+1, t_VEC);
    1375             :   GEN tas, pol3;
    1376           0 :   long param = flag & PLOT_PARAMETRIC;
    1377             : 
    1378           0 :   if (lx < 4) pari_err(e_MISC, "Too few points (%ld) for spline plot", lx);
    1379           0 :   for (i = 1; i <= lx; i++) {
    1380           0 :     gel(xa,i) = dbltor(x[i-1]);
    1381           0 :     gel(ya,i) = dbltor(y[i-1]);
    1382             :   }
    1383           0 :   if (param) {
    1384           0 :     tas = new_chunk(4);
    1385           0 :     for (j = 1; j <= 4; j++) gel(tas,j-1) = utoipos(j);
    1386           0 :     pol3 = cgetg(3, t_VEC);
    1387             :   }
    1388             :   else
    1389           0 :     tas = pol3 = NULL; /* gcc -Wall */
    1390           0 :   for (i = 0; i <= lx - 4; i++) {
    1391           0 :     pari_sp av = avma;
    1392             : 
    1393           0 :     xa++; ya++;
    1394           0 :     if (param) {
    1395           0 :       gel(pol3,1) = polint_i(tas, xa, X, 4, NULL);
    1396           0 :       gel(pol3,2) = polint_i(tas, ya, X, 4, NULL);
    1397             :     } else {
    1398           0 :       pol3 = polint_i(xa, ya, X, 4, NULL);
    1399           0 :       tas = xa;
    1400             :     }
    1401             :     /* Start with 3 points */
    1402           0 :     rectploth(ne, i==   0 ? gel(tas,0) : gel(tas,1),
    1403           0 :                   i==lx-4 ? gel(tas,3) : gel(tas,2), pol3,
    1404             :                   DEFAULTPREC, PLOT_RECURSIVE | PLOT_NO_RESCALE
    1405           0 :                   | PLOT_NO_FRAME | PLOT_NO_AXE_Y | PLOT_NO_AXE_X | param, 2);
    1406           0 :     avma = av;
    1407             :   }
    1408           0 :   avma = av0;
    1409           0 : }
    1410             : 
    1411             : static void
    1412       10282 : set_range(double m, double M, double *sml, double *big)
    1413             : {
    1414       10282 :   if (M - m < 1.e-9)
    1415             :   {
    1416           0 :     double d = fabs(m)/10; if (!d) d = 0.1;
    1417           0 :     M += d; m -= d;
    1418             :   }
    1419       10282 :   *sml = m; *big = M;
    1420       10282 : }
    1421             : /* Plot a dblPointList. Complete with axes, bounding box, etc.
    1422             :  *
    1423             :  * data is an array of structs. Its meaning depends on flags :
    1424             :  *
    1425             :  * + data[0] contains global extremas, the number of curves to plot
    1426             :  *   (data[0].nb) and a list of doubles (first set of x-coordinates).
    1427             :  *
    1428             :  * + data[i].nb (i>0) contains the number of points in the list
    1429             :  *   data[i].d (hopefully, data[2i].nb=data[2i+1].nb when i>0...)
    1430             :  *
    1431             :  * + If flags contain PLOT_PARAMETRIC, the array length should be
    1432             :  *   even, and successive pairs (data[2i].d, data[2i+1].d) represent
    1433             :  *   curves to plot.
    1434             :  *
    1435             :  * + If there is no such flag, the first element is an array with
    1436             :  *   x-coordinates and the following ones contain y-coordinates.
    1437             :  * If grect >= 0, output to this rectwindow. Otherwise draw immediately to
    1438             :  * screen (grect=-1) or to screen (grect=-2), using two drawing rectangles:
    1439             :  * one for labels, another for graphs.*/
    1440             : static GEN
    1441        5141 : rectplothrawin(long grect, dblPointList *data, long flags)
    1442             : {
    1443        5141 :   const long param = flags & (PLOT_PARAMETRIC|PLOT_COMPLEX);
    1444        5141 :   const pari_sp av = avma;
    1445             :   PARI_plot *W;
    1446             :   dblPointList y,x;
    1447             :   double xsml, xbig, ysml, ybig;
    1448             :   long ltype, max_graphcolors;
    1449             :   long i,nc,nbpoints, w[2], wx[2], wy[2];
    1450             : 
    1451        5141 :   if (!data) return cgetg(1,t_VEC);
    1452        5141 :   x = data[0]; nc = x.nb;
    1453        5141 :   set_range(x.xsml, x.xbig, &xsml, &xbig);
    1454        5141 :   set_range(x.ysml, x.ybig, &ysml, &ybig);
    1455        5141 :   if (grect >= 0) /* output to rectwindow, no labels */
    1456           0 :     W = NULL;
    1457             :   else
    1458             :   {
    1459        5141 :     const long srect = NUMRECT-2;
    1460             :     long lm, rm, tm, bm;
    1461             : 
    1462        5141 :     if (grect == -1) /* output to screen */
    1463        4096 :     { W = &pari_plot; PARI_get_plot(); }
    1464             :     else /* output to file */
    1465        1045 :     { W = &pari_psplot; PARI_get_psplot(); }
    1466        1045 :     grect = NUMRECT-1;
    1467             :     /* left/right/top/bottom margin */
    1468        1045 :     lm = W->fwidth*10;
    1469        1045 :     rm = W->hunit-1;
    1470        1045 :     tm = W->vunit-1;
    1471        1045 :     bm = W->vunit+W->fheight-1;
    1472        1045 :     w[0] = srect; wx[0] = 0;  wy[0] = 0;
    1473        1045 :     w[1] = grect;   wx[1] = lm; wy[1] = tm;
    1474             :    /* Window (width x height) is given in pixels, correct pixels are 0..n-1,
    1475             :     * whereas rect functions work with windows whose pixel range is [0,n] */
    1476        1045 :     initrect(srect, W->width - 1, W->height - 1);
    1477        1045 :     rectlinetype(srect,-2); /* Frame */
    1478        1045 :     current_color[srect] = DEFAULT_COLOR;
    1479        1045 :     initrect(grect, W->width - (lm+rm) - 1, W->height - (tm+bm) - 1);
    1480             :     /* draw labels on srect */
    1481        1045 :     put_label(srect, lm, 0, ybig, RoSTdirRIGHT|RoSTdirHGAP|RoSTdirTOP);
    1482        1045 :     put_label(srect, lm, W->height-bm, ysml, RoSTdirRIGHT|RoSTdirHGAP|RoSTdirVGAP);
    1483        1045 :     put_label(srect, lm, W->height - bm, xsml, RoSTdirLEFT|RoSTdirTOP);
    1484        1045 :     put_label(srect, W->width-rm-1, W->height-bm, xbig, RoSTdirRIGHT|RoSTdirTOP);
    1485             :   }
    1486        1045 :   RHasGraph(check_rect(grect)) = 1;
    1487             : 
    1488        1045 :   if (!(flags & PLOT_NO_RESCALE))
    1489        1045 :     rectscale0(grect, xsml, xbig, ysml, ybig);
    1490             : 
    1491        1045 :   if (!(flags & PLOT_NO_FRAME))
    1492             :   {
    1493        1045 :     int do_double = (flags & PLOT_NODOUBLETICK) ? TICKS_NODOUBLE : 0;
    1494        1045 :     PARI_plot *pl = W;
    1495        1045 :     if (!pl) { PARI_get_plot(); pl = &pari_plot; }
    1496             : 
    1497        1045 :     rectlinetype(grect, -2); /* Frame. */
    1498        1045 :     current_color[grect] = DEFAULT_COLOR;
    1499        1045 :     rectmove0(grect,xsml,ysml,0);
    1500        1045 :     rectbox0(grect,xbig,ybig,0);
    1501        1045 :     if (!(flags & PLOT_NO_TICK_X)) {
    1502        1045 :       rectticks(pl, grect, xsml, ysml, xbig, ysml, xsml, xbig,
    1503        1045 :         TICKS_CLOCKW | do_double);
    1504        1045 :       rectticks(pl, grect, xbig, ybig, xsml, ybig, xbig, xsml,
    1505        1045 :         TICKS_CLOCKW | do_double);
    1506             :     }
    1507        1045 :     if (!(flags & PLOT_NO_TICK_Y)) {
    1508        1045 :       rectticks(pl, grect, xbig, ysml, xbig, ybig, ysml, ybig,
    1509        1045 :         TICKS_CLOCKW | do_double);
    1510        1045 :       rectticks(pl, grect, xsml, ybig, xsml, ysml, ybig, ysml,
    1511        1045 :         TICKS_CLOCKW | do_double);
    1512             :     }
    1513             :   }
    1514             : 
    1515        1045 :   if (!(flags & PLOT_NO_AXE_Y) && (xsml<=0 && xbig >=0))
    1516             :   {
    1517        1038 :     rectlinetype(grect, -1); /* Axes. */
    1518        1038 :     current_color[grect] = AXIS_COLOR;
    1519        1038 :     rectmove0(grect,0.0,ysml,0);
    1520        1038 :     rectline0(grect,0.0,ybig,0);
    1521             :   }
    1522             : 
    1523        1045 :   if (!(flags & PLOT_NO_AXE_X) && (ysml<=0 && ybig >=0))
    1524             :   {
    1525        1038 :     rectlinetype(grect, -1); /* Axes. */
    1526        1038 :     current_color[grect] = AXIS_COLOR;
    1527        1038 :     rectmove0(grect,xsml,0.0,0);
    1528        1038 :     rectline0(grect,xbig,0.0,0);
    1529             :   }
    1530             : 
    1531        1045 :   if (param) {
    1532         526 :     i = 0;
    1533         526 :     flags |= PLOT_PARAMETRIC;
    1534         526 :     flags &= (~PLOT_COMPLEX); /* turn COMPLEX to PARAMETRIC*/
    1535         519 :   } else i = 1;
    1536        1045 :   max_graphcolors = lg(GP_DATA->graphcolors)-1;
    1537        2090 :   for (ltype = 0; ltype < nc; ltype++)
    1538             :   {
    1539        1045 :     current_color[grect] = GP_DATA->graphcolors[1+(ltype%max_graphcolors)];
    1540        1045 :     if (param) x = data[i++];
    1541             : 
    1542        1045 :     y = data[i++]; nbpoints = y.nb;
    1543        1045 :     if (flags & (PLOT_POINTS_LINES|PLOT_POINTS)) {
    1544           7 :       rectlinetype(grect, rectpoint_itype + ltype); /* Graphs */
    1545           7 :       rectpointtype(grect,rectpoint_itype + ltype); /* Graphs */
    1546           7 :       rectpoints0(grect,x.d,y.d,nbpoints);
    1547           7 :       if (!(flags & PLOT_POINTS_LINES)) continue;
    1548             :     }
    1549             : 
    1550        1038 :     if (flags & PLOT_SPLINES) {
    1551             :       /* rectsplines will call us back with ltype == 0 */
    1552           0 :       int old = rectline_itype;
    1553             : 
    1554           0 :       rectline_itype = rectline_itype + ltype;
    1555           0 :       rectsplines(grect,x.d,y.d,nbpoints,flags);
    1556           0 :       rectline_itype = old;
    1557             :     } else {
    1558        1038 :       rectlinetype(grect, rectline_itype + ltype); /* Graphs */
    1559        1038 :       rectlines0(grect,x.d,y.d,nbpoints,0);
    1560             :     }
    1561             :   }
    1562        1045 :   for (i--; i>=0; i--) pari_free(data[i].d);
    1563        1045 :   pari_free(data);
    1564             : 
    1565        1045 :   if (W)
    1566             :   {
    1567        1045 :     if (W == &pari_plot)
    1568           0 :       rectdraw0(w,wx,wy,2);
    1569             :     else
    1570        1045 :       postdraw0(w,wx,wy,2, 0);
    1571        1045 :     killrect(w[1]);
    1572        1045 :     killrect(w[0]);
    1573             :   }
    1574        1045 :   avma = av;
    1575        1045 :   retmkvec4(dbltor(xsml), dbltor(xbig), dbltor(ysml), dbltor(ybig));
    1576             : }
    1577             : 
    1578             : /*************************************************************************/
    1579             : /*                                                                       */
    1580             : /*                          HI-RES FUNCTIONS                             */
    1581             : /*                                                                       */
    1582             : /*************************************************************************/
    1583             : 
    1584             : GEN
    1585        5646 : rectploth(long ne, GEN a,GEN b,GEN code, long prec,ulong flags,long tpts)
    1586             : {
    1587        5646 :   dblPointList *pl = rectplothin(a,b, code, prec, flags, tpts);
    1588        3598 :   return rectplothrawin(ne, pl, flags);
    1589             : }
    1590             : 
    1591             : GEN
    1592        1543 : rectplothraw(long ne, GEN data, long flags)
    1593             : {
    1594        1543 :   dblPointList *pl = gtodblList(data,flags);
    1595        1543 :   return rectplothrawin(ne, pl, flags);
    1596             : }
    1597             : 
    1598             : static long
    1599        1543 : plothraw_flags(long fl)
    1600             : {
    1601        1543 :   switch(fl)
    1602             :   {
    1603         519 :     case 0: return PLOT_PARAMETRIC|PLOT_POINTS;
    1604        1024 :     case 1: return PLOT_PARAMETRIC;
    1605           0 :     default:return PLOT_PARAMETRIC|fl;
    1606             :   }
    1607             : }
    1608             : static GEN
    1609        1543 : plothraw0(long ne, GEN listx, GEN listy, long flags)
    1610             : {
    1611        1543 :   pari_sp av = avma;
    1612        1543 :   GEN z = rectplothraw(ne, mkvec2(listx,listy), plothraw_flags(flags));
    1613         519 :   return gerepileupto(av, z);
    1614             : }
    1615             : 
    1616             : GEN
    1617        1024 : plothraw(GEN listx, GEN listy, long flags)
    1618        1024 : { return plothraw0(-1, listx, listy, flags); }
    1619             : 
    1620             : GEN
    1621        5120 : ploth(GEN a, GEN b, GEN code, long prec,long flags,long numpoints)
    1622        5120 : { return rectploth(-1, a,b,code,prec,flags,numpoints); }
    1623             : GEN
    1624           0 : ploth2(GEN a, GEN b, GEN code, long prec)
    1625           0 : { return rectploth(-1, a,b,code,prec,PLOT_PARAMETRIC,0); }
    1626             : GEN
    1627           0 : plothmult(GEN a, GEN b, GEN code, long prec)
    1628           0 : { return rectploth(-1, a,b,code,prec,0,0); }
    1629             : 
    1630             : GEN
    1631         519 : postplothraw(GEN listx, GEN listy, long flags)
    1632         519 : { return plothraw0(-2, listx, listy, flags); }
    1633             : GEN
    1634         526 : postploth(GEN a, GEN b, GEN code, long prec,long flags, long numpoints)
    1635         526 : { return rectploth(-2, a,b,code,prec, flags,numpoints); }
    1636             : GEN
    1637           0 : postploth2(GEN a, GEN b, GEN code, long prec, long numpoints)
    1638           0 : { return rectploth(-2, a,b,code,prec, PLOT_PARAMETRIC,numpoints); }
    1639             : 
    1640             : GEN
    1641           0 : plothsizes(void) { return plothsizes_flag(0); }
    1642             : GEN
    1643         512 : plothsizes_flag(long flag)
    1644             : {
    1645         512 :   GEN vect = cgetg(1+6,t_VEC);
    1646             : 
    1647         512 :   PARI_get_plot();
    1648           0 :   gel(vect,1) = stoi(pari_plot.width);
    1649           0 :   gel(vect,2) = stoi(pari_plot.height);
    1650           0 :   if (flag) {
    1651           0 :     gel(vect,3) = dbltor(pari_plot.hunit*1.0/pari_plot.width);
    1652           0 :     gel(vect,4) = dbltor(pari_plot.vunit*1.0/pari_plot.height);
    1653           0 :     gel(vect,5) = dbltor(pari_plot.fwidth*1.0/pari_plot.width);
    1654           0 :     gel(vect,6) = dbltor(pari_plot.fheight*1.0/pari_plot.height);
    1655             :   } else {
    1656           0 :     gel(vect,3) = stoi(pari_plot.hunit);
    1657           0 :     gel(vect,4) = stoi(pari_plot.vunit);
    1658           0 :     gel(vect,5) = stoi(pari_plot.fwidth);
    1659           0 :     gel(vect,6) = stoi(pari_plot.fheight);
    1660             :   }
    1661           0 :   return vect;
    1662             : }
    1663             : 
    1664             : void
    1665           0 : plot_count(long *w, long lw, col_counter rcolcnt)
    1666             : {
    1667             :   RectObj *O;
    1668             :   long col, i;
    1669             : 
    1670           0 :   for (col = 1; col < lg(GP_DATA->colormap)-1; col++)
    1671           0 :     for (i = 0; i < ROt_MAX; i++) rcolcnt[col][i] = 0;
    1672           0 :   for (i = 0; i < lw; i++)
    1673             :   {
    1674           0 :     PariRect *e = rectgraph[w[i]];
    1675           0 :     for (O = RHead(e); O; O=RoNext(O))
    1676           0 :       switch(RoType(O))
    1677             :       {
    1678           0 :         case ROt_MP : rcolcnt[RoCol(O)][ROt_PT] += RoMPcnt(O);
    1679           0 :                       break;                 /* Multiple Point */
    1680             :         case ROt_PT :                        /* Point */
    1681             :         case ROt_LN :                        /* Line */
    1682             :         case ROt_BX :                        /* Box */
    1683             :         case ROt_ML :                        /* Multiple lines */
    1684           0 :         case ROt_ST : rcolcnt[RoCol(O)][RoType(O)]++;
    1685           0 :                       break;                 /* String */
    1686             :       }
    1687             :   }
    1688           0 : }
    1689             : /*************************************************************************/
    1690             : /*                                                                       */
    1691             : /*                         POSTSCRIPT OUTPUT                             */
    1692             : /*                                                                       */
    1693             : /*************************************************************************/
    1694             : 
    1695             : static void
    1696        3135 : PARI_get_psplot(void)
    1697             : {
    1698        6270 :   if (pari_psplot.init) return;
    1699         519 :   pari_psplot.init = 1;
    1700             : 
    1701         519 :   pari_psplot.width = 1120 - 60; /* 1400 - 60 for hi-res */
    1702         519 :   pari_psplot.height=  800 - 40; /* 1120 - 60 for hi-res */
    1703         519 :   pari_psplot.fheight= 15;
    1704         519 :   pari_psplot.fwidth = 6;
    1705         519 :   pari_psplot.hunit = 5;
    1706         519 :   pari_psplot.vunit = 5;
    1707             : }
    1708             : 
    1709             : static void
    1710        4629 : gendraw(GEN list, long ps, long flag)
    1711             : {
    1712             :   long i,n,ne,*w,*x,*y;
    1713             : 
    1714        4629 :   if (typ(list) != t_VEC) pari_err_TYPE("rectdraw",list);
    1715        7466 :   n = lg(list)-1; if (!n) return;
    1716        4629 :   if (n%3) pari_err_DIM("rectdraw");
    1717        4629 :   n = n/3;
    1718        4629 :   w = (long*)pari_malloc(n*sizeof(long));
    1719        4629 :   x = (long*)pari_malloc(n*sizeof(long));
    1720        4629 :   y = (long*)pari_malloc(n*sizeof(long));
    1721        4629 :   if (flag) PARI_get_plot();
    1722        9258 :   for (i=0; i<n; i++)
    1723             :   {
    1724        4629 :     GEN win = gel(list,3*i+1), x0 = gel(list,3*i+2), y0 = gel(list,3*i+3);
    1725             :     long xi, yi;
    1726        4629 :     if (typ(win)!=t_INT) pari_err_TYPE("rectdraw",win);
    1727        4629 :     if (flag) {
    1728           0 :       xi = DTOL(gtodouble(x0)*(pari_plot.width - 1));
    1729           0 :       yi = DTOL(gtodouble(y0)*(pari_plot.height - 1));
    1730             :     } else {
    1731        4629 :       xi = gtos(x0);
    1732        4629 :       yi = gtos(y0);
    1733             :     }
    1734        4629 :     x[i] = xi;
    1735        4629 :     y[i] = yi;
    1736        4629 :     ne = itos(win); check_rect(ne);
    1737        4629 :     w[i] = ne;
    1738             :   }
    1739        4629 :   if (ps) postdraw0(w,x,y,n,flag); else rectdraw0(w,x,y,n);
    1740        2837 :   pari_free(x); pari_free(y); pari_free(w);
    1741             : }
    1742             : 
    1743             : void
    1744           0 : postdraw(GEN list) { gendraw(list, 1, 0); }
    1745             : 
    1746             : void
    1747           0 : rectdraw(GEN list) { gendraw(list, 0, 0); }
    1748             : 
    1749             : void
    1750        1045 : postdraw_flag(GEN list, long flag) { gendraw(list, 1, flag); }
    1751             : 
    1752             : void
    1753        3584 : rectdraw_flag(GEN list, long flag) { gendraw(list, 0, flag); }
    1754             : 
    1755             : static void
    1756      155558 : ps_sc(void *data, long col)
    1757             : {
    1758      155558 :   long l = lg(GP_DATA->colormap)-1;
    1759             :   int r, g, b;
    1760      155558 :   if (col >= l)
    1761             :   {
    1762           0 :     pari_warn(warner,"non-existent color: %ld", col);
    1763           0 :     col = l-1;
    1764             :   }
    1765      155558 :   color_to_rgb(gel(GP_DATA->colormap,col+1), &r, &g, &b);
    1766      155558 :   fprintf((FILE*)data,"%f %f %f setrgbcolor\n", r/255., g/255., b/255.);
    1767      155558 : }
    1768             : 
    1769             : static void
    1770         860 : ps_point(void *data, long x, long y)
    1771             : {
    1772         860 :   fprintf((FILE*)data,"%ld %ld p\n",y,x);
    1773         860 : }
    1774             : 
    1775             : static void
    1776      149197 : ps_line(void *data, long x1, long y1, long x2, long y2)
    1777             : {
    1778      149197 :   fprintf((FILE*)data,"%ld %ld m %ld %ld l\n",y1,x1,y2,x2);
    1779      149197 :   fprintf((FILE*)data,"stroke\n");
    1780      149197 : }
    1781             : 
    1782             : static void
    1783        1073 : ps_rect(void *data, long x, long y, long w, long h)
    1784             : {
    1785        1073 :   fprintf((FILE*)data,"%ld %ld m %ld %ld l %ld %ld l %ld %ld l closepath\n",y,x, y,x+w, y+h,x+w, y+h,x);
    1786        1073 : }
    1787             : 
    1788             : static void
    1789          21 : ps_points(void *data, long nb, struct plot_points *p)
    1790             : {
    1791             :   long i;
    1792          21 :   for (i=0; i<nb; i++) ps_point(data, p[i].x, p[i].y);
    1793          21 : }
    1794             : 
    1795             : static void
    1796        1052 : ps_lines(void *data, long nb, struct plot_points *p)
    1797             : {
    1798        1052 :   FILE *psfile = (FILE*)data;
    1799             :   long i;
    1800        1052 :   fprintf(psfile,"%ld %ld m\n",p[0].y,p[0].x);
    1801        1052 :   for (i=1; i<nb; i++) fprintf(psfile, "%ld %ld l\n", p[i].y, p[i].x);
    1802        1052 :   fprintf(psfile,"stroke\n");
    1803        1052 : }
    1804             : 
    1805             : static void
    1806        4194 : ps_string(void *data, long x, long y, char *s, long length)
    1807             : {
    1808        4194 :   FILE *psfile = (FILE*)data;
    1809             :   (void)length;
    1810        4194 :   if (strpbrk(s, "(\\)")) {
    1811           7 :     fprintf(psfile,"(");
    1812          49 :     while (*s) {
    1813          35 :       if ( *s=='(' || *s==')' || *s=='\\' ) fputc('\\', psfile);
    1814          35 :       fputc(*s, psfile);
    1815          35 :       s++;
    1816             :     }
    1817             :   } else
    1818        4187 :     fprintf(psfile,"(%s", s);
    1819        4194 :   fprintf(psfile,") %ld %ld m 90 rotate show -90 rotate\n", y, x);
    1820        4194 : }
    1821             : 
    1822             : void
    1823        2090 : psplot_init(struct plot_eng *S, FILE *f, double xscale, double yscale, long fontsize)
    1824             : {
    1825        2090 :   PARI_get_psplot();
    1826             :   /* Definitions taken from post terminal of Gnuplot. */
    1827        2090 :   fprintf(f, "%%!\n\
    1828             : 50 50 translate\n\
    1829             : /p {moveto 0 2 rlineto 2 0 rlineto 0 -2 rlineto closepath fill} def\n\
    1830             : /l {lineto} def\n\
    1831             : /m {moveto} def\n"
    1832             : "/Times-Roman findfont %ld scalefont setfont\n"
    1833             : "%g %g scale\n", fontsize, yscale, xscale);
    1834             : 
    1835        2090 :   S->sc = &ps_sc;
    1836        2090 :   S->pt = &ps_point;
    1837        2090 :   S->ln = &ps_line;
    1838        2090 :   S->bx = &ps_rect;
    1839        2090 :   S->mp = &ps_points;
    1840        2090 :   S->ml = &ps_lines;
    1841        2090 :   S->st = &ps_string;
    1842        2090 :   S->pl = &pari_psplot;
    1843        2090 :   S->data = (void*)f;
    1844        2090 : }
    1845             : 
    1846             : void
    1847        2090 : postdraw0(long *w, long *x, long *y, long lw, long scale)
    1848             : {
    1849             :   struct plot_eng plot;
    1850             :   FILE *psfile;
    1851        2090 :   double xscale = 0.65, yscale = 0.65;
    1852        2090 :   long fontsize = 16;
    1853             : 
    1854        2090 :   psfile = fopen(current_psfile, "a");
    1855        2090 :   if (!psfile) pari_err_FILE("postscript file",current_psfile);
    1856        2090 :   if (scale) {
    1857             :     double psxscale, psyscale;
    1858           0 :     PARI_get_psplot();
    1859           0 :     PARI_get_plot();
    1860           0 :     psxscale = pari_psplot.width * 1.0/pari_plot.width ;
    1861           0 :     psyscale = pari_psplot.height* 1.0/pari_plot.height;
    1862           0 :     fontsize = (long) (fontsize/psxscale);
    1863           0 :     xscale *= psxscale;
    1864           0 :     yscale *= psyscale;
    1865             :   }
    1866        2090 :   psplot_init(&plot, psfile, xscale, yscale, fontsize);
    1867        2090 :   gen_rectdraw0(&plot, w, x, y, lw, 1, 1);
    1868        2090 :   fprintf(psfile,"stroke showpage\n"); fclose(psfile);
    1869        2090 : }
    1870             : 
    1871             : #define RoColT(R) minss(numcolors,RoCol(R))
    1872             : 
    1873             : void
    1874        2090 : gen_rectdraw0(struct plot_eng *eng, long *w, long *x, long *y, long lw, double xs, double ys)
    1875             : {
    1876        2090 :   void *data = eng->data;
    1877             :   long i, j;
    1878        2090 :   long hgapsize = eng->pl->hunit, fheight = eng->pl->fheight;
    1879        2090 :   long vgapsize = eng->pl->vunit,  fwidth = eng->pl->fwidth;
    1880        2090 :   long numcolors = lg(GP_DATA->colormap)-1;
    1881        5225 :   for(i=0; i<lw; i++)
    1882             :   {
    1883        3135 :     PariRect *e = rectgraph[w[i]];
    1884             :     RectObj *R;
    1885        3135 :     long x0 = x[i], y0 = y[i];
    1886      173421 :     for (R = RHead(e); R; R = RoNext(R))
    1887             :     {
    1888      170286 :       switch(RoType(R))
    1889             :       {
    1890             :       case ROt_PT:
    1891          21 :         eng->sc(data,RoColT(R));
    1892          21 :         eng->pt(data, DTOL((RoPTx(R)+x0)*xs), DTOL((RoPTy(R)+y0)*ys));
    1893          21 :         break;
    1894             :       case ROt_LN:
    1895      149197 :         eng->sc(data,RoColT(R));
    1896      596788 :         eng->ln(data, DTOL((RoLNx1(R)+x0)*xs),
    1897      149197 :                       DTOL((RoLNy1(R)+y0)*ys),
    1898      149197 :                       DTOL((RoLNx2(R)+x0)*xs),
    1899      149197 :                       DTOL((RoLNy2(R)+y0)*ys));
    1900      149197 :         break;
    1901             :       case ROt_BX:
    1902        1073 :         eng->sc(data,RoColT(R));
    1903        5365 :         eng->bx(data,
    1904        1073 :                 DTOL((RoBXx1(R)+x0)*xs),
    1905        1073 :                 DTOL((RoBXy1(R)+y0)*ys),
    1906        1073 :                 DTOL((RoBXx2(R)-RoBXx1(R))*xs),
    1907        1073 :                 DTOL((RoBXy2(R)-RoBXy1(R))*ys));
    1908        1073 :         break;
    1909             :       case ROt_MP:
    1910             :         {
    1911          21 :           double *ptx = RoMPxs(R);
    1912          21 :           double *pty = RoMPys(R);
    1913          21 :           long     nb = RoMPcnt(R);
    1914          21 :           struct plot_points *points =
    1915          21 :             (struct plot_points *) pari_malloc(sizeof(*points)*nb);
    1916         860 :           for(j=0;j<nb;j++)
    1917             :           {
    1918         839 :             points[j].x = DTOL((ptx[j]+x0)*xs);
    1919         839 :             points[j].y = DTOL((pty[j]+y0)*ys);
    1920             :           }
    1921          21 :           eng->sc(data,RoColT(R));
    1922          21 :           eng->mp(data, nb, points);
    1923          21 :           pari_free(points);
    1924          21 :           break;
    1925             :         }
    1926             :       case ROt_ML:
    1927             :         {
    1928        1052 :           double *ptx = RoMLxs(R);
    1929        1052 :           double *pty = RoMLys(R);
    1930        1052 :           long     nb = RoMLcnt(R);
    1931        1052 :           struct plot_points *points =
    1932        1052 :             (struct plot_points *) pari_malloc(sizeof(*points)*nb);
    1933      777334 :           for(j=0;j<nb;j++)
    1934             :           {
    1935      776282 :             points[j].x = DTOL((ptx[j]+x0)*xs);
    1936      776282 :             points[j].y = DTOL((pty[j]+y0)*ys);
    1937             :           }
    1938        1052 :           eng->sc(data,RoColT(R));
    1939        1052 :           eng->ml(data, nb, points);
    1940        1052 :           pari_free(points);
    1941        1052 :           break;
    1942             :         }
    1943             :       case ROt_ST:
    1944             :         {
    1945        4194 :           long dir = RoSTdir(R);
    1946        4194 :           long hjust = dir & RoSTdirHPOS_mask, hgap  = dir & RoSTdirHGAP;
    1947        4194 :           long vjust = dir & RoSTdirVPOS_mask, vgap  = dir & RoSTdirVGAP;
    1948        4194 :           char *text = RoSTs(R);
    1949        4194 :           long l     = RoSTl(R);
    1950             :           long x, y;
    1951        4194 :           long shift = (hjust == RoSTdirLEFT ? 0 :
    1952             :               (hjust == RoSTdirRIGHT ? 2 : 1));
    1953        4194 :           if (hgap)
    1954        2090 :             hgap = (hjust == RoSTdirLEFT) ? hgapsize : -hgapsize;
    1955        4194 :           if (vgap)
    1956        1045 :             vgap = (vjust == RoSTdirBOTTOM) ? 2*vgapsize : -2*vgapsize;
    1957        4194 :           if (vjust != RoSTdirBOTTOM)
    1958        3135 :             vgap -= ((vjust == RoSTdirTOP) ? 2 : 1)*(fheight - 1);
    1959        4194 :           x = DTOL((RoSTx(R) + x0 + hgap - (l * fwidth * shift)/2)*xs);
    1960        4194 :           y = DTOL((RoSTy(R) + y0 - vgap/2)*ys);
    1961        4194 :           eng->sc(data,RoColT(R));
    1962        4194 :           eng->st(data, x, y, text, l);
    1963        4194 :           break;
    1964             :         }
    1965             :       default:
    1966       14728 :         break;
    1967             :       }
    1968             :     }
    1969             :   }
    1970        2090 : }
    1971             : 
    1972             : /*************************************************************************/
    1973             : /*                                                                       */
    1974             : /*                           RGB COLORS                                  */
    1975             : /*                                                                       */
    1976             : /*************************************************************************/
    1977             : /* generated from /etc/X11/rgb.txt by the following perl script
    1978             : #!/usr/bin/perl
    1979             : while(<>)
    1980             : {
    1981             :   ($hex, $name) = split(/\t\t/, $_);
    1982             :   $hex =~ s/^ +//; chomp($name); $name =~ s, *,,g;
    1983             :   $hex = sprintf("0x%02x%02x%02x", split(/\s+/, $hex));
    1984             :   $name = lc($name); next if ($done{$name});
    1985             :   $done{$name} = 1;
    1986             :   print "COL(\"$name\", $hex),\n";
    1987             : }
    1988             : */
    1989             : 
    1990             : #define COL(x,y) {(void*)x,(void*)y,0,NULL}
    1991             : static hashentry col_list[] = {
    1992             : COL("", 0x000000),
    1993             : COL("snow", 0xfffafa),
    1994             : COL("ghostwhite", 0xf8f8ff),
    1995             : COL("whitesmoke", 0xf5f5f5),
    1996             : COL("gainsboro", 0xdcdcdc),
    1997             : COL("floralwhite", 0xfffaf0),
    1998             : COL("oldlace", 0xfdf5e6),
    1999             : COL("linen", 0xfaf0e6),
    2000             : COL("antiquewhite", 0xfaebd7),
    2001             : COL("papayawhip", 0xffefd5),
    2002             : COL("blanchedalmond", 0xffebcd),
    2003             : COL("bisque", 0xffe4c4),
    2004             : COL("peachpuff", 0xffdab9),
    2005             : COL("navajowhite", 0xffdead),
    2006             : COL("moccasin", 0xffe4b5),
    2007             : COL("cornsilk", 0xfff8dc),
    2008             : COL("ivory", 0xfffff0),
    2009             : COL("lemonchiffon", 0xfffacd),
    2010             : COL("seashell", 0xfff5ee),
    2011             : COL("honeydew", 0xf0fff0),
    2012             : COL("mintcream", 0xf5fffa),
    2013             : COL("azure", 0xf0ffff),
    2014             : COL("aliceblue", 0xf0f8ff),
    2015             : COL("lavender", 0xe6e6fa),
    2016             : COL("lavenderblush", 0xfff0f5),
    2017             : COL("mistyrose", 0xffe4e1),
    2018             : COL("white", 0xffffff),
    2019             : COL("black", 0x000000),
    2020             : COL("darkslategray", 0x2f4f4f),
    2021             : COL("darkslategrey", 0x2f4f4f),
    2022             : COL("dimgray", 0x696969),
    2023             : COL("dimgrey", 0x696969),
    2024             : COL("slategray", 0x708090),
    2025             : COL("slategrey", 0x708090),
    2026             : COL("lightslategray", 0x778899),
    2027             : COL("lightslategrey", 0x778899),
    2028             : COL("gray", 0xbebebe),
    2029             : COL("grey", 0xbebebe),
    2030             : COL("lightgrey", 0xd3d3d3),
    2031             : COL("lightgray", 0xd3d3d3),
    2032             : COL("midnightblue", 0x191970),
    2033             : COL("navy", 0x000080),
    2034             : COL("navyblue", 0x000080),
    2035             : COL("cornflowerblue", 0x6495ed),
    2036             : COL("darkslateblue", 0x483d8b),
    2037             : COL("slateblue", 0x6a5acd),
    2038             : COL("mediumslateblue", 0x7b68ee),
    2039             : COL("lightslateblue", 0x8470ff),
    2040             : COL("mediumblue", 0x0000cd),
    2041             : COL("royalblue", 0x4169e1),
    2042             : COL("blue", 0x0000ff),
    2043             : COL("dodgerblue", 0x1e90ff),
    2044             : COL("deepskyblue", 0x00bfff),
    2045             : COL("skyblue", 0x87ceeb),
    2046             : COL("lightskyblue", 0x87cefa),
    2047             : COL("steelblue", 0x4682b4),
    2048             : COL("lightsteelblue", 0xb0c4de),
    2049             : COL("lightblue", 0xadd8e6),
    2050             : COL("powderblue", 0xb0e0e6),
    2051             : COL("paleturquoise", 0xafeeee),
    2052             : COL("darkturquoise", 0x00ced1),
    2053             : COL("mediumturquoise", 0x48d1cc),
    2054             : COL("turquoise", 0x40e0d0),
    2055             : COL("cyan", 0x00ffff),
    2056             : COL("lightcyan", 0xe0ffff),
    2057             : COL("cadetblue", 0x5f9ea0),
    2058             : COL("mediumaquamarine", 0x66cdaa),
    2059             : COL("aquamarine", 0x7fffd4),
    2060             : COL("darkgreen", 0x006400),
    2061             : COL("darkolivegreen", 0x556b2f),
    2062             : COL("darkseagreen", 0x8fbc8f),
    2063             : COL("seagreen", 0x2e8b57),
    2064             : COL("mediumseagreen", 0x3cb371),
    2065             : COL("lightseagreen", 0x20b2aa),
    2066             : COL("palegreen", 0x98fb98),
    2067             : COL("springgreen", 0x00ff7f),
    2068             : COL("lawngreen", 0x7cfc00),
    2069             : COL("green", 0x00ff00),
    2070             : COL("chartreuse", 0x7fff00),
    2071             : COL("mediumspringgreen", 0x00fa9a),
    2072             : COL("greenyellow", 0xadff2f),
    2073             : COL("limegreen", 0x32cd32),
    2074             : COL("yellowgreen", 0x9acd32),
    2075             : COL("forestgreen", 0x228b22),
    2076             : COL("olivedrab", 0x6b8e23),
    2077             : COL("darkkhaki", 0xbdb76b),
    2078             : COL("khaki", 0xf0e68c),
    2079             : COL("palegoldenrod", 0xeee8aa),
    2080             : COL("lightgoldenrodyellow", 0xfafad2),
    2081             : COL("lightyellow", 0xffffe0),
    2082             : COL("yellow", 0xffff00),
    2083             : COL("gold", 0xffd700),
    2084             : COL("lightgoldenrod", 0xeedd82),
    2085             : COL("goldenrod", 0xdaa520),
    2086             : COL("darkgoldenrod", 0xb8860b),
    2087             : COL("rosybrown", 0xbc8f8f),
    2088             : COL("indianred", 0xcd5c5c),
    2089             : COL("saddlebrown", 0x8b4513),
    2090             : COL("sienna", 0xa0522d),
    2091             : COL("peru", 0xcd853f),
    2092             : COL("burlywood", 0xdeb887),
    2093             : COL("beige", 0xf5f5dc),
    2094             : COL("wheat", 0xf5deb3),
    2095             : COL("sandybrown", 0xf4a460),
    2096             : COL("tan", 0xd2b48c),
    2097             : COL("chocolate", 0xd2691e),
    2098             : COL("firebrick", 0xb22222),
    2099             : COL("brown", 0xa52a2a),
    2100             : COL("darksalmon", 0xe9967a),
    2101             : COL("salmon", 0xfa8072),
    2102             : COL("lightsalmon", 0xffa07a),
    2103             : COL("orange", 0xffa500),
    2104             : COL("darkorange", 0xff8c00),
    2105             : COL("coral", 0xff7f50),
    2106             : COL("lightcoral", 0xf08080),
    2107             : COL("tomato", 0xff6347),
    2108             : COL("orangered", 0xff4500),
    2109             : COL("red", 0xff0000),
    2110             : COL("hotpink", 0xff69b4),
    2111             : COL("deeppink", 0xff1493),
    2112             : COL("pink", 0xffc0cb),
    2113             : COL("lightpink", 0xffb6c1),
    2114             : COL("palevioletred", 0xdb7093),
    2115             : COL("maroon", 0xb03060),
    2116             : COL("mediumvioletred", 0xc71585),
    2117             : COL("violetred", 0xd02090),
    2118             : COL("magenta", 0xff00ff),
    2119             : COL("violet", 0xee82ee),
    2120             : COL("plum", 0xdda0dd),
    2121             : COL("orchid", 0xda70d6),
    2122             : COL("mediumorchid", 0xba55d3),
    2123             : COL("darkorchid", 0x9932cc),
    2124             : COL("darkviolet", 0x9400d3),
    2125             : COL("blueviolet", 0x8a2be2),
    2126             : COL("purple", 0xa020f0),
    2127             : COL("mediumpurple", 0x9370db),
    2128             : COL("thistle", 0xd8bfd8),
    2129             : COL("snow1", 0xfffafa),
    2130             : COL("snow2", 0xeee9e9),
    2131             : COL("snow3", 0xcdc9c9),
    2132             : COL("snow4", 0x8b8989),
    2133             : COL("seashell1", 0xfff5ee),
    2134             : COL("seashell2", 0xeee5de),
    2135             : COL("seashell3", 0xcdc5bf),
    2136             : COL("seashell4", 0x8b8682),
    2137             : COL("antiquewhite1", 0xffefdb),
    2138             : COL("antiquewhite2", 0xeedfcc),
    2139             : COL("antiquewhite3", 0xcdc0b0),
    2140             : COL("antiquewhite4", 0x8b8378),
    2141             : COL("bisque1", 0xffe4c4),
    2142             : COL("bisque2", 0xeed5b7),
    2143             : COL("bisque3", 0xcdb79e),
    2144             : COL("bisque4", 0x8b7d6b),
    2145             : COL("peachpuff1", 0xffdab9),
    2146             : COL("peachpuff2", 0xeecbad),
    2147             : COL("peachpuff3", 0xcdaf95),
    2148             : COL("peachpuff4", 0x8b7765),
    2149             : COL("navajowhite1", 0xffdead),
    2150             : COL("navajowhite2", 0xeecfa1),
    2151             : COL("navajowhite3", 0xcdb38b),
    2152             : COL("navajowhite4", 0x8b795e),
    2153             : COL("lemonchiffon1", 0xfffacd),
    2154             : COL("lemonchiffon2", 0xeee9bf),
    2155             : COL("lemonchiffon3", 0xcdc9a5),
    2156             : COL("lemonchiffon4", 0x8b8970),
    2157             : COL("cornsilk1", 0xfff8dc),
    2158             : COL("cornsilk2", 0xeee8cd),
    2159             : COL("cornsilk3", 0xcdc8b1),
    2160             : COL("cornsilk4", 0x8b8878),
    2161             : COL("ivory1", 0xfffff0),
    2162             : COL("ivory2", 0xeeeee0),
    2163             : COL("ivory3", 0xcdcdc1),
    2164             : COL("ivory4", 0x8b8b83),
    2165             : COL("honeydew1", 0xf0fff0),
    2166             : COL("honeydew2", 0xe0eee0),
    2167             : COL("honeydew3", 0xc1cdc1),
    2168             : COL("honeydew4", 0x838b83),
    2169             : COL("lavenderblush1", 0xfff0f5),
    2170             : COL("lavenderblush2", 0xeee0e5),
    2171             : COL("lavenderblush3", 0xcdc1c5),
    2172             : COL("lavenderblush4", 0x8b8386),
    2173             : COL("mistyrose1", 0xffe4e1),
    2174             : COL("mistyrose2", 0xeed5d2),
    2175             : COL("mistyrose3", 0xcdb7b5),
    2176             : COL("mistyrose4", 0x8b7d7b),
    2177             : COL("azure1", 0xf0ffff),
    2178             : COL("azure2", 0xe0eeee),
    2179             : COL("azure3", 0xc1cdcd),
    2180             : COL("azure4", 0x838b8b),
    2181             : COL("slateblue1", 0x836fff),
    2182             : COL("slateblue2", 0x7a67ee),
    2183             : COL("slateblue3", 0x6959cd),
    2184             : COL("slateblue4", 0x473c8b),
    2185             : COL("royalblue1", 0x4876ff),
    2186             : COL("royalblue2", 0x436eee),
    2187             : COL("royalblue3", 0x3a5fcd),
    2188             : COL("royalblue4", 0x27408b),
    2189             : COL("blue1", 0x0000ff),
    2190             : COL("blue2", 0x0000ee),
    2191             : COL("blue3", 0x0000cd),
    2192             : COL("blue4", 0x00008b),
    2193             : COL("dodgerblue1", 0x1e90ff),
    2194             : COL("dodgerblue2", 0x1c86ee),
    2195             : COL("dodgerblue3", 0x1874cd),
    2196             : COL("dodgerblue4", 0x104e8b),
    2197             : COL("steelblue1", 0x63b8ff),
    2198             : COL("steelblue2", 0x5cacee),
    2199             : COL("steelblue3", 0x4f94cd),
    2200             : COL("steelblue4", 0x36648b),
    2201             : COL("deepskyblue1", 0x00bfff),
    2202             : COL("deepskyblue2", 0x00b2ee),
    2203             : COL("deepskyblue3", 0x009acd),
    2204             : COL("deepskyblue4", 0x00688b),
    2205             : COL("skyblue1", 0x87ceff),
    2206             : COL("skyblue2", 0x7ec0ee),
    2207             : COL("skyblue3", 0x6ca6cd),
    2208             : COL("skyblue4", 0x4a708b),
    2209             : COL("lightskyblue1", 0xb0e2ff),
    2210             : COL("lightskyblue2", 0xa4d3ee),
    2211             : COL("lightskyblue3", 0x8db6cd),
    2212             : COL("lightskyblue4", 0x607b8b),
    2213             : COL("slategray1", 0xc6e2ff),
    2214             : COL("slategray2", 0xb9d3ee),
    2215             : COL("slategray3", 0x9fb6cd),
    2216             : COL("slategray4", 0x6c7b8b),
    2217             : COL("lightsteelblue1", 0xcae1ff),
    2218             : COL("lightsteelblue2", 0xbcd2ee),
    2219             : COL("lightsteelblue3", 0xa2b5cd),
    2220             : COL("lightsteelblue4", 0x6e7b8b),
    2221             : COL("lightblue1", 0xbfefff),
    2222             : COL("lightblue2", 0xb2dfee),
    2223             : COL("lightblue3", 0x9ac0cd),
    2224             : COL("lightblue4", 0x68838b),
    2225             : COL("lightcyan1", 0xe0ffff),
    2226             : COL("lightcyan2", 0xd1eeee),
    2227             : COL("lightcyan3", 0xb4cdcd),
    2228             : COL("lightcyan4", 0x7a8b8b),
    2229             : COL("paleturquoise1", 0xbbffff),
    2230             : COL("paleturquoise2", 0xaeeeee),
    2231             : COL("paleturquoise3", 0x96cdcd),
    2232             : COL("paleturquoise4", 0x668b8b),
    2233             : COL("cadetblue1", 0x98f5ff),
    2234             : COL("cadetblue2", 0x8ee5ee),
    2235             : COL("cadetblue3", 0x7ac5cd),
    2236             : COL("cadetblue4", 0x53868b),
    2237             : COL("turquoise1", 0x00f5ff),
    2238             : COL("turquoise2", 0x00e5ee),
    2239             : COL("turquoise3", 0x00c5cd),
    2240             : COL("turquoise4", 0x00868b),
    2241             : COL("cyan1", 0x00ffff),
    2242             : COL("cyan2", 0x00eeee),
    2243             : COL("cyan3", 0x00cdcd),
    2244             : COL("cyan4", 0x008b8b),
    2245             : COL("darkslategray1", 0x97ffff),
    2246             : COL("darkslategray2", 0x8deeee),
    2247             : COL("darkslategray3", 0x79cdcd),
    2248             : COL("darkslategray4", 0x528b8b),
    2249             : COL("aquamarine1", 0x7fffd4),
    2250             : COL("aquamarine2", 0x76eec6),
    2251             : COL("aquamarine3", 0x66cdaa),
    2252             : COL("aquamarine4", 0x458b74),
    2253             : COL("darkseagreen1", 0xc1ffc1),
    2254             : COL("darkseagreen2", 0xb4eeb4),
    2255             : COL("darkseagreen3", 0x9bcd9b),
    2256             : COL("darkseagreen4", 0x698b69),
    2257             : COL("seagreen1", 0x54ff9f),
    2258             : COL("seagreen2", 0x4eee94),
    2259             : COL("seagreen3", 0x43cd80),
    2260             : COL("seagreen4", 0x2e8b57),
    2261             : COL("palegreen1", 0x9aff9a),
    2262             : COL("palegreen2", 0x90ee90),
    2263             : COL("palegreen3", 0x7ccd7c),
    2264             : COL("palegreen4", 0x548b54),
    2265             : COL("springgreen1", 0x00ff7f),
    2266             : COL("springgreen2", 0x00ee76),
    2267             : COL("springgreen3", 0x00cd66),
    2268             : COL("springgreen4", 0x008b45),
    2269             : COL("green1", 0x00ff00),
    2270             : COL("green2", 0x00ee00),
    2271             : COL("green3", 0x00cd00),
    2272             : COL("green4", 0x008b00),
    2273             : COL("chartreuse1", 0x7fff00),
    2274             : COL("chartreuse2", 0x76ee00),
    2275             : COL("chartreuse3", 0x66cd00),
    2276             : COL("chartreuse4", 0x458b00),
    2277             : COL("olivedrab1", 0xc0ff3e),
    2278             : COL("olivedrab2", 0xb3ee3a),
    2279             : COL("olivedrab3", 0x9acd32),
    2280             : COL("olivedrab4", 0x698b22),
    2281             : COL("darkolivegreen1", 0xcaff70),
    2282             : COL("darkolivegreen2", 0xbcee68),
    2283             : COL("darkolivegreen3", 0xa2cd5a),
    2284             : COL("darkolivegreen4", 0x6e8b3d),
    2285             : COL("khaki1", 0xfff68f),
    2286             : COL("khaki2", 0xeee685),
    2287             : COL("khaki3", 0xcdc673),
    2288             : COL("khaki4", 0x8b864e),
    2289             : COL("lightgoldenrod1", 0xffec8b),
    2290             : COL("lightgoldenrod2", 0xeedc82),
    2291             : COL("lightgoldenrod3", 0xcdbe70),
    2292             : COL("lightgoldenrod4", 0x8b814c),
    2293             : COL("lightyellow1", 0xffffe0),
    2294             : COL("lightyellow2", 0xeeeed1),
    2295             : COL("lightyellow3", 0xcdcdb4),
    2296             : COL("lightyellow4", 0x8b8b7a),
    2297             : COL("yellow1", 0xffff00),
    2298             : COL("yellow2", 0xeeee00),
    2299             : COL("yellow3", 0xcdcd00),
    2300             : COL("yellow4", 0x8b8b00),
    2301             : COL("gold1", 0xffd700),
    2302             : COL("gold2", 0xeec900),
    2303             : COL("gold3", 0xcdad00),
    2304             : COL("gold4", 0x8b7500),
    2305             : COL("goldenrod1", 0xffc125),
    2306             : COL("goldenrod2", 0xeeb422),
    2307             : COL("goldenrod3", 0xcd9b1d),
    2308             : COL("goldenrod4", 0x8b6914),
    2309             : COL("darkgoldenrod1", 0xffb90f),
    2310             : COL("darkgoldenrod2", 0xeead0e),
    2311             : COL("darkgoldenrod3", 0xcd950c),
    2312             : COL("darkgoldenrod4", 0x8b6508),
    2313             : COL("rosybrown1", 0xffc1c1),
    2314             : COL("rosybrown2", 0xeeb4b4),
    2315             : COL("rosybrown3", 0xcd9b9b),
    2316             : COL("rosybrown4", 0x8b6969),
    2317             : COL("indianred1", 0xff6a6a),
    2318             : COL("indianred2", 0xee6363),
    2319             : COL("indianred3", 0xcd5555),
    2320             : COL("indianred4", 0x8b3a3a),
    2321             : COL("sienna1", 0xff8247),
    2322             : COL("sienna2", 0xee7942),
    2323             : COL("sienna3", 0xcd6839),
    2324             : COL("sienna4", 0x8b4726),
    2325             : COL("burlywood1", 0xffd39b),
    2326             : COL("burlywood2", 0xeec591),
    2327             : COL("burlywood3", 0xcdaa7d),
    2328             : COL("burlywood4", 0x8b7355),
    2329             : COL("wheat1", 0xffe7ba),
    2330             : COL("wheat2", 0xeed8ae),
    2331             : COL("wheat3", 0xcdba96),
    2332             : COL("wheat4", 0x8b7e66),
    2333             : COL("tan1", 0xffa54f),
    2334             : COL("tan2", 0xee9a49),
    2335             : COL("tan3", 0xcd853f),
    2336             : COL("tan4", 0x8b5a2b),
    2337             : COL("chocolate1", 0xff7f24),
    2338             : COL("chocolate2", 0xee7621),
    2339             : COL("chocolate3", 0xcd661d),
    2340             : COL("chocolate4", 0x8b4513),
    2341             : COL("firebrick1", 0xff3030),
    2342             : COL("firebrick2", 0xee2c2c),
    2343             : COL("firebrick3", 0xcd2626),
    2344             : COL("firebrick4", 0x8b1a1a),
    2345             : COL("brown1", 0xff4040),
    2346             : COL("brown2", 0xee3b3b),
    2347             : COL("brown3", 0xcd3333),
    2348             : COL("brown4", 0x8b2323),
    2349             : COL("salmon1", 0xff8c69),
    2350             : COL("salmon2", 0xee8262),
    2351             : COL("salmon3", 0xcd7054),
    2352             : COL("salmon4", 0x8b4c39),
    2353             : COL("lightsalmon1", 0xffa07a),
    2354             : COL("lightsalmon2", 0xee9572),
    2355             : COL("lightsalmon3", 0xcd8162),
    2356             : COL("lightsalmon4", 0x8b5742),
    2357             : COL("orange1", 0xffa500),
    2358             : COL("orange2", 0xee9a00),
    2359             : COL("orange3", 0xcd8500),
    2360             : COL("orange4", 0x8b5a00),
    2361             : COL("darkorange1", 0xff7f00),
    2362             : COL("darkorange2", 0xee7600),
    2363             : COL("darkorange3", 0xcd6600),
    2364             : COL("darkorange4", 0x8b4500),
    2365             : COL("coral1", 0xff7256),
    2366             : COL("coral2", 0xee6a50),
    2367             : COL("coral3", 0xcd5b45),
    2368             : COL("coral4", 0x8b3e2f),
    2369             : COL("tomato1", 0xff6347),
    2370             : COL("tomato2", 0xee5c42),
    2371             : COL("tomato3", 0xcd4f39),
    2372             : COL("tomato4", 0x8b3626),
    2373             : COL("orangered1", 0xff4500),
    2374             : COL("orangered2", 0xee4000),
    2375             : COL("orangered3", 0xcd3700),
    2376             : COL("orangered4", 0x8b2500),
    2377             : COL("red1", 0xff0000),
    2378             : COL("red2", 0xee0000),
    2379             : COL("red3", 0xcd0000),
    2380             : COL("red4", 0x8b0000),
    2381             : COL("debianred", 0xd70751),
    2382             : COL("deeppink1", 0xff1493),
    2383             : COL("deeppink2", 0xee1289),
    2384             : COL("deeppink3", 0xcd1076),
    2385             : COL("deeppink4", 0x8b0a50),
    2386             : COL("hotpink1", 0xff6eb4),
    2387             : COL("hotpink2", 0xee6aa7),
    2388             : COL("hotpink3", 0xcd6090),
    2389             : COL("hotpink4", 0x8b3a62),
    2390             : COL("pink1", 0xffb5c5),
    2391             : COL("pink2", 0xeea9b8),
    2392             : COL("pink3", 0xcd919e),
    2393             : COL("pink4", 0x8b636c),
    2394             : COL("lightpink1", 0xffaeb9),
    2395             : COL("lightpink2", 0xeea2ad),
    2396             : COL("lightpink3", 0xcd8c95),
    2397             : COL("lightpink4", 0x8b5f65),
    2398             : COL("palevioletred1", 0xff82ab),
    2399             : COL("palevioletred2", 0xee799f),
    2400             : COL("palevioletred3", 0xcd6889),
    2401             : COL("palevioletred4", 0x8b475d),
    2402             : COL("maroon1", 0xff34b3),
    2403             : COL("maroon2", 0xee30a7),
    2404             : COL("maroon3", 0xcd2990),
    2405             : COL("maroon4", 0x8b1c62),
    2406             : COL("violetred1", 0xff3e96),
    2407             : COL("violetred2", 0xee3a8c),
    2408             : COL("violetred3", 0xcd3278),
    2409             : COL("violetred4", 0x8b2252),
    2410             : COL("magenta1", 0xff00ff),
    2411             : COL("magenta2", 0xee00ee),
    2412             : COL("magenta3", 0xcd00cd),
    2413             : COL("magenta4", 0x8b008b),
    2414             : COL("orchid1", 0xff83fa),
    2415             : COL("orchid2", 0xee7ae9),
    2416             : COL("orchid3", 0xcd69c9),
    2417             : COL("orchid4", 0x8b4789),
    2418             : COL("plum1", 0xffbbff),
    2419             : COL("plum2", 0xeeaeee),
    2420             : COL("plum3", 0xcd96cd),
    2421             : COL("plum4", 0x8b668b),
    2422             : COL("mediumorchid1", 0xe066ff),
    2423             : COL("mediumorchid2", 0xd15fee),
    2424             : COL("mediumorchid3", 0xb452cd),
    2425             : COL("mediumorchid4", 0x7a378b),
    2426             : COL("darkorchid1", 0xbf3eff),
    2427             : COL("darkorchid2", 0xb23aee),
    2428             : COL("darkorchid3", 0x9a32cd),
    2429             : COL("darkorchid4", 0x68228b),
    2430             : COL("purple1", 0x9b30ff),
    2431             : COL("purple2", 0x912cee),
    2432             : COL("purple3", 0x7d26cd),
    2433             : COL("purple4", 0x551a8b),
    2434             : COL("mediumpurple1", 0xab82ff),
    2435             : COL("mediumpurple2", 0x9f79ee),
    2436             : COL("mediumpurple3", 0x8968cd),
    2437             : COL("mediumpurple4", 0x5d478b),
    2438             : COL("thistle1", 0xffe1ff),
    2439             : COL("thistle2", 0xeed2ee),
    2440             : COL("thistle3", 0xcdb5cd),
    2441             : COL("thistle4", 0x8b7b8b),
    2442             : COL("gray0", 0x000000),
    2443             : COL("grey0", 0x000000),
    2444             : COL("gray1", 0x030303),
    2445             : COL("grey1", 0x030303),
    2446             : COL("gray2", 0x050505),
    2447             : COL("grey2", 0x050505),
    2448             : COL("gray3", 0x080808),
    2449             : COL("grey3", 0x080808),
    2450             : COL("gray4", 0x0a0a0a),
    2451             : COL("grey4", 0x0a0a0a),
    2452             : COL("gray5", 0x0d0d0d),
    2453             : COL("grey5", 0x0d0d0d),
    2454             : COL("gray6", 0x0f0f0f),
    2455             : COL("grey6", 0x0f0f0f),
    2456             : COL("gray7", 0x121212),
    2457             : COL("grey7", 0x121212),
    2458             : COL("gray8", 0x141414),
    2459             : COL("grey8", 0x141414),
    2460             : COL("gray9", 0x171717),
    2461             : COL("grey9", 0x171717),
    2462             : COL("gray10", 0x1a1a1a),
    2463             : COL("grey10", 0x1a1a1a),
    2464             : COL("gray11", 0x1c1c1c),
    2465             : COL("grey11", 0x1c1c1c),
    2466             : COL("gray12", 0x1f1f1f),
    2467             : COL("grey12", 0x1f1f1f),
    2468             : COL("gray13", 0x212121),
    2469             : COL("grey13", 0x212121),
    2470             : COL("gray14", 0x242424),
    2471             : COL("grey14", 0x242424),
    2472             : COL("gray15", 0x262626),
    2473             : COL("grey15", 0x262626),
    2474             : COL("gray16", 0x292929),
    2475             : COL("grey16", 0x292929),
    2476             : COL("gray17", 0x2b2b2b),
    2477             : COL("grey17", 0x2b2b2b),
    2478             : COL("gray18", 0x2e2e2e),
    2479             : COL("grey18", 0x2e2e2e),
    2480             : COL("gray19", 0x303030),
    2481             : COL("grey19", 0x303030),
    2482             : COL("gray20", 0x333333),
    2483             : COL("grey20", 0x333333),
    2484             : COL("gray21", 0x363636),
    2485             : COL("grey21", 0x363636),
    2486             : COL("gray22", 0x383838),
    2487             : COL("grey22", 0x383838),
    2488             : COL("gray23", 0x3b3b3b),
    2489             : COL("grey23", 0x3b3b3b),
    2490             : COL("gray24", 0x3d3d3d),
    2491             : COL("grey24", 0x3d3d3d),
    2492             : COL("gray25", 0x404040),
    2493             : COL("grey25", 0x404040),
    2494             : COL("gray26", 0x424242),
    2495             : COL("grey26", 0x424242),
    2496             : COL("gray27", 0x454545),
    2497             : COL("grey27", 0x454545),
    2498             : COL("gray28", 0x474747),
    2499             : COL("grey28", 0x474747),
    2500             : COL("gray29", 0x4a4a4a),
    2501             : COL("grey29", 0x4a4a4a),
    2502             : COL("gray30", 0x4d4d4d),
    2503             : COL("grey30", 0x4d4d4d),
    2504             : COL("gray31", 0x4f4f4f),
    2505             : COL("grey31", 0x4f4f4f),
    2506             : COL("gray32", 0x525252),
    2507             : COL("grey32", 0x525252),
    2508             : COL("gray33", 0x545454),
    2509             : COL("grey33", 0x545454),
    2510             : COL("gray34", 0x575757),
    2511             : COL("grey34", 0x575757),
    2512             : COL("gray35", 0x595959),
    2513             : COL("grey35", 0x595959),
    2514             : COL("gray36", 0x5c5c5c),
    2515             : COL("grey36", 0x5c5c5c),
    2516             : COL("gray37", 0x5e5e5e),
    2517             : COL("grey37", 0x5e5e5e),
    2518             : COL("gray38", 0x616161),
    2519             : COL("grey38", 0x616161),
    2520             : COL("gray39", 0x636363),
    2521             : COL("grey39", 0x636363),
    2522             : COL("gray40", 0x666666),
    2523             : COL("grey40", 0x666666),
    2524             : COL("gray41", 0x696969),
    2525             : COL("grey41", 0x696969),
    2526             : COL("gray42", 0x6b6b6b),
    2527             : COL("grey42", 0x6b6b6b),
    2528             : COL("gray43", 0x6e6e6e),
    2529             : COL("grey43", 0x6e6e6e),
    2530             : COL("gray44", 0x707070),
    2531             : COL("grey44", 0x707070),
    2532             : COL("gray45", 0x737373),
    2533             : COL("grey45", 0x737373),
    2534             : COL("gray46", 0x757575),
    2535             : COL("grey46", 0x757575),
    2536             : COL("gray47", 0x787878),
    2537             : COL("grey47", 0x787878),
    2538             : COL("gray48", 0x7a7a7a),
    2539             : COL("grey48", 0x7a7a7a),
    2540             : COL("gray49", 0x7d7d7d),
    2541             : COL("grey49", 0x7d7d7d),
    2542             : COL("gray50", 0x7f7f7f),
    2543             : COL("grey50", 0x7f7f7f),
    2544             : COL("gray51", 0x828282),
    2545             : COL("grey51", 0x828282),
    2546             : COL("gray52", 0x858585),
    2547             : COL("grey52", 0x858585),
    2548             : COL("gray53", 0x878787),
    2549             : COL("grey53", 0x878787),
    2550             : COL("gray54", 0x8a8a8a),
    2551             : COL("grey54", 0x8a8a8a),
    2552             : COL("gray55", 0x8c8c8c),
    2553             : COL("grey55", 0x8c8c8c),
    2554             : COL("gray56", 0x8f8f8f),
    2555             : COL("grey56", 0x8f8f8f),
    2556             : COL("gray57", 0x919191),
    2557             : COL("grey57", 0x919191),
    2558             : COL("gray58", 0x949494),
    2559             : COL("grey58", 0x949494),
    2560             : COL("gray59", 0x969696),
    2561             : COL("grey59", 0x969696),
    2562             : COL("gray60", 0x999999),
    2563             : COL("grey60", 0x999999),
    2564             : COL("gray61", 0x9c9c9c),
    2565             : COL("grey61", 0x9c9c9c),
    2566             : COL("gray62", 0x9e9e9e),
    2567             : COL("grey62", 0x9e9e9e),
    2568             : COL("gray63", 0xa1a1a1),
    2569             : COL("grey63", 0xa1a1a1),
    2570             : COL("gray64", 0xa3a3a3),
    2571             : COL("grey64", 0xa3a3a3),
    2572             : COL("gray65", 0xa6a6a6),
    2573             : COL("grey65", 0xa6a6a6),
    2574             : COL("gray66", 0xa8a8a8),
    2575             : COL("grey66", 0xa8a8a8),
    2576             : COL("gray67", 0xababab),
    2577             : COL("grey67", 0xababab),
    2578             : COL("gray68", 0xadadad),
    2579             : COL("grey68", 0xadadad),
    2580             : COL("gray69", 0xb0b0b0),
    2581             : COL("grey69", 0xb0b0b0),
    2582             : COL("gray70", 0xb3b3b3),
    2583             : COL("grey70", 0xb3b3b3),
    2584             : COL("gray71", 0xb5b5b5),
    2585             : COL("grey71", 0xb5b5b5),
    2586             : COL("gray72", 0xb8b8b8),
    2587             : COL("grey72", 0xb8b8b8),
    2588             : COL("gray73", 0xbababa),
    2589             : COL("grey73", 0xbababa),
    2590             : COL("gray74", 0xbdbdbd),
    2591             : COL("grey74", 0xbdbdbd),
    2592             : COL("gray75", 0xbfbfbf),
    2593             : COL("grey75", 0xbfbfbf),
    2594             : COL("gray76", 0xc2c2c2),
    2595             : COL("grey76", 0xc2c2c2),
    2596             : COL("gray77", 0xc4c4c4),
    2597             : COL("grey77", 0xc4c4c4),
    2598             : COL("gray78", 0xc7c7c7),
    2599             : COL("grey78", 0xc7c7c7),
    2600             : COL("gray79", 0xc9c9c9),
    2601             : COL("grey79", 0xc9c9c9),
    2602             : COL("gray80", 0xcccccc),
    2603             : COL("grey80", 0xcccccc),
    2604             : COL("gray81", 0xcfcfcf),
    2605             : COL("grey81", 0xcfcfcf),
    2606             : COL("gray82", 0xd1d1d1),
    2607             : COL("grey82", 0xd1d1d1),
    2608             : COL("gray83", 0xd4d4d4),
    2609             : COL("grey83", 0xd4d4d4),
    2610             : COL("gray84", 0xd6d6d6),
    2611             : COL("grey84", 0xd6d6d6),
    2612             : COL("gray85", 0xd9d9d9),
    2613             : COL("grey85", 0xd9d9d9),
    2614             : COL("gray86", 0xdbdbdb),
    2615             : COL("grey86", 0xdbdbdb),
    2616             : COL("gray87", 0xdedede),
    2617             : COL("grey87", 0xdedede),
    2618             : COL("gray88", 0xe0e0e0),
    2619             : COL("grey88", 0xe0e0e0),
    2620             : COL("gray89", 0xe3e3e3),
    2621             : COL("grey89", 0xe3e3e3),
    2622             : COL("gray90", 0xe5e5e5),
    2623             : COL("grey90", 0xe5e5e5),
    2624             : COL("gray91", 0xe8e8e8),
    2625             : COL("grey91", 0xe8e8e8),
    2626             : COL("gray92", 0xebebeb),
    2627             : COL("grey92", 0xebebeb),
    2628             : COL("gray93", 0xededed),
    2629             : COL("grey93", 0xededed),
    2630             : COL("gray94", 0xf0f0f0),
    2631             : COL("grey94", 0xf0f0f0),
    2632             : COL("gray95", 0xf2f2f2),
    2633             : COL("grey95", 0xf2f2f2),
    2634             : COL("gray96", 0xf5f5f5),
    2635             : COL("grey96", 0xf5f5f5),
    2636             : COL("gray97", 0xf7f7f7),
    2637             : COL("grey97", 0xf7f7f7),
    2638             : COL("gray98", 0xfafafa),
    2639             : COL("grey98", 0xfafafa),
    2640             : COL("gray99", 0xfcfcfc),
    2641             : COL("grey99", 0xfcfcfc),
    2642             : COL("gray100", 0xffffff),
    2643             : COL("grey100", 0xffffff),
    2644             : COL("darkgrey", 0xa9a9a9),
    2645             : COL("darkgray", 0xa9a9a9),
    2646             : COL("darkblue", 0x00008b),
    2647             : COL("darkcyan", 0x008b8b),
    2648             : COL("darkmagenta", 0x8b008b),
    2649             : COL("darkred", 0x8b0000),
    2650             : COL("lightgreen", 0x90ee90),
    2651             : COL(NULL,0) /* sentinel */
    2652             : };
    2653             : #undef COL
    2654             : 
    2655             : static void
    2656      155558 : colorname_to_rgb(const char *s, int *r, int *g, int *b)
    2657             : {
    2658             :   hashentry *ep;
    2659             :   long rgb;
    2660             : 
    2661      155558 :   if (!rgb_colors) rgb_colors = hashstr_import_static(col_list, 1000);
    2662      155558 :   ep = hash_search(rgb_colors, (void*)s);
    2663      155558 :   if (!ep) pari_err(e_MISC, "unknown color %s", s);
    2664      155558 :   rgb = (long)ep->val;
    2665      155558 :   *b = rgb & 0xff; rgb >>= 8;
    2666      155558 :   *g = rgb & 0xff; rgb >>= 8;
    2667      155558 :   *r = rgb;
    2668      155558 : }
    2669             : 
    2670             : void
    2671      155558 : color_to_rgb(GEN c, int *r, int *g, int *b)
    2672             : {
    2673      155558 :   switch(typ(c))
    2674             :   {
    2675             :     case t_STR:
    2676      155558 :       colorname_to_rgb(GSTR(c), r,g,b);
    2677      155558 :       break;
    2678             :     default: /* t_VECSMALL: */
    2679           0 :       *r = c[1]; *g = c[2]; *b = c[3];
    2680           0 :       break;
    2681             :   }
    2682      155558 : }

Generated by: LCOV version 1.11