source: Sophya/trunk/SophyaLib/NTools/poly.cc@ 2526

Last change on this file since 2526 was 2506, checked in by ansari, 22 years ago

Remplacement THROW par throw - Reza 15/03/2004

File size: 19.1 KB
Line 
1#include "machdefs.h"
2#include "poly.h"
3#include "linfit.h"
4#include "fioarr.h"
5
6////////////////////////////////////////////////////////////
7////////////////////////////////////////////////////////////
8////////////////////////////////////////////////////////////
9////////////////////////////////////////////////////////////
10////////////////////////////////////////////////////////////
11/*!
12 \class SOPHYA::Poly
13 \ingroup NTools
14 One dimensional polynomials class.
15*/
16
17//! Constructor
18/*! Create a 1D polynomial of degre \b degre */
19Poly::Poly(int degre)
20: TVector<r_8>(degre+1), dirty(0), deg(0)
21{
22}
23
24//! Constructor by copy
25Poly::Poly(Poly const& a)
26:TVector<r_8>(a), dirty(a.dirty), deg(a.deg)
27{
28}
29
30//! update degre
31/*! update degre (that could be changed after operations) */
32void Poly::UpdateDeg() const
33{
34 int i = NElts()-1;
35 while (Element(i) == 0 && i>0) i--;
36
37 (int&) deg = i; // bientot mutable dans ANSI C++
38 (int&) dirty = 0;
39}
40
41//! compute value P(\b x)
42double Poly::operator()(double x) const
43{
44 UpdateDegIfDirty();
45 double res = Element(deg);
46 for (int i=deg-1; i>=0; i--) {
47 res *= x;
48 res += Element(i);
49 }
50 return res;
51}
52
53//! Replace p(x) by its derivate
54void Poly::Derivate()
55{
56 UpdateDegIfDirty();
57 if (deg == 0) { Element(0) = 0; return;}
58 for (int i=1; i<=deg; i++)
59 Element(i-1) = Element(i)*i;
60 Element(deg) = 0;
61 deg--;
62}
63
64
65//! Return the derivate in \b der(x)
66void Poly::Derivate(Poly& der) const
67{
68 UpdateDegIfDirty();
69 der.Realloc(deg);
70// der.Zero(); // on sait que Realloc met a zero le reste.
71 for (int i=1; i<=deg; i++)
72 der.Element(i-1) = Element(i)*i;
73}
74
75
76//! Return the roots of the polynomial into \b roots
77/*!
78 This works until degre 2
79 \return the number of roots
80*/
81int Poly::Roots(TVector<r_8>& roots) const
82{
83 UpdateDegIfDirty();
84
85 switch (deg)
86 {
87 case 0 : // degre 0
88 return 0;
89 case 1 : // degre 1
90 roots.Realloc(1);
91 return Root1(roots(0));
92 case 2 : // degre 2
93 roots.Realloc(2);
94 return Root2(roots(0),roots(1));
95 default :
96 throw ParmError("Poly::Roots()") ;
97 }
98}
99
100
101//! Return root \b r for a degre 1 polynomial
102/*! \return return 1 if succes, 0 if not */
103int Poly::Root1(double& r) const
104{
105 UpdateDegIfDirty();
106 if (deg != 1) ParmError("Poly::Root1() deg!= 1") ;
107
108 if (Element(1) == 0) return 0;
109 r = -Element(0)/Element(1);
110 return 1;
111}
112
113//! Return roots \b r1 and \b r2 for a degre 2 polynomial
114/*! \return return the number of roots found */
115int Poly::Root2(double& r1, double& r2) const
116{
117 UpdateDegIfDirty();
118 if (deg != 2) throw SzMismatchError("Poly::Root2() deg != 2") ;
119
120 double delta = Element(1)*Element(1) - 4*Element(0)*Element(2);
121 if (delta < 0) return 0;
122 if (delta == 0) {
123 r1 = r2 = -Element(1)/2/Element(0);
124 return 1;
125 }
126 r1 = (-Element(1) - sqrt(delta))/2/Element(0);
127 r2 = (-Element(1) + sqrt(delta))/2/Element(0);
128 return 2;
129}
130
131//! Operator P(x) = a(x)
132Poly& Poly::operator = (Poly const& a)
133{
134 if (this == &a) return *this;
135 TVector<r_8>::operator=(a);
136
137 UpdateDeg();
138 return *this;
139}
140
141//! Perform P(x) += b(x)
142Poly& Poly::operator += (Poly const& b)
143{
144 UpdateDegIfDirty();
145 b.UpdateDegIfDirty();
146
147 if (b.deg > deg) Realloc(b.deg);
148
149 int n = (deg > b.deg) ? deg : b.deg;
150 for (int i=0; i<=n; i++) Element(i) += b.Element(i);
151
152 UpdateDeg();
153 return *this;
154}
155
156//! Perform P(x) -= b(x)
157Poly& Poly::operator -= (Poly const& b)
158{
159 UpdateDegIfDirty();
160 b.UpdateDegIfDirty();
161
162 if (b.deg > deg) Realloc(b.deg);
163
164 int n = (deg > b.deg) ? deg : b.deg;
165 for (int i=0; i<=n; i++) Element(i) -= b.Element(i);
166
167 UpdateDeg();
168 return *this;
169}
170
171//! Perform P(x) *= b(x)
172Poly& Poly::operator *= (double a)
173{
174 UpdateDegIfDirty();
175 for (int i=0; i<=deg; i++) Element(i) *= a;
176 return *this;
177}
178
179//! Return P(x) = *this(x) * b(x)
180Poly Poly::Mult(Poly const& b) const
181{
182Poly c(deg + b.deg);
183 UpdateDegIfDirty();
184 b.UpdateDegIfDirty();
185
186 c.deg = deg + b.deg;
187
188 for (int i=0; i<=c.deg; i++) {
189 c[i] = 0;
190 int kmin = (i <= deg) ? 0 : i - deg;
191 int kmax = (i <= deg) ? i : deg;
192 for (int k=kmin; k<=kmax; k++)
193 c[i] += (*this)[k] * b[i-k];
194 }
195return c;
196}
197
198//! Print on stream \b s
199void Poly::Print(ostream& s, sa_size_t , bool, bool ) const
200{
201 UpdateDegIfDirty();
202 int nz=0;
203 for (int i = deg; i>=0; i--) {
204 if ((*this)[i] != 0) {
205 nz = 1;
206 if (i < deg && (*this)[i] > 0) s << "+";
207 s << (*this)[i];
208 if (i == 1) s << "*X ";
209 if (i > 1) s << "*X^" << i << " ";
210 }
211 }
212 if (!nz) s << " 0 ";
213}
214
215//! Fit datas by a polynomial
216/*!
217 Fit y(x) by a polynimial P(x)
218 \param x : x datas
219 \param y : y datas
220 \param degre : degre of the polynomial P(x) to be fitted
221 \warning result is stored in the current object
222 \return return chisquare
223*/
224double Poly::Fit(TVector<r_8> const& x, TVector<r_8> const& y, int degre)
225{
226 int n = x.NElts();
227 if (n != (int)y.NElts()) throw SzMismatchError("Poly::Fit() ");
228
229 Realloc(degre);
230
231 TMatrix<r_8> a(degre+1, n);
232
233 for (int c=0; c<n; c++) {
234 double xpow = 1.0;
235 for (int l=0; l<=degre; l++) {
236 a(l,c) = xpow;
237 xpow *= x(c);
238 }
239 }
240
241 LinFitter<r_8> lf;
242 double rc = lf.LinFit(a,y,(TVector<r_8>&)*this);
243 UpdateDeg();
244 return rc;
245}
246
247//! Fit datas with errors by a polynomial
248/*!
249 Fit y(x) by a polynimial P(x)
250 \param x : x datas
251 \param y : y datas
252 \param erry2 : errors squared on y
253 \param degre : degre of the polynomial P(x) to be fitted
254 \warning result is stored in the current object
255 \return \b errcoeff : errors on the coefficients
256 \return return chisquare
257*/
258double Poly::Fit(TVector<r_8> const& x, TVector<r_8> const& y,
259 TVector<r_8> const& erry2, int degre,TVector<r_8>& errCoef)
260{
261 int n = x.NElts();
262 if (n != (int)y.NElts()) throw SzMismatchError("Poly::Fit() ");
263 if (n != (int)erry2.NElts()) throw SzMismatchError("Poly::Fit() ") ;
264
265 Realloc(degre);
266 errCoef.Realloc(degre+1);
267
268 TMatrix<r_8> a(degre+1, n);
269
270 for (int c=0; c<n; c++) {
271 double xpow = 1.0;
272 for (int l=0; l<=degre; l++) {
273 a(l,c) = xpow;
274 xpow *= x(c);
275 }
276 }
277
278 LinFitter<r_8> lf;
279 double rc = lf.LinFit(a,y,erry2,(TVector<r_8>&)*this,errCoef);
280 UpdateDeg();
281 return rc;
282}
283
284
285//! Return the polynomial at power \b n : ( \f$ P(x)^n \f$ )
286Poly Poly::power(int n) const // a accelerer !!!
287{
288 if (n < 0) throw RangeCheckError("Poly::power() n<0 ");
289 if (n == 0) { Poly r(0); r[0] = 1; return r;}
290 if (n == 1) { return *this; }
291 return *this * power(n-1);
292}
293
294//! Substitue polynomial and return P\f$ (b(x)) \f$
295Poly Poly::operator() (Poly const& b) const
296{
297 Poly c(b.Degre()*Degre());
298 for (int i=0; i<= Degre(); i++)
299 c += (*this)[i] * b.power(i);
300 return c;
301}
302
303
304//////////////////////////////////////////////////////////////////////////
305//! For persistance management
306DECL_TEMP_SPEC /* equivalent a template <> , pour SGI-CC en particulier */
307void ObjFileIO<Poly>::ReadSelf(PInPersist& is)
308{
309if(dobj==NULL) dobj=new Poly;
310int_4 dg;
311is >> dg;
312dobj->Realloc(dg,true);
313is >> *((TVector<r_8> *) dobj);
314dobj->UpdateDeg();
315}
316
317//! For persistance management
318DECL_TEMP_SPEC /* equivalent a template <> , pour SGI-CC en particulier */
319void ObjFileIO<Poly>::WriteSelf(POutPersist& os) const
320{
321if(dobj == NULL) return;
322dobj->UpdateDegIfDirty();
323dobj->Realloc(dobj->deg,true);
324os << dobj->deg;
325os << *((TVector<r_8> *) dobj);
326}
327
328//////////////////////////////////////////////////////////////////////////
329/*! \ingroup NTools
330 \fn binomial(int,int)
331 Return the binomial coefficient \f$ {C_n}^p \f$.
332*/
333int binomial(int n, int p)
334{
335 int c = 1;
336 for (int i=n-p+1; i<=n; i++) c *= i;
337 for (int j=2; j<=p; j++) c /= j;
338 return c;
339}
340
341
342////////////////////////////////////////////////////////////
343////////////////////////////////////////////////////////////
344////////////////////////////////////////////////////////////
345////////////////////////////////////////////////////////////
346////////////////////////////////////////////////////////////
347/*!
348 \class SOPHYA::Poly2
349 \ingroup NTools
350 Two dimensional polynomials class.
351*/
352
353//! Constructor of 2D polynomial of degres \b degreX \b degreY
354Poly2::Poly2(int degreX, int degreY)
355:TVector<r_8>((degreX+1)*(degreY+1)), dirty(0),
356 maxDegX(degreX), maxDegY(degreY), degX(0), degY(0), deg(0)
357{
358}
359
360//! Constructor of 2D polynomial \f$ P(x,y) = px(x) * py(y) \f$
361Poly2::Poly2(Poly const& polX, Poly const& polY)
362:TVector<r_8>((polX.Degre()+1)*(polY.Degre()+1)), dirty(0),
363 maxDegX(polX.Degre()), maxDegY(polY.Degre()),
364 degX(polX.Degre()), degY(polY.Degre()), deg(degX+degY)
365{
366 for (int i=0; i<=degX; i++)
367 for (int j=0; j<=degY; j++)
368 Coef(i,j) = polX[i]*polY[j];
369}
370
371//! Constructor by copy
372Poly2::Poly2(Poly2 const& a)
373:TVector<r_8>(a), dirty(a.dirty),
374 maxDegX(a.maxDegX), maxDegY(a.maxDegY),
375 degX(a.degX), degY(a.degY), deg(a.deg)
376{
377}
378
379//! Operator P(x) = a(x)
380Poly2& Poly2::operator = (Poly2 const& a)
381{
382 if (this == &a) return *this;
383 if (maxDegX < a.DegX() || maxDegY < a.DegY())
384 Realloc(a.DegX(), a.DegY());
385
386
387 for (int i=0; i<= maxDegX; i++)
388 for (int j=0; j<= maxDegY; j++)
389 Coef(i,j) = a.Coef(i,j);
390
391 UpdateDeg();
392 return *this;
393}
394
395//! Re-allocate space for 2D polynomial with partial degres \b degreX \b degreY
396void Poly2::Realloc(int degreX, int degreY)
397{
398 UpdateDegIfDirty();
399 Poly2 tmp(*this);
400 TVector<r_8>::Realloc((degreX+1)*(degreY+1));
401 DataBlock().Reset();
402 maxDegX = degreX;
403 maxDegY = degreY;
404
405// Attention - Reza 30/09/99
406// il faut prendre le min en degre du polynome de depart et le nouveau
407 int cdegx = (tmp.degX < degreX) ? tmp.degX : degreX;
408 int cdegy = (tmp.degY < degreY) ? tmp.degY : degreY;
409 for (int i=0; i<= cdegx; i++)
410 for (int j=0; j<= cdegy; j++)
411 Coef(i,j) = tmp.Coef(i,j);
412}
413
414
415//! update degres
416/*! update degres (that could be changed after operations) */
417void Poly2::UpdateDeg() const
418{
419 (int&)degX=(int&)degY=(int&)deg=0;
420
421 for (int dx=0; dx<=maxDegX; dx++)
422 for (int dy=0; dy<=maxDegY; dy++)
423 if (Coef(dx,dy) != 0) {
424 if (dx > degX) (int&)degX = dx;
425 if (dy > degY) (int&)degY = dy;
426 if (dx+dy > deg) (int&)deg = dx+dy;
427 }
428
429 (int&)dirty = 0;
430}
431
432//! Return P(\b x, \b y)
433double Poly2::operator()(double x, double y) const
434{
435 UpdateDegIfDirty();
436 double res = 0;
437 double xPow = 1;
438 for (int dx=0; dx<=maxDegX; dx++) {
439 double yPow = 1;
440 for (int dy=0; dy<=maxDegY; dy++) {
441 res += Coef(dx,dy) * xPow * yPow;
442 yPow *= y;
443 }
444 xPow *= x;
445 }
446 return res;
447}
448
449//! Fit datas by a polynomial
450/*!
451 Fit z(x,y) by a polynimial P(x,y)
452 \param x : x datas
453 \param y : y datas
454 \param z : z datas
455 \param degreX : partial degre on X
456 \param degreY : partial degre on Y
457 \warning result is stored in the current object
458 \return return chisquare
459*/
460double Poly2::Fit(TVector<r_8> const& x, TVector<r_8> const& y,
461 TVector<r_8> const& z, int degreX, int degreY)
462{
463 int n = x.NElts();
464 if (n != (int)y.NElts()) throw SzMismatchError("Poly2::Fit() - 1");
465 if (n != (int)z.NElts()) throw SzMismatchError("Poly2::Fit() - 2");
466
467 Realloc(degreX, degreY);
468
469 TMatrix<r_8> a((degreX+1)*(degreY+1), n);
470
471 for (int c=0; c<n; c++) {
472 double xPow = 1.0;
473 for (int dx = 0; dx <= degreX; dx++) {
474 double yPow = 1.0;
475 for (int dy = 0; dy <= degreY; dy++) {
476 a(IndCoef(dx,dy), c) = xPow*yPow;
477 yPow *= y(c);
478 }
479 xPow *= x(c);
480 }
481 }
482
483 LinFitter<r_8> lf;
484 double rc = lf.LinFit(a,z,(TVector<r_8>&)*this);
485 UpdateDeg();
486 return rc;
487}
488
489//! Fit datas with errors by a polynomial
490/*!
491 Fit z(x,y) by a polynimial P(x,y)
492 \param x : x datas
493 \param y : y datas
494 \param z : z datas
495 \param errz2 : errors squared on z
496 \param degreX : partial degre on X
497 \param degreY : partial degre on Y
498 \warning result is stored in the current object
499 \return \b errcoeff : errors on the coefficients
500 \return return chisquare
501*/
502double Poly2::Fit(TVector<r_8> const& x, TVector<r_8> const& y, TVector<r_8> const& z,
503 TVector<r_8> const& errz2, int degreX, int degreY,
504 TVector<r_8>& errCoef)
505{
506 int n = x.NElts();
507 if (n != (int)y.NElts()) throw SzMismatchError("Poly2::Fit() - 3");
508 if (n != (int)z.NElts()) throw SzMismatchError("Poly2::Fit() - 4");
509 if (n != (int)errz2.NElts()) throw SzMismatchError("Poly2::Fit() - 5");
510
511 Realloc(degreX, degreY);
512 errCoef.Realloc((degreX+1)*(degreY+1));
513
514 TMatrix<r_8> a((degreX+1)*(degreY+1), n);
515
516 for (int c=0; c<n; c++) {
517 double xPow = 1.0;
518 for (int dx = 0; dx <= degreX; dx++) {
519 double yPow = 1.0;
520 for (int dy = 0; dy <= degreY; dy++) {
521 a(IndCoef(dx,dy), c) = xPow*yPow;
522 yPow *= y(c);
523 }
524 xPow *= x(c);
525 }
526 }
527
528 LinFitter<r_8> lf;
529 double rc = lf.LinFit(a,z,errz2,(TVector<r_8>&)*this,errCoef);
530 UpdateDeg();
531 return rc;
532}
533
534//! Fit datas by a polynomial
535/*!
536 Fit z(x,y) by a polynimial P(x,y)
537 \param x : x datas
538 \param y : y datas
539 \param z : z datas
540 \param degre : total degre
541 \warning result is stored in the current object
542 \return return chisquare
543*/
544double Poly2::Fit(TVector<r_8> const& x, TVector<r_8> const& y,
545 TVector<r_8> const& z, int degre)
546{
547 int n = x.NElts();
548 if (n != (int)y.NElts()) throw SzMismatchError("Poly2::Fit() - 6");
549 if (n != (int)z.NElts()) throw SzMismatchError("Poly2::Fit() - 7");
550
551 Realloc(degre, degre); // certains vaudront 0, impose.
552
553 TMatrix<r_8> a((degre+1)*(degre+2)/2, n);
554 TVector<r_8> cf((degre+1)*(degre+2)/2);
555#define C_INDEX(i,j) ((i) + (j)*(2*degre+3-(j))/2)
556
557 for (int c=0; c<n; c++) {
558 double xPow = 1.0;
559 for (int dx = 0; dx <= degre; dx++) {
560 double yPow = 1.0;
561 for (int dy = 0; dy <= degre; dy++) {
562 if (dy+dx <= degre)
563 a(C_INDEX(dx,dy), c) = xPow*yPow;
564 yPow *= y(c);
565 }
566 xPow *= x(c);
567 }
568 }
569
570 LinFitter<r_8> lf;
571 double rc = lf.LinFit(a,z,cf);
572
573 for (int dx = 0; dx <= degre; dx++)
574 for (int dy = 0; dy <= degre; dy++)
575 if (dx+dy <= degre)
576 Coef(dx,dy) = cf(C_INDEX(dx,dy));
577 else
578 Coef(dx,dy) = 0;
579
580 UpdateDeg();
581 return rc;
582}
583
584//! Fit datas with errors by a polynomial
585/*!
586 Fit z(x,y) by a polynimial P(x,y)
587 \param x : x datas
588 \param y : y datas
589 \param z : z datas
590 \param errz2 : errors squared on z
591 \param degre : total degre
592 \warning result is stored in the current object
593 \return \b errcoeff : errors on the coefficients
594 \return return chisquare
595*/
596double Poly2::Fit(TVector<r_8> const& x, TVector<r_8> const& y,
597 TVector<r_8> const& z,TVector<r_8> const& errz2,
598 int degre, TVector<r_8>& errCoef)
599{
600 int n = x.NElts();
601 if (n != (int)y.NElts()) throw SzMismatchError("Poly2::Fit() - 8");
602 if (n != (int)z.NElts()) throw SzMismatchError("Poly2::Fit() - 9");
603 if (n != (int)errz2.NElts()) throw SzMismatchError("Poly2::Fit() - 10");
604
605 Realloc(degre, degre);
606 errCoef.Realloc((degre+1)*(degre+1));
607#define C_INDEX(i,j) ((i) + (j)*(2*degre+3-(j))/2)
608
609 TMatrix<r_8> a((degre+1)*(degre+2)/2, n);
610 TVector<r_8> cf((degre+1)*(degre+2)/2);
611 TVector<r_8> ecf((degre+1)*(degre+2)/2);
612
613 for (int c=0; c<n; c++) {
614 double xPow = 1.0;
615 for (int dx = 0; dx <= degre; dx++) {
616 double yPow = 1.0;
617 for (int dy = 0; dy <= degre; dy++) {
618 if (dy+dx <= degre)
619 a(C_INDEX(dx,dy), c) = xPow*yPow;
620 yPow *= y(c);
621 }
622 xPow *= x(c);
623 }
624 }
625
626 LinFitter<r_8> lf;
627 double rc = lf.LinFit(a,z,errz2,cf,ecf);
628
629
630 for (int dx = 0; dx <= degre; dx++)
631 for (int dy = 0; dy <= degre; dy++)
632 if (dx+dy <= degre) {
633 Coef(dx,dy) = cf(C_INDEX(dx,dy));
634 errCoef(IndCoef(dx,dy)) = ecf(C_INDEX(dx,dy));
635 } else {
636 Coef(dx,dy) = 0;
637 errCoef(IndCoef(dx,dy)) = 0;
638 }
639 UpdateDeg();
640 return rc;
641}
642
643//! Print on stream \b s
644void Poly2::Print(ostream& s, sa_size_t , bool, bool ) const
645{
646 UpdateDegIfDirty();
647 int nz=0;
648 int notfirst=0;
649 for (int dx = degX; dx>=0; dx--)
650 for (int dy= degY; dy>=0; dy--) {
651 double c = Coef(dx,dy);
652 if (c != 0) {
653 nz = 1;
654 if (notfirst && c > 0) {
655 s << "+";
656 notfirst = 1;
657 }
658 s << c << " ";
659 if (dx == 1) s << "* X ";
660 if (dx > 1) s << "* X^" << dx << " ";
661 if (dy == 1) s << "* Y ";
662 if (dy > 1) s << "* Y^" << dy << " ";
663 s << endl;
664 }
665 }
666 if (!nz) s << " 0 ";
667}
668
669//! Operator: return P(x) = *this(x) + b(x)
670Poly2& Poly2::operator += (Poly2 const& b)
671{
672 if (maxDegX < b.DegX() || maxDegY < b.DegY())
673 Realloc(b.DegX(),b.DegY());
674
675 UpdateDegIfDirty();
676
677 int mx = b.DegX();
678 int my = b.DegY();
679 for (int i=0; i<= mx; i++)
680 for (int j=0; j<= my; j++)
681 Coef(i,j) += b.Coef(i,j);
682
683 UpdateDeg();
684 return *this;
685}
686
687//! Operator: return P(x) = *this(x) - b(x)
688Poly2& Poly2::operator -= (Poly2 const& b)
689{
690 if (maxDegX < b.DegX() || maxDegY < b.DegY())
691 Realloc(b.DegX(),b.DegY());
692
693 UpdateDegIfDirty();
694
695 int mx = b.DegX();
696 int my = b.DegY();
697 for (int i=0; i<= mx; i++)
698 for (int j=0; j<= my; j++)
699 Coef(i,j) -= b.Coef(i,j);
700
701 UpdateDeg();
702 return *this;
703}
704
705//! Operator: return P(x) = *this(x) * a
706Poly2& Poly2::operator *= (double a)
707{
708 for (uint_4 i=0; i<NElts(); i++) Element(i) *= a;
709 return *this;
710}
711
712//! Operator: return P(x) = *this(x) * b(x)
713Poly2 Poly2::Mult(Poly2 const& b) const
714{
715 Poly2 c(DegX() + b.DegX(), DegY() + b.DegY());
716 UpdateDegIfDirty();
717 b.UpdateDegIfDirty();
718
719 for (int i=0; i<=DegX(); i++)
720 for (int j=0; j<=DegY(); j++)
721 for (int k=0; k<=b.DegX(); k++)
722 for (int l=0; l<=b.DegY(); l++)
723 c.Coef(i+k,j+l) += Coef(i,j)*b.Coef(k,l);
724 return c;
725}
726
727//! Return \f$ P(x,y)^n \f$
728Poly2 Poly2::power(int n) const
729{
730 if (n < 0) throw RangeCheckError("Poly2::power(n<0) ");
731 if (n == 0) { Poly2 r(0); r.Coef(0,0) = 1; return r;}
732 if (n == 1) { return *this; }
733 return *this * power(n-1);
734}
735
736
737//! substitute and return \f$ P(a(x),b(x)) \f$
738Poly2 Poly2::operator() (Poly const& a, Poly const& b) const
739{
740 UpdateDegIfDirty();
741 Poly2 c(maxDegX*a.Degre(), maxDegY*b.Degre());
742
743 for (int i=0; i<= degX; i++)
744 for (int j=0; j<= degY; j++) {
745 Poly2 d(a.power(i), b.power(j));
746 c += Coef(i,j) * d;
747 }
748
749 return c;
750}
751
752//! substitute and return 2D polynomial \f$ P(a(x,y)) \f$, P is a 1D polynomial
753Poly2 Poly::operator() (Poly2 const& a) const
754{
755 Poly2 c(a.MaxDegX()*Degre(), a.MaxDegY()*Degre());
756
757 for (int i=0; i<= Degre(); i++)
758 c += (*this)[i] * a.power(i);
759 return c;
760}
761
762//////////////////////////////////////////////////////////////////////////
763//! For persistance management
764DECL_TEMP_SPEC /* equivalent a template <> , pour SGI-CC en particulier */
765void ObjFileIO<Poly2>::ReadSelf(PInPersist& is)
766{
767if(dobj==NULL) dobj=new Poly2;
768int_4 dgx, dgy;
769is >> dgx >> dgy;
770dobj->Realloc(dgx,dgy);
771is >> *((TVector<r_8> *) dobj);
772dobj->UpdateDeg();
773}
774
775//! For persistance management
776DECL_TEMP_SPEC /* equivalent a template <> , pour SGI-CC en particulier */
777void ObjFileIO<Poly2>::WriteSelf(POutPersist& os) const
778{
779if(dobj == NULL) return;
780os << dobj->maxDegX << dobj->maxDegY;
781os << *((TVector<r_8> *) dobj);
782}
783
784
785//////////////////////////////////////////////////////////////////////////
786#ifdef __CXX_PRAGMA_TEMPLATES__
787#pragma define_template ObjFileIO<Poly>
788#pragma define_template ObjFileIO<Poly2>
789#endif
790
791#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
792template class ObjFileIO<Poly>;
793template class ObjFileIO<Poly2>;
794#endif
Note: See TracBrowser for help on using the repository browser.