27 ClassImp(TSplinePoly);
28 ClassImp(TSplinePoly3);
29 ClassImp(TSplinePoly5);
37 TSpline::TSpline(
const TSpline &sp) :
58 if(fHistogram)
delete fHistogram;
59 if(fGraph)
delete fGraph;
65 TSpline& TSpline::operator=(
const TSpline &sp)
68 TNamed::operator=(sp);
69 TAttLine::operator=(sp);
70 TAttFill::operator=(sp);
71 TAttMarker::operator=(sp);
97 void TSpline::Draw(Option_t *option)
101 if (gPad && !opt.Contains(
"same")) gPad->Clear();
109 Int_t TSpline::DistancetoPrimitive(Int_t px, Int_t py)
111 if (!fHistogram)
return 999;
112 return fHistogram->DistancetoPrimitive(px, py);
118 void TSpline::ExecuteEvent(Int_t event, Int_t px, Int_t py)
120 if (!fHistogram)
return;
121 fHistogram->ExecuteEvent(event, px, py);
127 void TSpline::Paint(Option_t *option)
132 TString opt = option;
134 Double_t xmin, xmax, pmin, pmax;
135 pmin = gPad->PadtoX(gPad->GetUxmin());
136 pmax = gPad->PadtoX(gPad->GetUxmax());
139 if (opt.Contains(
"same")) {
140 if (xmax < pmin)
return;
141 if (xmin > pmax)
return;
142 if (xmin < pmin) xmin = pmin;
143 if (xmax > pmax) xmax = pmax;
150 if ((!gPad->GetLogx() && fHistogram->TestBit(TH1::kLogX)) ||
151 (gPad->GetLogx() && !fHistogram->TestBit(TH1::kLogX)))
152 {
delete fHistogram; fHistogram = 0;}
156 fHistogram->GetXaxis()->SetLimits(xmin,xmax);
160 if (xmin > 0 && gPad->GetLogx()) {
161 Double_t *xbins =
new Double_t[fNpx+1];
162 Double_t xlogmin = TMath::Log10(xmin);
163 Double_t xlogmax = TMath::Log10(xmax);
164 Double_t dlogx = (xlogmax-xlogmin)/((Double_t)fNpx);
165 for (i=0;i<=fNpx;i++) {
166 xbins[i] = gPad->PadtoX(xlogmin+ i*dlogx);
168 fHistogram =
new TH1F(
"Spline",GetTitle(),fNpx,xbins);
169 fHistogram->SetBit(TH1::kLogX);
172 fHistogram =
new TH1F(
"Spline",GetTitle(),fNpx,xmin,xmax);
174 if (!fHistogram)
return;
175 fHistogram->SetDirectory(0);
177 for (i=1;i<=fNpx;i++) {
178 xv = fHistogram->GetBinCenter(i);
179 fHistogram->SetBinContent(i,this->Eval(xv));
183 fHistogram->SetBit(TH1::kNoStats);
184 fHistogram->SetLineColor(GetLineColor());
185 fHistogram->SetLineStyle(GetLineStyle());
186 fHistogram->SetLineWidth(GetLineWidth());
187 fHistogram->SetFillColor(GetFillColor());
188 fHistogram->SetFillStyle(GetFillStyle());
189 fHistogram->SetMarkerColor(GetMarkerColor());
190 fHistogram->SetMarkerStyle(GetMarkerStyle());
191 fHistogram->SetMarkerSize(GetMarkerSize());
195 char *o = (
char *) opt.Data();
200 if(o[i]==
'p') graph=kTRUE ;
else o[j++]=o[i];
202 if (opt.Length() == 0 ) fHistogram->Paint(
"lf");
203 else if (opt ==
"same") fHistogram->Paint(
"lfsame");
204 else fHistogram->Paint(opt.Data());
209 Double_t *xx =
new Double_t[fNp];
210 Double_t *yy =
new Double_t[fNp];
212 GetKnot(i,xx[i],yy[i]);
213 fGraph=
new TGraph(fNp,xx,yy);
217 fGraph->SetMarkerColor(GetMarkerColor());
218 fGraph->SetMarkerStyle(GetMarkerStyle());
219 fGraph->SetMarkerSize(GetMarkerSize());
227 void TSpline::Streamer(TBuffer &R__b)
229 if (R__b.IsReading()) {
231 Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
233 R__b.ReadClassBuffer(TSpline::Class(),
this, R__v, R__s, R__c);
237 TNamed::Streamer(R__b);
238 TAttLine::Streamer(R__b);
239 TAttFill::Streamer(R__b);
240 TAttMarker::Streamer(R__b);
253 R__b.CheckByteCount(R__s, R__c, TSpline::IsA());
257 R__b.WriteClassBuffer(TSpline::Class(),
this);
269 TSplinePoly &TSplinePoly::operator=(TSplinePoly
const &other)
272 TObject::operator=(other);
281 void TSplinePoly::CopyPoly(TSplinePoly
const &other)
295 TSplinePoly3 &TSplinePoly3::operator=(TSplinePoly3
const &other)
298 TSplinePoly::operator=(other);
307 void TSplinePoly3::CopyPoly(TSplinePoly3
const &other)
322 TSplinePoly5 &TSplinePoly5::operator=(TSplinePoly5
const &other)
325 TSplinePoly::operator=(other);
334 void TSplinePoly5::CopyPoly(TSplinePoly5
const &other)
354 TSpline3::TSpline3(
const char *title,
355 Double_t x[], Double_t y[], Int_t n,
const char *opt,
356 Double_t valbeg, Double_t valend) :
357 TSpline(title,-1,x[0],x[n-1],n,kFALSE),
358 fValBeg(valbeg), fValEnd(valend), fBegCond(0), fEndCond(0)
363 if(opt) SetCond(opt);
367 fPoly =
new TSplinePoly3[n];
368 for (Int_t i=0; i<n; ++i) {
382 TSpline3::TSpline3(
const char *title,
383 Double_t xmin, Double_t xmax,
384 Double_t y[], Int_t n,
const char *opt,
385 Double_t valbeg, Double_t valend) :
386 TSpline(title,(xmax-xmin)/(n-1), xmin, xmax, n, kTRUE),
387 fValBeg(valbeg), fValEnd(valend),
388 fBegCond(0), fEndCond(0)
393 if(opt) SetCond(opt);
397 fPoly =
new TSplinePoly3[n];
398 for (Int_t i=0; i<n; ++i) {
399 fPoly[i].X() = fXmin+i*fDelta;
412 TSpline3::TSpline3(
const char *title,
413 Double_t x[],
const TF1 *func, Int_t n,
const char *opt,
414 Double_t valbeg, Double_t valend) :
415 TSpline(title,-1, x[0], x[n-1], n, kFALSE),
416 fValBeg(valbeg), fValEnd(valend),
417 fBegCond(0), fEndCond(0)
422 if(opt) SetCond(opt);
426 fPoly =
new TSplinePoly3[n];
427 for (Int_t i=0; i<n; ++i) {
429 fPoly[i].Y() = ((TF1*)func)->Eval(x[i]);
441 TSpline3::TSpline3(
const char *title,
442 Double_t xmin, Double_t xmax,
443 const TF1 *func, Int_t n,
const char *opt,
444 Double_t valbeg, Double_t valend) :
445 TSpline(title,(xmax-xmin)/(n-1), xmin, xmax, n, kTRUE),
446 fValBeg(valbeg), fValEnd(valend),
447 fBegCond(0), fEndCond(0)
452 if(opt) SetCond(opt);
456 fPoly =
new TSplinePoly3[n];
459 if (!func) {fKstep = kFALSE; fDelta = -1;
return;}
460 for (Int_t i=0; i<n; ++i) {
461 Double_t x=fXmin+i*fDelta;
463 fPoly[i].Y() = ((TF1*)func)->Eval(x);
475 TSpline3::TSpline3(
const char *title,
476 const TGraph *g,
const char *opt,
477 Double_t valbeg, Double_t valend) :
478 TSpline(title,-1,0,0,g->GetN(),kFALSE),
479 fValBeg(valbeg), fValEnd(valend),
480 fBegCond(0), fEndCond(0)
485 if(opt) SetCond(opt);
489 fPoly =
new TSplinePoly3[fNp];
490 for (Int_t i=0; i<fNp; ++i) {
492 g->GetPoint(i,xx,yy);
496 fXmin = fPoly[0].X();
497 fXmax = fPoly[fNp-1].X();
506 TSpline3::TSpline3(
const TH1 *h,
const char *opt,
507 Double_t valbeg, Double_t valend) :
508 TSpline(h->GetTitle(),-1,0,0,h->GetNbinsX(),kFALSE),
509 fValBeg(valbeg), fValEnd(valend),
510 fBegCond(0), fEndCond(0)
515 if(opt) SetCond(opt);
519 fPoly =
new TSplinePoly3[fNp];
520 for (Int_t i=0; i<fNp; ++i) {
521 fPoly[i].X()=h->GetXaxis()->GetBinCenter(i+1);
522 fPoly[i].Y()=h->GetBinContent(i+1);
524 fXmin = fPoly[0].X();
525 fXmax = fPoly[fNp-1].X();
534 TSpline3::TSpline3(
const TSpline3& sp3) :
537 fValBeg(sp3.fValBeg),
538 fValEnd(sp3.fValEnd),
539 fBegCond(sp3.fBegCond),
540 fEndCond(sp3.fEndCond)
542 if (fNp > 0) fPoly =
new TSplinePoly3[fNp];
543 for (Int_t i=0; i<fNp; ++i)
544 fPoly[i] = sp3.fPoly[i];
550 TSpline3& TSpline3::operator=(
const TSpline3& sp3)
553 TSpline::operator=(sp3);
555 if (fNp > 0) fPoly =
new TSplinePoly3[fNp];
556 for (Int_t i=0; i<fNp; ++i)
557 fPoly[i] = sp3.fPoly[i];
561 fBegCond=sp3.fBegCond;
562 fEndCond=sp3.fEndCond;
570 void TSpline3::SetCond(
const char *opt)
572 const char *b1 = strstr(opt,
"b1");
573 const char *e1 = strstr(opt,
"e1");
574 const char *b2 = strstr(opt,
"b2");
575 const char *e2 = strstr(opt,
"e2");
577 Error(
"SetCond",
"Cannot specify first and second derivative at first point");
579 Error(
"SetCond",
"Cannot specify first and second derivative at last point");
581 else if (b2) fBegCond=2;
583 else if (e2) fEndCond=2;
609 void TSpline3::Test()
613 Double_t a[800], c[4];
615 Double_t x[200], y[200], z;
619 printf(
"1 TEST OF TSpline3 WITH NONEQUIDISTANT KNOTS\n");
634 printf(
"\n-N = %3d M =%2d\n",n,m);
635 TSpline3 *spline =
new TSpline3(
"Test",x,y,n);
636 for (i = 0; i < n; ++i)
637 spline->GetCoeff(i,hx, a[i],a[i+200],a[i+400],a[i+600]);
639 for (i = 0; i < mm1; ++i) diff[i] = com[i] = 0;
640 for (k = 0; k < n; ++k) {
641 for (i = 0; i < mm; ++i) c[i] = a[k+i*200];
642 printf(
" ---------------------------------------%3d --------------------------------------------\n",k+1);
643 printf(
"%12.8f\n",x[k]);
645 printf(
"%16.8f\n",c[0]);
647 for (i = 0; i < mm; ++i) printf(
"%16.8f",c[i]);
649 for (i = 0; i < mm1; ++i)
650 if ((z=TMath::Abs(a[k+i*200])) > com[i]) com[i] = z;
652 for (i = 1; i < mm; ++i)
653 for (jj = i; jj < mm; ++jj) {
655 c[j-2] = c[j-1]*z+c[j-2];
657 for (i = 0; i < mm; ++i) printf(
"%16.8f",c[i]);
659 for (i = 0; i < mm1; ++i)
660 if (!(k >= n-2 && i != 0))
661 if((z = TMath::Abs(c[i]-a[k+1+i*200]))
662 > diff[i]) diff[i] = z;
665 printf(
" MAXIMUM ABSOLUTE VALUES OF DIFFERENCES \n");
666 for (i = 0; i < mm1; ++i) printf(
"%18.9E",diff[i]);
668 printf(
" MAXIMUM ABSOLUTE VALUES OF COEFFICIENTS \n");
669 if (TMath::Abs(c[0]) > com[0])
670 com[0] = TMath::Abs(c[0]);
671 for (i = 0; i < mm1; ++i) printf(
"%16.8f",com[i]);
674 for (n = 10; n <= 100; n += 10) {
678 for (i = 0; i < nm1; i += 2) {
688 printf(
"\n-N = %3d M =%2d\n",n,m);
689 spline =
new TSpline3(
"Test",x,y,n);
690 for (i = 0; i < n; ++i)
691 spline->GetCoeff(i,hx,a[i],a[i+200],a[i+400],a[i+600]);
693 for (i = 0; i < mm1; ++i)
694 diff[i] = com[i] = 0;
695 for (k = 0; k < n; ++k) {
696 for (i = 0; i < mm; ++i)
699 printf(
" ---------------------------------------%3d --------------------------------------------\n",k+1);
700 printf(
"%12.8f\n",x[k]);
701 if (k == n-1) printf(
"%16.8f\n",c[0]);
705 for (i = 0; i < mm; ++i) printf(
"%16.8f",c[i]);
708 for (i = 0; i < mm1; ++i)
709 if ((z=TMath::Abs(a[k+i*200])) > com[i])
712 for (i = 1; i < mm; ++i)
713 for (jj = i; jj < mm; ++jj) {
715 c[j-2] = c[j-1]*z+c[j-2];
718 for (i = 0; i < mm; ++i) printf(
"%16.8f",c[i]);
721 for (i = 0; i < mm1; ++i)
722 if (!(k >= n-2 && i != 0))
723 if ((z = TMath::Abs(c[i]-a[k+1+i*200]))
724 > diff[i]) diff[i] = z;
726 printf(
" MAXIMUM ABSOLUTE VALUES OF DIFFERENCES \n");
727 for (i = 0; i < mm1; ++i) printf(
"%18.9E",diff[i]);
729 printf(
" MAXIMUM ABSOLUTE VALUES OF COEFFICIENTS \n");
730 if (TMath::Abs(c[0]) > com[0])
731 com[0] = TMath::Abs(c[0]);
732 for (i = 0; i < mm1; ++i) printf(
"%16.8E",com[i]);
740 Int_t TSpline3::FindX(Double_t x)
const
742 Int_t klow=0, khig=fNp-1;
747 else if(x>=fXmax) klow=khig;
752 klow = TMath::FloorNint((x-fXmin)/fDelta);
754 if (x < fPoly[klow].X())
755 klow = TMath::Max(klow-1,0);
756 else if (klow < khig) {
757 if (x > fPoly[klow+1].X()) ++klow;
764 if(x>fPoly[khalf=(klow+khig)/2].X())
770 if(!(fPoly[klow].X()<=x && x<=fPoly[klow+1].X()))
772 "Binary search failed x(%d) = %f < x= %f < x(%d) = %f\n",
773 klow,fPoly[klow].X(),x,klow+1,fPoly[klow+1].X());
782 Double_t TSpline3::Eval(Double_t x)
const
785 if (klow >= fNp-1 && fNp > 1) klow = fNp-2;
786 return fPoly[klow].Eval(x);
792 Double_t TSpline3::Derivative(Double_t x)
const
795 if (klow >= fNp-1) klow = fNp-2;
796 return fPoly[klow].Derivative(x);
803 void TSpline3::SaveAs(
const char *filename, Option_t * )
const
806 std::ofstream *f =
new std::ofstream(filename,std::ios::out);
807 if (f == 0 || gSystem->AccessPathName(filename,kWritePermission)) {
808 Error(
"SaveAs",
"Cannot open file:%s\n",filename);
814 Int_t nch = strlen(filename);
815 snprintf(buffer,512,
"double %s",filename);
816 char *dot = strstr(buffer,
".");
818 strlcat(buffer,
"(double x) {\n",512);
819 nch = strlen(buffer); f->write(buffer,nch);
820 snprintf(buffer,512,
" const int fNp = %d, fKstep = %d;\n",fNp,fKstep);
821 nch = strlen(buffer); f->write(buffer,nch);
822 snprintf(buffer,512,
" const double fDelta = %g, fXmin = %g, fXmax = %g;\n",fDelta,fXmin,fXmax);
823 nch = strlen(buffer); f->write(buffer,nch);
827 snprintf(buffer,512,
" const double fX[%d] = {",fNp);
828 nch = strlen(buffer); f->write(buffer,nch);
832 for (i=0;i<fNp;i++) {
833 snprintf(numb,20,
" %g,",fPoly[i].X());
835 if (i == fNp-1) numb[nch-1]=0;
836 strlcat(buffer,numb,512);
837 if (i%5 == 4 || i == fNp-1) {
838 nch = strlen(buffer); f->write(buffer,nch);
839 if (i != fNp-1) snprintf(buffer,512,
"\n ");
842 snprintf(buffer,512,
" };\n");
843 nch = strlen(buffer); f->write(buffer,nch);
845 snprintf(buffer,512,
" const double fY[%d] = {",fNp);
846 nch = strlen(buffer); f->write(buffer,nch);
848 for (i=0;i<fNp;i++) {
849 snprintf(numb,20,
" %g,",fPoly[i].Y());
851 if (i == fNp-1) numb[nch-1]=0;
852 strlcat(buffer,numb,512);
853 if (i%5 == 4 || i == fNp-1) {
854 nch = strlen(buffer); f->write(buffer,nch);
855 if (i != fNp-1) snprintf(buffer,512,
"\n ");
858 snprintf(buffer,512,
" };\n");
859 nch = strlen(buffer); f->write(buffer,nch);
861 snprintf(buffer,512,
" const double fB[%d] = {",fNp);
862 nch = strlen(buffer); f->write(buffer,nch);
864 for (i=0;i<fNp;i++) {
865 snprintf(numb,20,
" %g,",fPoly[i].B());
867 if (i == fNp-1) numb[nch-1]=0;
868 strlcat(buffer,numb,512);
869 if (i%5 == 4 || i == fNp-1) {
870 nch = strlen(buffer); f->write(buffer,nch);
871 if (i != fNp-1) snprintf(buffer,512,
"\n ");
874 snprintf(buffer,512,
" };\n");
875 nch = strlen(buffer); f->write(buffer,nch);
877 snprintf(buffer,512,
" const double fC[%d] = {",fNp);
878 nch = strlen(buffer); f->write(buffer,nch);
880 for (i=0;i<fNp;i++) {
881 snprintf(numb,20,
" %g,",fPoly[i].C());
883 if (i == fNp-1) numb[nch-1]=0;
884 strlcat(buffer,numb,512);
885 if (i%5 == 4 || i == fNp-1) {
886 nch = strlen(buffer); f->write(buffer,nch);
887 if (i != fNp-1) snprintf(buffer,512,
"\n ");
890 snprintf(buffer,512,
" };\n");
891 nch = strlen(buffer); f->write(buffer,nch);
893 snprintf(buffer,512,
" const double fD[%d] = {",fNp);
894 nch = strlen(buffer); f->write(buffer,nch);
896 for (i=0;i<fNp;i++) {
897 snprintf(numb,20,
" %g,",fPoly[i].D());
899 if (i == fNp-1) numb[nch-1]=0;
900 strlcat(buffer,numb,512);
901 if (i%5 == 4 || i == fNp-1) {
902 nch = strlen(buffer); f->write(buffer,nch);
903 if (i != fNp-1) snprintf(buffer,512,
"\n ");
906 snprintf(buffer,512,
" };\n");
907 nch = strlen(buffer); f->write(buffer,nch);
910 snprintf(buffer,512,
" int klow=0;\n");
911 nch = strlen(buffer); f->write(buffer,nch);
913 snprintf(buffer,512,
" // If out of boundaries, extrapolate. It may be badly wrong\n");
914 snprintf(buffer,512,
" if(x<=fXmin) klow=0;\n");
915 nch = strlen(buffer); f->write(buffer,nch);
916 snprintf(buffer,512,
" else if(x>=fXmax) klow=fNp-1;\n");
917 nch = strlen(buffer); f->write(buffer,nch);
918 snprintf(buffer,512,
" else {\n");
919 nch = strlen(buffer); f->write(buffer,nch);
920 snprintf(buffer,512,
" if(fKstep) {\n");
921 nch = strlen(buffer); f->write(buffer,nch);
923 snprintf(buffer,512,
" // Equidistant knots, use histogramming\n");
924 nch = strlen(buffer); f->write(buffer,nch);
925 snprintf(buffer,512,
" klow = int((x-fXmin)/fDelta);\n");
926 nch = strlen(buffer); f->write(buffer,nch);
927 snprintf(buffer,512,
" if (klow < fNp-1) klow = fNp-1;\n");
928 nch = strlen(buffer); f->write(buffer,nch);
929 snprintf(buffer,512,
" } else {\n");
930 nch = strlen(buffer); f->write(buffer,nch);
931 snprintf(buffer,512,
" int khig=fNp-1, khalf;\n");
932 nch = strlen(buffer); f->write(buffer,nch);
934 snprintf(buffer,512,
" // Non equidistant knots, binary search\n");
935 nch = strlen(buffer); f->write(buffer,nch);
936 snprintf(buffer,512,
" while(khig-klow>1)\n");
937 nch = strlen(buffer); f->write(buffer,nch);
938 snprintf(buffer,512,
" if(x>fX[khalf=(klow+khig)/2]) klow=khalf;\n");
939 nch = strlen(buffer); f->write(buffer,nch);
940 snprintf(buffer,512,
" else khig=khalf;\n");
941 nch = strlen(buffer); f->write(buffer,nch);
942 snprintf(buffer,512,
" }\n");
943 nch = strlen(buffer); f->write(buffer,nch);
944 snprintf(buffer,512,
" }\n");
945 nch = strlen(buffer); f->write(buffer,nch);
946 snprintf(buffer,512,
" // Evaluate now\n");
947 nch = strlen(buffer); f->write(buffer,nch);
948 snprintf(buffer,512,
" double dx=x-fX[klow];\n");
949 nch = strlen(buffer); f->write(buffer,nch);
950 snprintf(buffer,512,
" return (fY[klow]+dx*(fB[klow]+dx*(fC[klow]+dx*fD[klow])));\n");
951 nch = strlen(buffer); f->write(buffer,nch);
956 if (f) { f->close();
delete f;}
962 void TSpline3::SavePrimitive(std::ostream &out, Option_t *option )
966 if (gROOT->ClassSaved(TSpline3::Class())) {
971 out<<
"spline3 = new TSpline3("<<quote<<GetTitle()<<quote<<
","
972 <<fXmin<<
","<<fXmax<<
",(TF1*)0,"<<fNp<<
","<<quote<<quote<<
","
973 <<fValBeg<<
","<<fValEnd<<
");"<<std::endl;
974 out<<
" spline3->SetName("<<quote<<GetName()<<quote<<
");"<<std::endl;
976 SaveFillAttributes(out,
"spline3",0,1001);
977 SaveLineAttributes(out,
"spline3",1,1,1);
978 SaveMarkerAttributes(out,
"spline3",1,1,1);
979 if (fNpx != 100) out<<
" spline3->SetNpx("<<fNpx<<
");"<<std::endl;
981 for (Int_t i=0;i<fNp;i++) {
982 out<<
" spline3->SetPoint("<<i<<
","<<fPoly[i].X()<<
","<<fPoly[i].Y()<<
");"<<std::endl;
983 out<<
" spline3->SetPointCoeff("<<i<<
","<<fPoly[i].B()<<
","<<fPoly[i].C()<<
","<<fPoly[i].D()<<
");"<<std::endl;
985 out<<
" spline3->Draw("<<quote<<option<<quote<<
");"<<std::endl;
991 void TSpline3::SetPoint(Int_t i, Double_t x, Double_t y)
993 if (i < 0 || i >= fNp)
return;
1001 void TSpline3::SetPointCoeff(Int_t i, Double_t b, Double_t c, Double_t d)
1003 if (i < 0 || i >= fNp)
return;
1044 void TSpline3::BuildCoeff()
1047 Double_t divdf1,divdf3,dtau,g=0;
1055 for (m=1; m<fNp ; ++m) {
1056 fPoly[m].C() = fPoly[m].X() - fPoly[m-1].X();
1057 fPoly[m].D() = (fPoly[m].Y() - fPoly[m-1].Y())/fPoly[m].C();
1066 fPoly[0].B() = 2.*fPoly[1].D();
1069 fPoly[0].D() = fPoly[2].C();
1070 fPoly[0].C() = fPoly[1].C() + fPoly[2].C();
1071 fPoly[0].B() =((fPoly[1].C()+2.*fPoly[0].C())*fPoly[1].D()*fPoly[2].C()+fPoly[1].C()*fPoly[1].C()*fPoly[2].D())/fPoly[0].C();
1073 }
else if (fBegCond==1) {
1075 fPoly[0].B() = fValBeg;
1078 }
else if (fBegCond==2) {
1082 fPoly[0].B() = 3.*fPoly[1].D() - fPoly[1].C()/2.*fValBeg;
1088 for (m=1; m<l; ++m) {
1089 g = -fPoly[m+1].C()/fPoly[m-1].D();
1090 fPoly[m].B() = g*fPoly[m-1].B() + 3.*(fPoly[m].C()*fPoly[m+1].D()+fPoly[m+1].C()*fPoly[m].D());
1091 fPoly[m].D() = g*fPoly[m-1].C() + 2.*(fPoly[m].C() + fPoly[m+1].C());
1099 if (fNp > 3 || fBegCond != 0) {
1102 g = fPoly[fNp-2].C() + fPoly[fNp-1].C();
1103 fPoly[fNp-1].B() = ((fPoly[fNp-1].C()+2.*g)*fPoly[fNp-1].D()*fPoly[fNp-2].C()
1104 + fPoly[fNp-1].C()*fPoly[fNp-1].C()*(fPoly[fNp-2].Y()-fPoly[fNp-3].Y())/fPoly[fNp-2].C())/g;
1105 g = -g/fPoly[fNp-2].D();
1106 fPoly[fNp-1].D() = fPoly[fNp-2].C();
1110 fPoly[fNp-1].B() = 2.*fPoly[fNp-1].D();
1111 fPoly[fNp-1].D() = 1.;
1112 g = -1./fPoly[fNp-2].D();
1114 }
else if (fEndCond == 1) {
1115 fPoly[fNp-1].B() = fValEnd;
1117 }
else if (fEndCond == 2) {
1119 fPoly[fNp-1].B() = 3.*fPoly[fNp-1].D() + fPoly[fNp-1].C()/2.*fValEnd;
1120 fPoly[fNp-1].D() = 2.;
1121 g = -1./fPoly[fNp-2].D();
1128 fPoly[fNp-1].B() = 2.*fPoly[fNp-1].D();
1129 fPoly[fNp-1].D() = 1.;
1130 g = -1./fPoly[fNp-2].D();
1133 fPoly[fNp-1].B() = fPoly[fNp-1].D();
1136 }
else if(fEndCond == 1) {
1137 fPoly[fNp-1].B() = fValEnd;
1139 }
else if(fEndCond == 2) {
1141 fPoly[fNp-1].B() = 3.*fPoly[fNp-1].D() + fPoly[fNp-1].C()/2.*fValEnd;
1142 fPoly[fNp-1].D() = 2.;
1143 g = -1./fPoly[fNp-2].D();
1147 fPoly[fNp-1].D() = g*fPoly[fNp-2].C() + fPoly[fNp-1].D();
1148 fPoly[fNp-1].B() = (g*fPoly[fNp-2].B() + fPoly[fNp-1].B())/fPoly[fNp-1].D();
1152 fPoly[j].B() = (fPoly[j].B() - fPoly[j].C()*fPoly[j+1].B())/fPoly[j].D();
1157 for (i=1; i<fNp; ++i) {
1158 dtau = fPoly[i].C();
1159 divdf1 = (fPoly[i].Y() - fPoly[i-1].Y())/dtau;
1160 divdf3 = fPoly[i-1].B() + fPoly[i].B() - 2.*divdf1;
1161 fPoly[i-1].C() = (divdf1 - fPoly[i-1].B() - divdf3)/dtau;
1162 fPoly[i-1].D() = (divdf3/dtau)/dtau;
1169 void TSpline3::Streamer(TBuffer &R__b)
1171 if (R__b.IsReading()) {
1173 Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
1175 R__b.ReadClassBuffer(TSpline3::Class(),
this, R__v, R__s, R__c);
1179 TSpline::Streamer(R__b);
1181 fPoly =
new TSplinePoly3[fNp];
1182 for(Int_t i=0; i<fNp; ++i) {
1183 fPoly[i].Streamer(R__b);
1192 R__b.WriteClassBuffer(TSpline3::Class(),
this);
1209 TSpline5::TSpline5(
const char *title,
1210 Double_t x[], Double_t y[], Int_t n,
1211 const char *opt, Double_t b1, Double_t e1,
1212 Double_t b2, Double_t e2) :
1213 TSpline(title,-1, x[0], x[n-1], n, kFALSE)
1216 const char *cb1, *ce1, *cb2, *ce2;
1220 BoundaryConditions(opt,beg,end,cb1,ce1,cb2,ce2);
1224 fPoly =
new TSplinePoly5[fNp];
1225 for (Int_t i=0; i<n; ++i) {
1226 fPoly[i+beg].X() = x[i];
1227 fPoly[i+beg].Y() = y[i];
1231 SetBoundaries(b1,e1,b2,e2,cb1,ce1,cb2,ce2);
1242 TSpline5::TSpline5(
const char *title,
1243 Double_t xmin, Double_t xmax,
1244 Double_t y[], Int_t n,
1245 const char *opt, Double_t b1, Double_t e1,
1246 Double_t b2, Double_t e2) :
1247 TSpline(title,(xmax-xmin)/(n-1), xmin, xmax, n, kTRUE)
1250 const char *cb1, *ce1, *cb2, *ce2;
1254 BoundaryConditions(opt,beg,end,cb1,ce1,cb2,ce2);
1258 fPoly =
new TSplinePoly5[fNp];
1259 for (Int_t i=0; i<n; ++i) {
1260 fPoly[i+beg].X() = fXmin+i*fDelta;
1261 fPoly[i+beg].Y() = y[i];
1265 SetBoundaries(b1,e1,b2,e2,cb1,ce1,cb2,ce2);
1276 TSpline5::TSpline5(
const char *title,
1277 Double_t x[],
const TF1 *func, Int_t n,
1278 const char *opt, Double_t b1, Double_t e1,
1279 Double_t b2, Double_t e2) :
1280 TSpline(title,-1, x[0], x[n-1], n, kFALSE)
1283 const char *cb1, *ce1, *cb2, *ce2;
1287 BoundaryConditions(opt,beg,end,cb1,ce1,cb2,ce2);
1291 fPoly =
new TSplinePoly5[fNp];
1292 for (Int_t i=0; i<n; i++) {
1293 fPoly[i+beg].X() = x[i];
1294 fPoly[i+beg].Y() = ((TF1*)func)->Eval(x[i]);
1298 SetBoundaries(b1,e1,b2,e2,cb1,ce1,cb2,ce2);
1309 TSpline5::TSpline5(
const char *title,
1310 Double_t xmin, Double_t xmax,
1311 const TF1 *func, Int_t n,
1312 const char *opt, Double_t b1, Double_t e1,
1313 Double_t b2, Double_t e2) :
1314 TSpline(title,(xmax-xmin)/(n-1), xmin, xmax, n, kTRUE)
1317 const char *cb1, *ce1, *cb2, *ce2;
1321 BoundaryConditions(opt,beg,end,cb1,ce1,cb2,ce2);
1325 fPoly =
new TSplinePoly5[fNp];
1326 for (Int_t i=0; i<n; ++i) {
1327 Double_t x=fXmin+i*fDelta;
1328 fPoly[i+beg].X() = x;
1329 if (func) fPoly[i+beg].Y() = ((TF1*)func)->Eval(x);
1331 if (!func) {fDelta = -1; fKstep = kFALSE;}
1334 SetBoundaries(b1,e1,b2,e2,cb1,ce1,cb2,ce2);
1337 if (func) BuildCoeff();
1345 TSpline5::TSpline5(
const char *title,
1347 const char *opt, Double_t b1, Double_t e1,
1348 Double_t b2, Double_t e2) :
1349 TSpline(title,-1,0,0,g->GetN(),kFALSE)
1352 const char *cb1, *ce1, *cb2, *ce2;
1356 BoundaryConditions(opt,beg,end,cb1,ce1,cb2,ce2);
1360 fPoly =
new TSplinePoly5[fNp];
1361 for (Int_t i=0; i<fNp-beg; ++i) {
1363 g->GetPoint(i,xx,yy);
1364 fPoly[i+beg].X()=xx;
1365 fPoly[i+beg].Y()=yy;
1369 SetBoundaries(b1,e1,b2,e2,cb1,ce1,cb2,ce2);
1370 fXmin = fPoly[0].X();
1371 fXmax = fPoly[fNp-1].X();
1380 TSpline5::TSpline5(
const TH1 *h,
1381 const char *opt, Double_t b1, Double_t e1,
1382 Double_t b2, Double_t e2) :
1383 TSpline(h->GetTitle(),-1,0,0,h->GetNbinsX(),kFALSE)
1386 const char *cb1, *ce1, *cb2, *ce2;
1390 BoundaryConditions(opt,beg,end,cb1,ce1,cb2,ce2);
1394 fPoly =
new TSplinePoly5[fNp];
1395 for (Int_t i=0; i<fNp-beg; ++i) {
1396 fPoly[i+beg].X()=h->GetXaxis()->GetBinCenter(i+1);
1397 fPoly[i+beg].Y()=h->GetBinContent(i+1);
1401 SetBoundaries(b1,e1,b2,e2,cb1,ce1,cb2,ce2);
1402 fXmin = fPoly[0].X();
1403 fXmax = fPoly[fNp-1].X();
1412 TSpline5::TSpline5(
const TSpline5& sp5) :
1416 if (fNp > 0) fPoly =
new TSplinePoly5[fNp];
1417 for (Int_t i=0; i<fNp; ++i) {
1418 fPoly[i] = sp5.fPoly[i];
1425 TSpline5& TSpline5::operator=(
const TSpline5& sp5)
1428 TSpline::operator=(sp5);
1430 if (fNp > 0) fPoly =
new TSplinePoly5[fNp];
1431 for (Int_t i=0; i<fNp; ++i) {
1432 fPoly[i] = sp5.fPoly[i];
1442 void TSpline5::BoundaryConditions(
const char *opt,Int_t &beg,Int_t &end,
1443 const char *&cb1,
const char *&ce1,
1444 const char *&cb2,
const char *&ce2)
1449 cb1 = strstr(opt,
"b1");
1450 ce1 = strstr(opt,
"e1");
1451 cb2 = strstr(opt,
"b2");
1452 ce2 = strstr(opt,
"e2");
1473 void TSpline5::SetBoundaries(Double_t b1, Double_t e1, Double_t b2, Double_t e2,
1474 const char *cb1,
const char *ce1,
const char *cb2,
1480 fPoly[0].X() = fPoly[1].X() = fPoly[2].X();
1481 fPoly[0].Y() = fPoly[2].Y();
1489 fPoly[1].Y()=(fPoly[3].Y()-fPoly[0].Y())/(fPoly[3].X()-fPoly[2].X());
1493 fPoly[0].X() = fPoly[1].X();
1494 fPoly[0].Y() = fPoly[1].Y();
1500 fPoly[fNp-1].X() = fPoly[fNp-2].X() = fPoly[fNp-3].X();
1501 fPoly[fNp-1].Y()=e2;
1506 fPoly[fNp-2].Y()=e1;
1509 (fPoly[fNp-3].Y()-fPoly[fNp-4].Y())
1510 /(fPoly[fNp-3].X()-fPoly[fNp-4].X());
1514 fPoly[fNp-1].X() = fPoly[fNp-2].X();
1515 fPoly[fNp-1].Y()=e1;
1522 Int_t TSpline5::FindX(Double_t x)
const
1528 if(x<=fXmin) klow=0;
1529 else if(x>=fXmax) klow=fNp-1;
1534 klow = TMath::Min(Int_t((x-fXmin)/fDelta),fNp-1);
1536 Int_t khig=fNp-1, khalf;
1540 if(x>fPoly[khalf=(klow+khig)/2].X())
1547 if(!(fPoly[klow].X()<=x && x<=fPoly[klow+1].X()))
1549 "Binary search failed x(%d) = %f < x(%d) = %f\n",
1550 klow,fPoly[klow].X(),klow+1,fPoly[klow+1].X());
1558 Double_t TSpline5::Eval(Double_t x)
const
1560 Int_t klow=FindX(x);
1561 return fPoly[klow].Eval(x);
1567 Double_t TSpline5::Derivative(Double_t x)
const
1569 Int_t klow=FindX(x);
1570 return fPoly[klow].Derivative(x);
1577 void TSpline5::SaveAs(
const char *filename, Option_t * )
const
1580 std::ofstream *f =
new std::ofstream(filename,std::ios::out);
1581 if (f == 0 || gSystem->AccessPathName(filename,kWritePermission)) {
1582 Error(
"SaveAs",
"Cannot open file:%s\n",filename);
1588 Int_t nch = strlen(filename);
1589 snprintf(buffer,512,
"double %s",filename);
1590 char *dot = strstr(buffer,
".");
1592 strlcat(buffer,
"(double x) {\n",512);
1593 nch = strlen(buffer); f->write(buffer,nch);
1594 snprintf(buffer,512,
" const int fNp = %d, fKstep = %d;\n",fNp,fKstep);
1595 nch = strlen(buffer); f->write(buffer,nch);
1596 snprintf(buffer,512,
" const double fDelta = %g, fXmin = %g, fXmax = %g;\n",fDelta,fXmin,fXmax);
1597 nch = strlen(buffer); f->write(buffer,nch);
1601 snprintf(buffer,512,
" const double fX[%d] = {",fNp);
1602 nch = strlen(buffer); f->write(buffer,nch);
1606 for (i=0;i<fNp;i++) {
1607 snprintf(numb,20,
" %g,",fPoly[i].X());
1609 if (i == fNp-1) numb[nch-1]=0;
1610 strlcat(buffer,numb,512);
1611 if (i%5 == 4 || i == fNp-1) {
1612 nch = strlen(buffer); f->write(buffer,nch);
1613 if (i != fNp-1) snprintf(buffer,512,
"\n ");
1616 snprintf(buffer,512,
" };\n");
1617 nch = strlen(buffer); f->write(buffer,nch);
1619 snprintf(buffer,512,
" const double fY[%d] = {",fNp);
1620 nch = strlen(buffer); f->write(buffer,nch);
1622 for (i=0;i<fNp;i++) {
1623 snprintf(numb,20,
" %g,",fPoly[i].Y());
1625 if (i == fNp-1) numb[nch-1]=0;
1626 strlcat(buffer,numb,512);
1627 if (i%5 == 4 || i == fNp-1) {
1628 nch = strlen(buffer); f->write(buffer,nch);
1629 if (i != fNp-1) snprintf(buffer,512,
"\n ");
1632 snprintf(buffer,512,
" };\n");
1633 nch = strlen(buffer); f->write(buffer,nch);
1635 snprintf(buffer,512,
" const double fB[%d] = {",fNp);
1636 nch = strlen(buffer); f->write(buffer,nch);
1638 for (i=0;i<fNp;i++) {
1639 snprintf(numb,20,
" %g,",fPoly[i].B());
1641 if (i == fNp-1) numb[nch-1]=0;
1642 strlcat(buffer,numb,512);
1643 if (i%5 == 4 || i == fNp-1) {
1644 nch = strlen(buffer); f->write(buffer,nch);
1645 if (i != fNp-1) snprintf(buffer,512,
"\n ");
1648 snprintf(buffer,512,
" };\n");
1649 nch = strlen(buffer); f->write(buffer,nch);
1651 snprintf(buffer,512,
" const double fC[%d] = {",fNp);
1652 nch = strlen(buffer); f->write(buffer,nch);
1654 for (i=0;i<fNp;i++) {
1655 snprintf(numb,20,
" %g,",fPoly[i].C());
1657 if (i == fNp-1) numb[nch-1]=0;
1658 strlcat(buffer,numb,512);
1659 if (i%5 == 4 || i == fNp-1) {
1660 nch = strlen(buffer); f->write(buffer,nch);
1661 if (i != fNp-1) snprintf(buffer,512,
"\n ");
1664 snprintf(buffer,512,
" };\n");
1665 nch = strlen(buffer); f->write(buffer,nch);
1667 snprintf(buffer,512,
" const double fD[%d] = {",fNp);
1668 nch = strlen(buffer); f->write(buffer,nch);
1670 for (i=0;i<fNp;i++) {
1671 snprintf(numb,20,
" %g,",fPoly[i].D());
1673 if (i == fNp-1) numb[nch-1]=0;
1674 strlcat(buffer,numb,512);
1675 if (i%5 == 4 || i == fNp-1) {
1676 nch = strlen(buffer); f->write(buffer,nch);
1677 if (i != fNp-1) snprintf(buffer,512,
"\n ");
1680 snprintf(buffer,512,
" };\n");
1681 nch = strlen(buffer); f->write(buffer,nch);
1683 snprintf(buffer,512,
" const double fE[%d] = {",fNp);
1684 nch = strlen(buffer); f->write(buffer,nch);
1686 for (i=0;i<fNp;i++) {
1687 snprintf(numb,20,
" %g,",fPoly[i].E());
1689 if (i == fNp-1) numb[nch-1]=0;
1690 strlcat(buffer,numb,512);
1691 if (i%5 == 4 || i == fNp-1) {
1692 nch = strlen(buffer); f->write(buffer,nch);
1693 if (i != fNp-1) snprintf(buffer,512,
"\n ");
1696 snprintf(buffer,512,
" };\n");
1697 nch = strlen(buffer); f->write(buffer,nch);
1699 snprintf(buffer,512,
" const double fF[%d] = {",fNp);
1700 nch = strlen(buffer); f->write(buffer,nch);
1702 for (i=0;i<fNp;i++) {
1703 snprintf(numb,20,
" %g,",fPoly[i].F());
1705 if (i == fNp-1) numb[nch-1]=0;
1706 strlcat(buffer,numb,512);
1707 if (i%5 == 4 || i == fNp-1) {
1708 nch = strlen(buffer); f->write(buffer,nch);
1709 if (i != fNp-1) snprintf(buffer,512,
"\n ");
1712 snprintf(buffer,512,
" };\n");
1713 nch = strlen(buffer); f->write(buffer,nch);
1716 snprintf(buffer,512,
" int klow=0;\n");
1717 nch = strlen(buffer); f->write(buffer,nch);
1719 snprintf(buffer,512,
" // If out of boundaries, extrapolate. It may be badly wrong\n");
1720 snprintf(buffer,512,
" if(x<=fXmin) klow=0;\n");
1721 nch = strlen(buffer); f->write(buffer,nch);
1722 snprintf(buffer,512,
" else if(x>=fXmax) klow=fNp-1;\n");
1723 nch = strlen(buffer); f->write(buffer,nch);
1724 snprintf(buffer,512,
" else {\n");
1725 nch = strlen(buffer); f->write(buffer,nch);
1726 snprintf(buffer,512,
" if(fKstep) {\n");
1727 nch = strlen(buffer); f->write(buffer,nch);
1729 snprintf(buffer,512,
" // Equidistant knots, use histogramming\n");
1730 nch = strlen(buffer); f->write(buffer,nch);
1731 snprintf(buffer,512,
" klow = int((x-fXmin)/fDelta);\n");
1732 nch = strlen(buffer); f->write(buffer,nch);
1733 snprintf(buffer,512,
" if (klow < fNp-1) klow = fNp-1;\n");
1734 nch = strlen(buffer); f->write(buffer,nch);
1735 snprintf(buffer,512,
" } else {\n");
1736 nch = strlen(buffer); f->write(buffer,nch);
1737 snprintf(buffer,512,
" int khig=fNp-1, khalf;\n");
1738 nch = strlen(buffer); f->write(buffer,nch);
1740 snprintf(buffer,512,
" // Non equidistant knots, binary search\n");
1741 nch = strlen(buffer); f->write(buffer,nch);
1742 snprintf(buffer,512,
" while(khig-klow>1)\n");
1743 nch = strlen(buffer); f->write(buffer,nch);
1744 snprintf(buffer,512,
" if(x>fX[khalf=(klow+khig)/2]) klow=khalf;\n");
1745 nch = strlen(buffer); f->write(buffer,nch);
1746 snprintf(buffer,512,
" else khig=khalf;\n");
1747 nch = strlen(buffer); f->write(buffer,nch);
1748 snprintf(buffer,512,
" }\n");
1749 nch = strlen(buffer); f->write(buffer,nch);
1750 snprintf(buffer,512,
" }\n");
1751 nch = strlen(buffer); f->write(buffer,nch);
1752 snprintf(buffer,512,
" // Evaluate now\n");
1753 nch = strlen(buffer); f->write(buffer,nch);
1754 snprintf(buffer,512,
" double dx=x-fX[klow];\n");
1755 nch = strlen(buffer); f->write(buffer,nch);
1756 snprintf(buffer,512,
" return (fY[klow]+dx*(fB[klow]+dx*(fC[klow]+dx*(fD[klow]+dx*(fE[klow]+dx*fF[klow])))));\n");
1757 nch = strlen(buffer); f->write(buffer,nch);
1762 if (f) { f->close();
delete f;}
1768 void TSpline5::SavePrimitive(std::ostream &out, Option_t *option )
1771 out<<
" "<<std::endl;
1772 if (gROOT->ClassSaved(TSpline5::Class())) {
1777 Double_t b1 = fPoly[1].Y();
1778 Double_t e1 = fPoly[fNp-1].Y();
1779 Double_t b2 = fPoly[2].Y();
1780 Double_t e2 = fPoly[fNp-1].Y();
1781 out<<
"spline5 = new TSpline5("<<quote<<GetTitle()<<quote<<
","
1782 <<fXmin<<
","<<fXmax<<
",(TF1*)0,"<<fNp<<
","<<quote<<quote<<
","
1783 <<b1<<
","<<e1<<
","<<b2<<
","<<e2<<
");"<<std::endl;
1784 out<<
" spline5->SetName("<<quote<<GetName()<<quote<<
");"<<std::endl;
1786 SaveFillAttributes(out,
"spline5",0,1001);
1787 SaveLineAttributes(out,
"spline5",1,1,1);
1788 SaveMarkerAttributes(out,
"spline5",1,1,1);
1789 if (fNpx != 100) out<<
" spline5->SetNpx("<<fNpx<<
");"<<std::endl;
1791 for (Int_t i=0;i<fNp;i++) {
1792 out<<
" spline5->SetPoint("<<i<<
","<<fPoly[i].X()<<
","<<fPoly[i].Y()<<
");"<<std::endl;
1793 out<<
" spline5->SetPointCoeff("<<i<<
","<<fPoly[i].B()<<
","<<fPoly[i].C()<<
","<<fPoly[i].D()<<
","<<fPoly[i].E()<<
","<<fPoly[i].F()<<
");"<<std::endl;
1795 out<<
" spline5->Draw("<<quote<<option<<quote<<
");"<<std::endl;
1801 void TSpline5::SetPoint(Int_t i, Double_t x, Double_t y)
1804 if (i < 0 || i >= fNp)
return;
1812 void TSpline5::SetPointCoeff(Int_t i, Double_t b, Double_t c, Double_t d,
1813 Double_t e, Double_t f)
1815 if (i < 0 || i >= fNp)
return;
1900 void TSpline5::BuildCoeff()
1903 Double_t pqqr, p, q, r, s, t, u, v,
1904 b1, p2, p3, q2, q3, r2, pq, pr, qr;
1913 q = fPoly[1].X()-fPoly[0].X();
1914 r = fPoly[2].X()-fPoly[1].X();
1918 fPoly[0].D() = fPoly[0].E() = 0;
1919 if (q) fPoly[1].D() = q*6.*q2/(qr*qr);
1920 else fPoly[1].D() = 0;
1923 for (i = 1; i < m; ++i) {
1926 r = fPoly[i+2].X()-fPoly[i+1].X();
1936 fPoly[i+1].D() = q3*6./(qr*qr);
1937 fPoly[i].D() += (q+q)*(pr*15.*pr+(p+r)*q
1938 *(pr* 20.+q2*7.)+q2*
1939 ((p2+r2)*8.+pr*21.+q2+q2))/(pqqr*pqqr);
1940 fPoly[i-1].D() += q3*6./(pq*pq);
1941 fPoly[i].E() = q2*(p*qr+pq*3.*(qr+r+r))/(pqqr*qr);
1942 fPoly[i-1].E() += q2*(r*pq+qr*3.*(pq+p+p))/(pqqr*pq);
1943 fPoly[i-1].F() = q3/pqqr;
1945 fPoly[i+1].D() = fPoly[i].E() = fPoly[i-1].F() = 0;
1948 if (r) fPoly[m-1].D() += r*6.*r2/(qr*qr);
1953 for (i = 1; i < fNp; ++i) {
1954 if (fPoly[i].X() != fPoly[i-1].X()) {
1956 (fPoly[i].Y()-fPoly[i-1].Y())/(fPoly[i].X()-fPoly[i-1].X());
1958 fPoly[i].B() = fPoly[i].Y();
1959 fPoly[i].Y() = fPoly[i-1].Y();
1962 for (i = 2; i < fNp; ++i) {
1963 if (fPoly[i].X() != fPoly[i-2].X()) {
1965 (fPoly[i].B()-fPoly[i-1].B())/(fPoly[i].X()-fPoly[i-2].X());
1967 fPoly[i].C() = fPoly[i].B()*.5;
1968 fPoly[i].B() = fPoly[i-1].B();
1974 p=fPoly[0].C()=fPoly[m-1].E()=fPoly[0].F()
1975 =fPoly[m-2].F()=fPoly[m-1].F()=0;
1976 fPoly[1].C() = fPoly[3].C()-fPoly[2].C();
1977 fPoly[1].D() = 1./fPoly[1].D();
1980 for (i = 2; i < m; ++i) {
1981 q = fPoly[i-1].D()*fPoly[i-1].E();
1982 fPoly[i].D() = 1./(fPoly[i].D()-p*fPoly[i-2].F()-q*fPoly[i-1].E());
1983 fPoly[i].E() -= q*fPoly[i-1].F();
1984 fPoly[i].C() = fPoly[i+2].C()-fPoly[i+1].C()-p*fPoly[i-2].C()
1986 p = fPoly[i-1].D()*fPoly[i-1].F();
1991 fPoly[fNp-2].C() = fPoly[fNp-1].C() = 0;
1993 for (i=fNp-3; i > 0; --i)
1994 fPoly[i].C() = (fPoly[i].C()-fPoly[i].E()*fPoly[i+1].C()
1995 -fPoly[i].F()*fPoly[i+2].C())*fPoly[i].D();
1999 q = fPoly[1].X()-fPoly[0].X();
2000 r = fPoly[2].X()-fPoly[1].X();
2005 v = fPoly[1].C()/qr;
2009 if (q) fPoly[0].F() = v/q;
2010 else fPoly[0].F() = 0;
2011 for (i = 1; i < m; ++i) {
2014 if (i != m-1) r = fPoly[i+2].X()-fPoly[i+1].X();
2021 if (qr) t = (fPoly[i+1].C()-fPoly[i].C())/qr;
2026 fPoly[i].F() = fPoly[i-1].F();
2027 if (q) fPoly[i].F() = v/q;
2028 fPoly[i].E() = s*5.;
2029 fPoly[i].D() = (fPoly[i].C()-q*s)*10;
2031 fPoly[i].D()*(p-q)+(fPoly[i+1].B()-fPoly[i].B()+(u-fPoly[i].E())*
2032 p3-(v+fPoly[i].E())*q3)/pq;
2033 fPoly[i].B() = (p*(fPoly[i+1].B()-v*q3)+q*(fPoly[i].B()-u*p3))/pq-p
2034 *q*(fPoly[i].D()+fPoly[i].E()*(q-p));
2036 fPoly[i].C() = fPoly[i-1].C();
2037 fPoly[i].D() = fPoly[i].E() = fPoly[i].F() = 0;
2042 p = fPoly[1].X()-fPoly[0].X();
2043 s = fPoly[0].F()*p*p*p;
2044 fPoly[0].E() = fPoly[0].D() = 0;
2045 fPoly[0].C() = fPoly[1].C()-s*10;
2046 fPoly[0].B() = b1-(fPoly[0].C()+s)*p;
2048 q = fPoly[fNp-1].X()-fPoly[fNp-2].X();
2049 t = fPoly[fNp-2].F()*q*q*q;
2050 fPoly[fNp-1].E() = fPoly[fNp-1].D() = 0;
2051 fPoly[fNp-1].C() = fPoly[fNp-2].C()+t*10;
2052 fPoly[fNp-1].B() += (fPoly[fNp-1].C()-t)*q;
2078 void TSpline5::Test()
2082 Double_t a[1200], c[6];
2083 Int_t i, j, k, m, n;
2084 Double_t p, x[200], y[200], z;
2089 printf(
"1 TEST OF TSpline5 WITH NONEQUIDISTANT KNOTS\n");
2104 printf(
"\n-N = %3d M =%2d\n",n,m);
2105 TSpline5 *spline =
new TSpline5(
"Test",x,y,n);
2106 for (i = 0; i < n; ++i)
2107 spline->GetCoeff(i,hx, a[i],a[i+200],a[i+400],
2108 a[i+600],a[i+800],a[i+1000]);
2110 for (i = 0; i < mm1; ++i) diff[i] = com[i] = 0;
2111 for (k = 0; k < n; ++k) {
2112 for (i = 0; i < mm; ++i) c[i] = a[k+i*200];
2113 printf(
" ---------------------------------------%3d --------------------------------------------\n",k+1);
2114 printf(
"%12.8f\n",x[k]);
2116 printf(
"%16.8f\n",c[0]);
2118 for (i = 0; i < mm; ++i) printf(
"%16.8f",c[i]);
2120 for (i = 0; i < mm1; ++i)
2121 if ((z=TMath::Abs(a[k+i*200])) > com[i]) com[i] = z;
2123 for (i = 1; i < mm; ++i)
2124 for (jj = i; jj < mm; ++jj) {
2126 c[j-2] = c[j-1]*z+c[j-2];
2128 for (i = 0; i < mm; ++i) printf(
"%16.8f",c[i]);
2130 for (i = 0; i < mm1; ++i)
2131 if (!(k >= n-2 && i != 0))
2132 if((z = TMath::Abs(c[i]-a[k+1+i*200]))
2133 > diff[i]) diff[i] = z;
2136 printf(
" MAXIMUM ABSOLUTE VALUES OF DIFFERENCES \n");
2137 for (i = 0; i < mm1; ++i) printf(
"%18.9E",diff[i]);
2139 printf(
" MAXIMUM ABSOLUTE VALUES OF COEFFICIENTS \n");
2140 if (TMath::Abs(c[0]) > com[0])
2141 com[0] = TMath::Abs(c[0]);
2142 for (i = 0; i < mm1; ++i) printf(
"%16.8f",com[i]);
2145 for (n = 10; n <= 100; n += 10) {
2149 for (i = 0; i < nm1; i += 2) {
2159 printf(
"\n-N = %3d M =%2d\n",n,m);
2160 spline =
new TSpline5(
"Test",x,y,n);
2161 for (i = 0; i < n; ++i)
2162 spline->GetCoeff(i,hx,a[i],a[i+200],a[i+400],
2163 a[i+600],a[i+800],a[i+1000]);
2165 for (i = 0; i < mm1; ++i)
2166 diff[i] = com[i] = 0;
2167 for (k = 0; k < n; ++k) {
2168 for (i = 0; i < mm; ++i)
2171 printf(
" ---------------------------------------%3d --------------------------------------------\n",k+1);
2172 printf(
"%12.8f\n",x[k]);
2173 if (k == n-1) printf(
"%16.8f\n",c[0]);
2175 if (k == n-1)
break;
2177 for (i = 0; i < mm; ++i) printf(
"%16.8f",c[i]);
2180 for (i = 0; i < mm1; ++i)
2181 if ((z=TMath::Abs(a[k+i*200])) > com[i])
2184 for (i = 1; i < mm; ++i)
2185 for (jj = i; jj < mm; ++jj) {
2187 c[j-2] = c[j-1]*z+c[j-2];
2190 for (i = 0; i < mm; ++i) printf(
"%16.8f",c[i]);
2193 for (i = 0; i < mm1; ++i)
2194 if (!(k >= n-2 && i != 0))
2195 if ((z = TMath::Abs(c[i]-a[k+1+i*200]))
2196 > diff[i]) diff[i] = z;
2198 printf(
" MAXIMUM ABSOLUTE VALUES OF DIFFERENCES \n");
2199 for (i = 0; i < mm1; ++i) printf(
"%18.9E",diff[i]);
2201 printf(
" MAXIMUM ABSOLUTE VALUES OF COEFFICIENTS \n");
2202 if (TMath::Abs(c[0]) > com[0])
2203 com[0] = TMath::Abs(c[0]);
2204 for (i = 0; i < mm1; ++i) printf(
"%16.8E",com[i]);
2209 printf(
"1 TEST OF TSpline5 WITH NONEQUIDISTANT DOUBLE KNOTS\n");
2235 printf(
"-N = %3d M =%2d\n",n,m);
2236 spline =
new TSpline5(
"Test",x,y,nn);
2237 for (i = 0; i < nn; ++i)
2238 spline->GetCoeff(i,hx,a[i],a[i+200],a[i+400],
2239 a[i+600],a[i+800],a[i+1000]);
2241 for (i = 0; i < mm1; ++i)
2242 diff[i] = com[i] = 0;
2243 for (k = 0; k < nn; ++k) {
2244 for (i = 0; i < mm; ++i)
2246 printf(
" ---------------------------------------%3d --------------------------------------------\n",k+1);
2247 printf(
"%12.8f\n",x[k]);
2249 printf(
"%16.8f\n",c[0]);
2252 for (i = 0; i < mm; ++i) printf(
"%16.8f",c[i]);
2254 for (i = 0; i < mm1; ++i)
2255 if ((z=TMath::Abs(a[k+i*200])) > com[i]) com[i] = z;
2257 for (i = 1; i < mm; ++i)
2258 for (jj = i; jj < mm; ++jj) {
2260 c[j-2] = c[j-1]*z+c[j-2];
2262 for (i = 0; i < mm; ++i) printf(
"%16.8f",c[i]);
2264 for (i = 0; i < mm1; ++i)
2265 if (!(k >= nn-2 && i != 0))
2266 if ((z = TMath::Abs(c[i]-a[k+1+i*200]))
2267 > diff[i]) diff[i] = z;
2269 printf(
" MAXIMUM ABSOLUTE VALUES OF DIFFERENCES \n");
2270 for (i = 1; i <= mm1; ++i) {
2271 printf(
"%18.9E",diff[i-1]);
2274 if (TMath::Abs(c[0]) > com[0])
2275 com[0] = TMath::Abs(c[0]);
2276 printf(
" MAXIMUM ABSOLUTE VALUES OF COEFFICIENTS \n");
2277 for (i = 0; i < mm1; ++i) printf(
"%16.8f",com[i]);
2280 for (n = 10; n <= 100; n += 10) {
2285 for (i = 0; i < n; ++i) {
2286 p += TMath::Abs(TMath::Sin(i+1));
2289 y[(i << 1)] = TMath::Cos(i+1)-.5;
2290 y[(i << 1)+1] = TMath::Cos((i << 1)+2)-.5;
2292 printf(
"-N = %3d M =%2d\n",n,m);
2293 spline =
new TSpline5(
"Test",x,y,nn);
2294 for (i = 0; i < nn; ++i)
2295 spline->GetCoeff(i,hx,a[i],a[i+200],a[i+400],
2296 a[i+600],a[i+800],a[i+1000]);
2298 for (i = 0; i < mm1; ++i)
2299 diff[i] = com[i] = 0;
2300 for (k = 0; k < nn; ++k) {
2301 for (i = 0; i < mm; ++i)
2304 printf(
" ---------------------------------------%3d --------------------------------------------\n",k+1);
2305 printf(
"%12.8f\n",x[k]);
2306 if (k == nn-1) printf(
"%16.8f\n",c[0]);
2308 if (k == nn-1)
break;
2310 for (i = 0; i < mm; ++i) printf(
"%16.8f",c[i]);
2313 for (i = 0; i < mm1; ++i)
2314 if ((z=TMath::Abs(a[k+i*200])) > com[i]) com[i] = z;
2316 for (i = 1; i < mm; ++i) {
2317 for (jj = i; jj < mm; ++jj) {
2319 c[j-2] = c[j-1]*z+c[j-2];
2323 for (i = 0; i < mm; ++i) printf(
"%16.8f",c[i]);
2326 for (i = 0; i < mm1; ++i)
2327 if (!(k >= nn-2 && i != 0))
2328 if ((z = TMath::Abs(c[i]-a[k+1+i*200]))
2329 > diff[i]) diff[i] = z;
2331 printf(
" MAXIMUM ABSOLUTE VALUES OF DIFFERENCES \n");
2332 for (i = 0; i < mm1; ++i) printf(
"%18.9E",diff[i]);
2334 printf(
" MAXIMUM ABSOLUTE VALUES OF COEFFICIENTS \n");
2335 if (TMath::Abs(c[0]) > com[0])
2336 com[0] = TMath::Abs(c[0]);
2337 for (i = 0; i < mm1; ++i) printf(
"%18.9E",com[i]);
2343 printf(
"1 TEST OF TSpline5 WITH NONEQUIDISTANT KNOTS,\n");
2344 printf(
" ONE DOUBLE, ONE TRIPLE KNOT\n");
2365 printf(
"-N = %3d M =%2d\n",n,m);
2366 spline=
new TSpline5(
"Test",x,y,n);
2367 for (i = 0; i < n; ++i)
2368 spline->GetCoeff(i,hx,a[i],a[i+200],a[i+400],
2369 a[i+600],a[i+800],a[i+1000]);
2371 for (i = 0; i < mm1; ++i)
2372 diff[i] = com[i] = 0;
2373 for (k = 0; k < n; ++k) {
2374 for (i = 0; i < mm; ++i)
2376 printf(
" ---------------------------------------%3d --------------------------------------------\n",k+1);
2377 printf(
"%12.8f\n",x[k]);
2379 printf(
"%16.8f\n",c[0]);
2382 for (i = 0; i < mm; ++i) printf(
"%16.8f",c[i]);
2384 for (i = 0; i < mm1; ++i)
2385 if ((z=TMath::Abs(a[k+i*200])) > com[i]) com[i] = z;
2387 for (i = 1; i < mm; ++i)
2388 for (jj = i; jj < mm; ++jj) {
2390 c[j-2] = c[j-1]*z+c[j-2];
2392 for (i = 0; i < mm; ++i) printf(
"%16.8f",c[i]);
2394 for (i = 0; i < mm1; ++i)
2395 if (!(k >= n-2 && i != 0))
2396 if ((z = TMath::Abs(c[i]-a[k+1+i*200]))
2397 > diff[i]) diff[i] = z;
2399 printf(
" MAXIMUM ABSOLUTE VALUES OF DIFFERENCES \n");
2400 for (i = 0; i < mm1; ++i) printf(
"%18.9E",diff[i]);
2402 printf(
" MAXIMUM ABSOLUTE VALUES OF COEFFICIENTS \n");
2403 if (TMath::Abs(c[0]) > com[0])
2404 com[0] = TMath::Abs(c[0]);
2405 for (i = 0; i < mm1; ++i) printf(
"%16.8f",com[i]);
2410 printf(
"1 TEST OF TSpline5 WITH NONEQUIDISTANT KNOTS,\n");
2411 printf(
" TWO DOUBLE, ONE TRIPLE KNOT\n");
2436 printf(
"-N = %3d M =%2d\n",n,m);
2437 spline =
new TSpline5(
"Test",x,y,n);
2438 for (i = 0; i < n; ++i)
2439 spline->GetCoeff(i,hx,a[i],a[i+200],a[i+400],
2440 a[i+600],a[i+800],a[i+1000]);
2442 for (i = 0; i < mm1; ++i)
2443 diff[i] = com[i] = 0;
2444 for (k = 0; k < n; ++k) {
2445 for (i = 0; i < mm; ++i)
2447 printf(
" ---------------------------------------%3d --------------------------------------------\n",k+1);
2448 printf(
"%12.8f\n",x[k]);
2450 printf(
"%16.8f\n",c[0]);
2453 for (i = 0; i < mm; ++i) printf(
"%16.8f",c[i]);
2455 for (i = 0; i < mm1; ++i)
2456 if ((z=TMath::Abs(a[k+i*200])) > com[i]) com[i] = z;
2458 for (i = 1; i < mm; ++i)
2459 for (jj = i; jj < mm; ++jj) {
2461 c[j-2] = c[j-1]*z+c[j-2];
2463 for (i = 0; i < mm; ++i) printf(
"%16.8f",c[i]);
2465 for (i = 0; i < mm1; ++i)
2466 if (!(k >= n-2 && i != 0))
2467 if((z = TMath::Abs(c[i]-a[k+1+i*200]))
2468 > diff[i]) diff[i] = z;
2470 printf(
" MAXIMUM ABSOLUTE VALUES OF DIFFERENCES \n");
2471 for (i = 0; i < mm1; ++i) printf(
"%18.9E",diff[i]);
2473 printf(
" MAXIMUM ABSOLUTE VALUES OF COEFFICIENTS \n");
2474 if (TMath::Abs(c[0]) > com[0])
2475 com[0] = TMath::Abs(c[0]);
2476 for (i = 0; i < mm1; ++i) printf(
"%16.8f",com[i]);
2483 void TSpline5::Streamer(TBuffer &R__b)
2485 if (R__b.IsReading()) {
2487 Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
2489 R__b.ReadClassBuffer(TSpline5::Class(),
this, R__v, R__s, R__c);
2493 TSpline::Streamer(R__b);
2495 fPoly =
new TSplinePoly5[fNp];
2496 for(Int_t i=0; i<fNp; ++i) {
2497 fPoly[i].Streamer(R__b);
2502 R__b.WriteClassBuffer(TSpline5::Class(),
this);