Re: [ROOT] TGraph::SetPoint performance

From: Rene Brun (Rene.Brun@cern.ch)
Date: Fri Sep 10 2004 - 09:36:38 MEST


Hi Maxim,

Nice improvement. Now in CVS (with a few typo mods).
Could you provide the similar changes for TGraphAsymmErrors and
TGraphBentErrors?

Rene

Maxim Nikulin wrote:
> 
> Dear Rene,
> 
> I'm sorry for long delay.
> 
> Rene Brun wrote:
>  > Hi Maxim,
>  >
>  > In the CVS version, I have improved the array reallocation mechanism
>  > for TGraph, TGraphErrors, TGraphAsymmErrors and TGraphBentErrors.
>  > I hope that you see an improvement. Let me know.
> 
> Your solution works, performance of TGraph::SetPoint() was improved. but
> I am not satisfied yet. I'm surprised that
> 
> new Double_t[0];
> 
> doesn't lead to segmentation fault. Consider
> 
> gr = new TGraph(); // fMaxSize = 0;
> gr->SetPoint(Int_t i = 0, 1, 2); // (i >= fMaxSize) is true, 2*i == 0
> 
> A have several additional remarks. Probable methods
> TGraph::InsertPoint(), TGraph::RemovePoint() should also use buffers.
> 
> I'm suggesting add test (2 == sscanf(...)) in the TGraph::TGraph(const
> char *filename, const char *format) constructor. It allows to skip empty
> lines and comments like '# comment '. Similar TGraphErrors constructor
> uses inaccurate field counting algorithm. It doesn't allow skipping
> numbers using "*" modifier.
> 
> I'm sending my attempt to implement issues mentioned above (only for
> TGraph and TGraphErros). The patch is  in the attachment. Use
> 
> patch -p1 < TGraph_TGraphErrors.patch
> 
> from root/graph source directory. I'm trying to localize new/delete
> operations.
> 
> --
> Yours faithfully,
> Maxim Nikulin
> 
> > Maxim Nikulin wrote:
> >
> >>Hi,
> >>
> >>I'm writing a kind of slow control system. I use several histograms, two
> >>dimensional plots and TGTextView widgets. They should be "ready to
> >>display". If program receives entries one by one it works fine, but
> >>reading a file recorded early takes significant time.
> >>
> >>Using the callgrind program I found several poor places. The first one
> >>was TGTextView::AddLine() (Posted in
> >>http://root.cern.ch/cgi-bin/print_hit_bold.pl/root/roottalk/roottalk04/2536.html
> >>and fixed). Than my manipulations with TAxis::SetTimeDisplay() became
> >>most important (old post, for curiosity only
> >>http://root.cern.ch/phpBB2/viewtopic.php?t=992 ) and I found more cheap
> >>workaround.
> >>
> >>For two dimensional plots I use the TGraph class. When the program
> >>receives an entry it calls TGraph::SetPoint(). This leads to allocation,
> >>copying and deallocation of x and y arrays. I don't use TGraph::Set() to
> >>allocate large buffer due to (0, 0) points appear on my plots.
> >>
> >>I propose to introduce additional member and split point number and
> >>array size for the TGraph suite. Are there any arguments against the
> >>solution? I checked it with restricted descendant of TGraph, but in
> >>general case it is more complicated than the TGTextView::AddLine()
> >>issue, that's why I decide to discuss it firstly.
> >>
> >>--
> >>Max
> 
>   --------------------------------------------------------------------------------
> Index: graf/inc/TGraph.h
> ===================================================================
> RCS file: /user/cvs/root/graf/inc/TGraph.h,v
> retrieving revision 1.37
> diff -a -u -r1.37 TGraph.h
> --- graf/inc/TGraph.h   6 Sep 2004 06:54:55 -0000       1.37
> +++ graf/inc/TGraph.h   9 Sep 2004 11:01:46 -0000
> @@ -49,6 +49,16 @@
>      static void      SwapValues(Double_t* arr, Int_t pos1, Int_t pos2);
>      virtual void     SwapPoints(Int_t pos1, Int_t pos2);
> 
> +    virtual Double_t **Allocate(Double_t **newarrays, Int_t newsize);
> +    virtual Bool_t CopyPoints(Double_t **newarrays, Int_t ibegin, Int_t iend,
> +                              Int_t obegin);
> +    virtual void CopyAndRelease(Double_t **newarrays,
> +                                      Int_t ibegin, Int_t iend, Int_t obegin);
> +    virtual Double_t **ExpandAndCopy(Double_t **newarrays,
> +                                     Int_t size, Int_t iend);
> +    virtual Double_t **ShrinkAndCopy(Double_t **newarrays,
> +                                     Int_t size, Int_t iend);
> +
>  public:
>      // TGraph status bits
>      enum {
> @@ -85,6 +95,8 @@
>          virtual void     DrawPanel(); // *MENU*
>          virtual Double_t Eval(Double_t x, TSpline *spline=0, Option_t *option="") const;
>          virtual void     ExecuteEvent(Int_t event, Int_t px, Int_t py);
> +        virtual void   Expand(Int_t newsize);
> +        virtual void   Expand(Int_t newsize, Int_t step);
>          virtual TObject *FindObject(const char *name) const;
>          virtual TObject *FindObject(const TObject *obj) const;
>          virtual Int_t    Fit(const char *formula ,Option_t *option="" ,Option_t *goption="", Axis_t xmin=0, Axis_t xmax=0); // *MENU*
> Index: graf/inc/TGraphErrors.h
> ===================================================================
> RCS file: /user/cvs/root/graf/inc/TGraphErrors.h,v
> retrieving revision 1.15
> diff -a -u -r1.15 TGraphErrors.h
> --- graf/inc/TGraphErrors.h     6 May 2004 09:40:30 -0000       1.15
> +++ graf/inc/TGraphErrors.h     9 Sep 2004 11:01:47 -0000
> @@ -1,4 +1,4 @@
> -// @(#)root/graf:$Name:  $:$Id: TGraphErrors.h,v 1.15 2004/05/06 09:40:30 brun Exp $
> +// @(#)root/graf:$Name: v4-00-08-patches $:$Id: TGraphErrors.h,v 1.15 2004/05/06 09:40:30 brun Exp $
>  // Author: Rene Brun   15/09/96
> 
>  /*************************************************************************
> @@ -32,6 +32,11 @@
>      Double_t    *fEY;        //[fNpoints] array of Y errors
> 
>      virtual void     SwapPoints(Int_t pos1, Int_t pos2);
> +    virtual Double_t** Allocate(Double_t **newarrays, Int_t size);
> +    virtual void CopyAndRelease(Double_t **newarrays,
> +                                Int_t ibegin, Int_t iend, Int_t obegin);
> +    virtual Bool_t CopyPoints(Double_t **arrays, Int_t ibegin, Int_t iend,
> +                              Int_t obegin);
> 
>  public:
>          TGraphErrors();
> @@ -43,6 +48,7 @@
>          TGraphErrors(const char *filename, const char *format="%lg %lg %lg %lg", Option_t *option="");
>          virtual ~TGraphErrors();
>          virtual void    Apply(TF1 *f);
> +        static Int_t    CalculateScanfFields(const char *fmt);
>          virtual void    ComputeRange(Double_t &xmin, Double_t &ymin, Double_t &xmax, Double_t &ymax) const;
>          Double_t        GetErrorX(Int_t bin) const;
>          Double_t        GetErrorY(Int_t bin) const;
> @@ -51,8 +57,6 @@
>          virtual Int_t   InsertPoint(); // *MENU*
>          virtual void    Paint(Option_t *chopt="");
>          virtual void    Print(Option_t *chopt="") const;
> -        virtual Int_t   RemovePoint(); // *MENU*
> -        virtual Int_t   RemovePoint(Int_t ipoint);
>          virtual void    SavePrimitive(ofstream &out, Option_t *option);
>          virtual void    Set(Int_t n);
>          virtual void    SetPoint(Int_t i, Double_t x, Double_t y);
> Index: graf/src/TGraph.cxx
> ===================================================================
> RCS file: /user/cvs/root/graf/src/TGraph.cxx,v
> retrieving revision 1.137
> diff -a -u -r1.137 TGraph.cxx
> --- graf/src/TGraph.cxx 6 Sep 2004 06:54:55 -0000       1.137
> +++ graf/src/TGraph.cxx 9 Sep 2004 11:01:48 -0000
> @@ -466,8 +466,10 @@
>     char line[80];
>     Int_t np = 0;
>     while (fgets(line,80,fp)) {
> -      sscanf(&line[0],format,&x, &y);
> -      if (np >= fNpoints) Set(2*fNpoints);
> +      if( 2 != sscanf(&line[0],format,&x, &y)) {
> +         // skip empty and ill-formed lines
> +         continue;
> +      }
>        SetPoint(np,x,y);
>        np++;
>     }
> @@ -503,6 +505,27 @@
>  }
> 
>  //______________________________________________________________________________
> +Double_t** TGraph::Allocate(Double_t **newarrays, Int_t size)
> +{
> +// allocate new arays of size n.
> +// For zero newarrays allocate newarrays[2],
> +// assign pointers to newarrays[0] for x and newarrays[1] for y.
> +// Return newarrays (argument or allocated one)
> +   if (size < 0) { size = 0; }
> +   if (!newarrays) {
> +      newarrays = new Double_t*[2];
> +   }
> +   if (!size) {
> +      newarrays[0] = newarrays[1] = 0;
> +   } else {
> +      newarrays[0] = new Double_t[size];
> +      newarrays[1] = new Double_t[size];
> +   }
> +   fMaxSize = size;
> +   return newarrays;
> +}
> +
> +//______________________________________________________________________________
>  void TGraph::Apply(TF1 *f)
>  {
>    // apply function f to all the data points
> @@ -554,6 +577,48 @@
>  }
> 
>  //______________________________________________________________________________
> +void TGraph::CopyAndRelease(Double_t **newarrays, Int_t ibegin, Int_t iend,
> +                           Int_t obegin)
> +{
> +// Copy points from fX and fY to arrays[0] and arrays[1]
> +// or to fX and fY if arrays == 0 and ibegin != iend.
> +// If newarrays is non null, replace fX, fY with pointers from newarrays[0,1].
> +// Delete newarrays, old fX and fY
> +   CopyPoints(newarrays, ibegin, iend, obegin);
> +   if (newarrays) {
> +      delete[] fX;
> +      fX = newarrays[0];
> +      delete[] fY;
> +      fY = newarrays[1];
> +      delete[] newarrays;
> +   }
> +}
> +
> +//______________________________________________________________________________
> +Bool_t TGraph::CopyPoints(Double_t **arrays, Int_t ibegin, Int_t iend,
> +                        Int_t obegin)
> +{
> +// Copy points from fX and fY to arrays[0] and arrays[1]
> +// or to fX and fY if arrays == 0 and ibegin != iend.
> +   if (ibegin < 0 || iend <= ibegin || obegin < 0) { // Error;
> +      return kFALSE;
> +   }
> +   if (!arrays && ibegin == obegin) { // No copying is needed
> +      return kFALSE;
> +   }
> +   if (arrays) {
> +      memmove(&arrays[0][obegin], &fX[ibegin],
> +              (iend - ibegin)*sizeof(Double_t));
> +      memmove(&arrays[1][obegin], &fY[ibegin],
> +              (iend - ibegin)*sizeof(Double_t));
> +   } else {
> +      memmove(&fX[obegin], &fX[ibegin], (iend - ibegin)*sizeof(Double_t));
> +      memmove(&fY[obegin], &fY[ibegin], (iend - ibegin)*sizeof(Double_t));
> +   }
> +   return kTRUE;
> +}
> +
> +//______________________________________________________________________________
>  void TGraph::Draw(Option_t *option)
>  {
>  //*-*-*-*-*-*-*-*-*-*-*Draw this graph with its current attributes*-*-*-*-*-*-*
> @@ -952,6 +1017,39 @@
>  }
> 
>  //______________________________________________________________________________
> +void TGraph::Expand(Int_t newsize)
> +{
> +// if array sizes <= newsize, expand storage to 2*newsize.
> +  Double_t **ps = ExpandAndCopy(0, newsize, fNpoints);
> +  CopyAndRelease(ps, 0, 0, 0);
> +}
> +
> +//______________________________________________________________________________
> +void TGraph::Expand(Int_t newsize, Int_t step)
> +{
> +// If graph capacity is less than newsize points then make array sizes
> +// equal to least multiple of step to contain newsize points.
> +// Returns kTRUE if size was altered
> +   if (newsize <= fMaxSize) {
> +      return;
> +   }
> +   Double_t **ps = Allocate(0, (newsize/step + (newsize%step?1:0))*step);
> +   CopyAndRelease(ps, 0, fNpoints, 0);
> +}
> +
> +//______________________________________________________________________________
> +Double_t **TGraph::ExpandAndCopy(Double_t **newarrays, Int_t size, Int_t iend)
> +{
> +// if size > fMaxSize allocate new arrays of 2*size points
> +//  and copy oend first points.
> +// Return pointer to new arrays.
> +   if (size <= fMaxSize) { return newarrays; }
> +   newarrays = Allocate(newarrays, 2*size);
> +   CopyPoints(newarrays, 0, iend, 0);
> +   return newarrays;
> +}
> +
> +//______________________________________________________________________________
>  TObject *TGraph::FindObject(const char *name) const
>  {
>  // search object named name in the list of functions
> @@ -1673,24 +1771,10 @@
>        if (dpx*dpx+dpy*dpy < 25) ipoint = 0;
>        else                      ipoint = fNpoints;
>     }
> -   fNpoints++;
> -   fMaxSize   = fNpoints;
> -   Double_t *newX = new Double_t[fNpoints];
> -   Double_t *newY = new Double_t[fNpoints];
> -   for (i=0;i<ipoint;i++) {
> -      newX[i] = fX[i];
> -      newY[i] = fY[i];
> -   }
> -   newX[ipoint] = gPad->PadtoX(gPad->AbsPixeltoX(px));
> -   newY[ipoint] = gPad->PadtoY(gPad->AbsPixeltoY(py));
> -   for (i=ipoint+1;i<fNpoints;i++) {
> -      newX[i] = fX[i-1];
> -      newY[i] = fY[i-1];
> -   }
> -   delete [] fX;
> -   delete [] fY;
> -   fX = newX;
> -   fY = newY;
> +   Double_t **ps = ExpandAndCopy(0, fNpoints + 1, ipoint);
> +   CopyAndRelease(ps, ipoint, fNpoints++, ipoint + 1);
> +   fX[ipoint] = gPad->PadtoX(gPad->AbsPixeltoX(px));
> +   fY[ipoint] = gPad->PadtoY(gPad->AbsPixeltoY(py));
>     gPad->Modified();
>     return ipoint;
>  }
> @@ -3291,24 +3375,7 @@
>        Int_t dpy = py - gPad->YtoAbsPixel(gPad->YtoPad(fY[i]));
>        if (dpx*dpx+dpy*dpy < 25) {ipoint = i; break;}
>     }
> -   if (ipoint == -2) return -1;
> -   fNpoints--;
> -   fMaxSize   = fNpoints;
> -   Double_t *newX = new Double_t[fNpoints];
> -   Double_t *newY = new Double_t[fNpoints];
> -   Int_t j = -1;
> -   for (i=0;i<fNpoints+1;i++) {
> -      if (i == ipoint) continue;
> -      j++;
> -      newX[j] = fX[i];
> -      newY[j] = fY[i];
> -   }
> -   delete [] fX;
> -   delete [] fY;
> -   fX = newX;
> -   fY = newY;
> -   gPad->Modified();
> -   return ipoint;
> +   return RemovePoint(ipoint);
>  }
> 
>  //______________________________________________________________________________
> @@ -3319,21 +3386,8 @@
>     if (ipoint < 0) return -1;
>     if (ipoint >= fNpoints) return -1;
> 
> -   fNpoints--;
> -   fMaxSize   = fNpoints;
> -   Double_t *newX = new Double_t[fNpoints];
> -   Double_t *newY = new Double_t[fNpoints];
> -   Int_t j = -1;
> -   for (Int_t i=0;i<fNpoints+1;i++) {
> -      if (i == ipoint) continue;
> -      j++;
> -      newX[j] = fX[i];
> -      newY[j] = fY[i];
> -   }
> -   delete [] fX;
> -   delete [] fY;
> -   fX = newX;
> -   fY = newY;
> +   Double_t **ps = ShrinkAndCopy(0, fNpoints - 1, ipoint);
> +   CopyAndRelease(ps, ipoint+1, fNpoints--, ipoint);
>     if (gPad) gPad->Modified();
>     return ipoint;
>  }
> @@ -3402,26 +3456,13 @@
> 
>     if (n < 0) n = 0;
>     if (n == fNpoints) return;
> -   Double_t *xx=0, *yy=0;
> -   if (n > 0) {
> -      xx = new Double_t[n];
> -      yy = new Double_t[n];
> -   }
> -   Int_t i;
> -   for (i=0; i<fNpoints && i<n;i++) {
> -      if (fX) xx[i] = fX[i];
> -      if (fY) yy[i] = fY[i];
> -   }
> -   for (i=fNpoints; i<n;i++) {
> -      xx[i] = 0;
> -      yy[i] = 0;
> +   Double_t **ps = Allocate(0, n);
> +   CopyAndRelease(ps, 0, TMath::Min(fNpoints,n), 0);
> +   if (n > fNpoints) {
> +      memset(&fX[fNpoints], 0, (n - fNpoints)*sizeof(Double_t));
> +      memset(&fY[fNpoints], 0, (n - fNpoints)*sizeof(Double_t));
>     }
> -   delete [] fX;
> -   delete [] fY;
>     fNpoints = n;
> -   fMaxSize = n;
> -   fX = xx;
> -   fY = yy;
>  }
> 
>  //______________________________________________________________________________
> @@ -3464,22 +3505,15 @@
> 
>     if (i < 0) return;
>     if (i >= fMaxSize) {
> -   // re-allocate the object
> -      fMaxSize = 2*i;
> -      Double_t *savex = new Double_t[fMaxSize];
> -      Double_t *savey = new Double_t[fMaxSize];
> -      if (fNpoints > 0) {
> -         memcpy(savex,fX,fNpoints*sizeof(Double_t));
> -         memcpy(savey,fY,fNpoints*sizeof(Double_t));
> -      }
> -      memset(&savex[fNpoints],0,(fMaxSize-fNpoints)*sizeof(Double_t));
> -      memset(&savey[fNpoints],0,(fMaxSize-fNpoints)*sizeof(Double_t));
> -      if (fX) delete [] fX;
> -      if (fY) delete [] fY;
> -      fX = savex;
> -      fY = savey;
> +      Double_t **ps = ExpandAndCopy(0, i+1, fNpoints);
> +      CopyAndRelease(ps, 0,0,0);
> +   }
> +   if (i >= fNpoints) {
> +      // points above i can be not initialized
> +      memset(&fX[fNpoints],0,(i-fNpoints)*sizeof(Double_t));
> +      memset(&fY[fNpoints],0,(i-fNpoints)*sizeof(Double_t));
> +      fNpoints = i+1;
>     }
> -   if (i >= fNpoints) fNpoints = i+1;
>     fX[i] = x;
>     fY[i] = y;
>     if (fHistogram) {
> @@ -3496,6 +3530,22 @@
>  }
> 
>  //______________________________________________________________________________
> +Double_t **TGraph::ShrinkAndCopy(Double_t **newarrays, Int_t size,
> +                                 Int_t oend)
> +{
> +// if size*2 <= fMaxSize allocate new arrays of size points,
> +// copy points [0,oend).
> +// Return newarray (passed or new instance if it was zero
> +// and allocations are needed)
> +   if (size*2 > fMaxSize || !fMaxSize) {
> +      return 0;
> +   }
> +   newarrays = Allocate(newarrays, size);
> +   CopyPoints(newarrays, 0, oend, 0);
> +   return newarrays;
> +}
> +
> +//______________________________________________________________________________
>  void TGraph::Smooth(Int_t npoints, Double_t *x, Double_t *y, Int_t drawtype)
>  {
>  //*-*-*-*-*-*-*-*-*-*-*-*Smooth a curve given by N points*-*-*-*-*-*-*-*-*-*
> Index: graf/src/TGraphErrors.cxx
> ===================================================================
> RCS file: /user/cvs/root/graf/src/TGraphErrors.cxx,v
> retrieving revision 1.39
> diff -a -u -r1.39 TGraphErrors.cxx
> --- graf/src/TGraphErrors.cxx   2 Sep 2004 14:22:20 -0000       1.39
> +++ graf/src/TGraphErrors.cxx   9 Sep 2004 11:01:48 -0000
> @@ -198,21 +198,23 @@
>        return;
>     }
>     // count number of columns in format
> -   Int_t ncol = 0;
> -   char *s = (char*)format;
> -   while((s=(char*)strstr(s,"%"))) {ncol++; s++;}
> +   Int_t ncol = CalculateScanfFields(format);
>     char line[80];
>     Int_t np = 0;
> 
>     while (fgets(line,80,fp)) {
> +      ex=ey=0;
> +      Int_t res;
>        if (ncol < 3) {
> -         ex=ey=0;
> -         sscanf(&line[0],format,&x, &y);
> +         res = sscanf(&line[0],format,&x, &y);
>        } else if(ncol <4) {
> -         ex=0;
> -         sscanf(&line[0],format,&x, &y, &ey);
> +         res = sscanf(&line[0],format,&x, &y, &ey);
>        } else {
> -         sscanf(&line[0],format,&x, &y, &ex, &ey);
> +         res = sscanf(&line[0],format,&x, &y, &ex, &ey);
> +      }
> +      if (res < 2) {
> +         // not a data line
> +         continue;
>        }
>        if (np >= fNpoints) Set(2*fNpoints);
>        SetPoint(np,x,y);
> @@ -235,6 +237,28 @@
>  }
> 
>  //______________________________________________________________________________
> +Double_t** TGraphErrors::Allocate(Double_t **newarrays, Int_t size)
> +{
> +// allocate new arays of size n.
> +// For zero newarrays allocate newarrays[4],
> +// assign pointers to newarrays[0] for ex and newarrays[1] for ey,
> +// newarrays[2] for x and newarrays[3] for y
> +// Return newarrays (argument or allocated one)
> +   if (size < 0) { size = 0; }
> +   if (!newarrays) {
> +      newarrays = new Double_t*[4];
> +   }
> +   if (!size) {
> +      newarrays[0] = newarrays[1] = 0;
> +   } else {
> +      newarrays[0] = new Double_t[size];
> +      newarrays[1] = new Double_t[size];
> +   }
> +   TGraph::Allocate(newarrays + 2, size);
> +   return newarrays;
> +}
> +
> +//______________________________________________________________________________
>  void TGraphErrors::Apply(TF1 *f)
>  {
>    // apply function to all the data points
> @@ -262,6 +286,34 @@
>  }
> 
>  //______________________________________________________________________________
> +Int_t TGraphErrors::CalculateScanfFields(const char *fmt)
> +{
> +   Int_t fields = 0;
> +   while ((fmt = strchr(fmt, '%'))) {
> +      Bool_t skip = kFALSE;
> +      while (*(++fmt)) {
> +         if ('[' == *fmt) {
> +            if (*++fmt && '^' == *fmt) ++fmt; // "%[^]a]"
> +            if (*++fmt && ']' == *fmt) ++fmt; // "%[]a]" or "%[^]a]"
> +            while (*fmt && *fmt != ']')
> +               ++fmt;
> +            if (!skip) ++fields;
> +            break;
> +         }
> +         if ('%' == *fmt) break; // %% literal %
> +         if ('*' == *fmt) {
> +            skip = kTRUE; // %*d -- skip a number
> +         } else if (strchr("dDiouxXxfegEscpn", *fmt)) {
> +            if (!skip) ++fields;
> +            break;
> +         }
> +         // skip modifiers & field width
> +      }
> +   }
> +   return fields;
> +}
> +
> +//______________________________________________________________________________
>  void TGraphErrors::ComputeRange(Double_t &xmin, Double_t &ymin, Double_t &xmax, Double_t &ymax) const
>  {
>    for (Int_t i=0;i<fNpoints;i++) {
> @@ -287,6 +339,52 @@
>  }
> 
>  //______________________________________________________________________________
> +void TGraphErrors::CopyAndRelease(Double_t **newarrays,
> +                                  Int_t ibegin, Int_t iend, Int_t obegin)
> +{
> +// Copy points from fX and fY to arrays[3] and arrays[1],
> +// errors from arrays[0] and arrays[1];
> +// or to fX and fY if arrays == 0 and ibegin != iend.
> +// If newarrays is non null, replace fX, fY with pointers from newarrays[0,1].
> +// Delete newarrays, old fX and fY
> +   CopyPoints(newarrays, ibegin, iend, obegin);
> +   if (newarrays) {
> +      delete[] fX;
> +      fX = newarrays[2];
> +      delete[] fY;
> +      fY = newarrays[3];
> +      delete[] fEX;
> +      fEX = newarrays[0];
> +      delete[] fEY;
> +      fEY = newarrays[1];
> +      delete[] newarrays;
> +   }
> +}
> +
> +//______________________________________________________________________________
> +Bool_t TGraphErrors::CopyPoints(Double_t **arrays, Int_t ibegin, Int_t iend,
> +                                Int_t obegin)
> +{
> +// Copy errors from fEX and fEY to arrays[0] and arrays[1]
> +// or to fX and fY. Copy points.
> +   if (TGraph::CopyPoints(arrays ? arrays+2 : 0, ibegin, iend, obegin)) {
> +      if (arrays) {
> +         memmove(&arrays[0][obegin], &fEX[ibegin],
> +                 (iend - ibegin)*sizeof(Double_t));
> +         memmove(&arrays[1][obegin], &fEY[ibegin],
> +                 (iend - ibegin)*sizeof(Double_t));
> +      } else {
> +         memmove(&fEX[obegin], &fEX[ibegin], (iend - ibegin)*sizeof(Double_t));
> +         memmove(&fEY[obegin], &fEY[ibegin], (iend - ibegin)*sizeof(Double_t));
> +      }
> +      return kTRUE;
> +   } else {
> +      return kFALSE;
> +   }
> +}
> +
> +
> +//______________________________________________________________________________
>  Double_t TGraphErrors::GetErrorX(Int_t i) const
>  {
>  //    This function is called by GraphFitChisquare.
> @@ -314,24 +412,10 @@
>  // Insert a new point at the mouse position
> 
>     Int_t ipoint = TGraph::InsertPoint();
> -
> -   Double_t *newEX = new Double_t[fNpoints];
> -   Double_t *newEY = new Double_t[fNpoints];
> -   Int_t i;
> -   for (i=0;i<ipoint;i++) {
> -      newEX[i] = fEX[i];
> -      newEY[i] = fEY[i];
> -   }
> -   newEX[ipoint] = 0;
> -   newEY[ipoint] = 0;
> -   for (i=ipoint+1;i<fNpoints;i++) {
> -      newEX[i] = fEX[i-1];
> -      newEY[i] = fEY[i-1];
> +   if (ipoint >= 0) {
> +      fEX[ipoint] = 0;
> +      fEY[ipoint] = 0;
>     }
> -   delete [] fEX;
> -   delete [] fEY;
> -   fEX = newEX;
> -   fEY = newEY;
>     return ipoint;
>  }
> 
> @@ -546,54 +630,6 @@
>  }
> 
>  //______________________________________________________________________________
> -Int_t TGraphErrors::RemovePoint()
> -{
> -// Delete point close to the mouse position
> -
> -   Int_t ipoint = TGraph::RemovePoint();
> -   if (ipoint < 0) return ipoint;
> -
> -   Double_t *newEX = new Double_t[fNpoints];
> -   Double_t *newEY = new Double_t[fNpoints];
> -   Int_t i, j = -1;
> -   for (i=0;i<fNpoints+1;i++) {
> -      if (i == ipoint) continue;
> -      j++;
> -      newEX[j] = fEX[i];
> -      newEY[j] = fEY[i];
> -   }
> -   delete [] fEX;
> -   delete [] fEY;
> -   fEX = newEX;
> -   fEY = newEY;
> -   return ipoint;
> -}
> -
> -//______________________________________________________________________________
> -Int_t TGraphErrors::RemovePoint(Int_t ipnt)
> -{
> -// Delete point number ipnt
> -
> -   Int_t ipoint = TGraph::RemovePoint(ipnt);
> -   if (ipoint < 0) return ipoint;
> -
> -   Double_t *newEX = new Double_t[fNpoints];
> -   Double_t *newEY = new Double_t[fNpoints];
> -   Int_t i, j = -1;
> -   for (i=0;i<fNpoints+1;i++) {
> -      if (i == ipoint) continue;
> -      j++;
> -      newEX[j] = fEX[i];
> -      newEY[j] = fEY[i];
> -   }
> -   delete [] fEX;
> -   delete [] fEY;
> -   fEX = newEX;
> -   fEY = newEY;
> -   return ipoint;
> -}
> -
> -//______________________________________________________________________________
>  void TGraphErrors::SavePrimitive(ofstream &out, Option_t *option)
>  {
>      // Save primitive as a C++ statement(s) on output stream out
> @@ -655,39 +691,12 @@
>  // Existing coordinates are preserved
>  // New coordinates and errors above fNpoints are preset to 0.
> 
> -   if (n < 0) n = 0;
> -   if (n == fNpoints) return;
> -   Double_t *x=0, *y=0, *ex=0, *ey=0;
> -   if (n > 0) {
> -      x  = new Double_t[n];
> -      y  = new Double_t[n];
> -      ex = new Double_t[n];
> -      ey = new Double_t[n];
> -   }
> -   Int_t i;
> -   for (i=0; i<fNpoints && i<n;i++) {
> -      if (fX)   x[i] = fX[i];
> -      if (fY)   y[i] = fY[i];
> -      if (fEX) ex[i] = fEX[i];
> -      if (fEY) ey[i] = fEY[i];
> -   }
> -   for (i=fNpoints; i<n;i++) {
> -      x[i]  = 0;
> -      y[i]  = 0;
> -      ex[i] = 0;
> -      ey[i] = 0;
> +   Int_t saveNpoints = fNpoints;
> +   TGraph::Set(n);
> +   if (fNpoints > saveNpoints) {
> +      memset(&fEX[saveNpoints], 0, (fNpoints - saveNpoints)*sizeof(Double_t));
> +      memset(&fEY[saveNpoints], 0, (fNpoints - saveNpoints)*sizeof(Double_t));
>     }
> -   delete [] fX;
> -   delete [] fY;
> -   delete [] fEX;
> -   delete [] fEY;
> -   fNpoints = n;
> -   fMaxSize = n;
> -
> -   fX  = x;
> -   fY  = y;
> -   fEX = ex;
> -   fEY = ey;
>  }
> 
>  //______________________________________________________________________________
> @@ -695,40 +704,11 @@
>  {
>  //*-*-*-*-*-*-*-*-*-*-*Set x and y values for point number i*-*-*-*-*-*-*-*-*
>  //*-*                  =====================================
> -
> -   if (i < 0) return;
> -   if (i >= fMaxSize) {
> -   // re-allocate the object
> -      fMaxSize = 2*i;
> -      Double_t *savex  = new Double_t[fMaxSize];
> -      Double_t *savey  = new Double_t[fMaxSize];
> -      Double_t *saveex = new Double_t[fMaxSize];
> -      Double_t *saveey = new Double_t[fMaxSize];
> -      if (fNpoints > 0) {
> -         memcpy(savex, fX, fNpoints*sizeof(Double_t));
> -         memcpy(savey, fY, fNpoints*sizeof(Double_t));
> -         memcpy(saveex,fEX,fNpoints*sizeof(Double_t));
> -         memcpy(saveey,fEY,fNpoints*sizeof(Double_t));
> -      }
> -      memset(&savex[fNpoints],0,(fMaxSize-fNpoints)*sizeof(Double_t));
> -      memset(&savey[fNpoints],0,(fMaxSize-fNpoints)*sizeof(Double_t));
> -      memset(&saveex[fNpoints],0,(fMaxSize-fNpoints)*sizeof(Double_t));
> -      memset(&saveey[fNpoints],0,(fMaxSize-fNpoints)*sizeof(Double_t));
> -      if (fX)  delete [] fX;
> -      if (fY)  delete [] fY;
> -      if (fEX) delete [] fEX;
> -      if (fEY) delete [] fEY;
> -      fX  = savex;
> -      fY  = savey;
> -      fEX = saveex;
> -      fEY = saveey;
> -   }
> -   if (i >= fNpoints) fNpoints = i+1;
> -   fX[i] = x;
> -   fY[i] = y;
> -   if (fHistogram) {
> -      delete fHistogram;
> -      fHistogram = 0;
> +   Int_t saveNpoints = fNpoints;
> +   TGraph::SetPoint(i, x, y);
> +   if (fNpoints > saveNpoints) {
> +      memset(fEX + fNpoints, 0, (fNpoints - saveNpoints + 1)*sizeof(Double_t));
> +      memset(fEY + fNpoints, 0, (fNpoints - saveNpoints + 1)*sizeof(Double_t));
>     }
>  }
>



This archive was generated by hypermail 2b29 : Sun Jan 02 2005 - 05:50:09 MET