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

Last change on this file since 2683 was 2615, checked in by cmv, 21 years ago

using namespace sophya enleve de machdefs.h, nouveau sopnamsp.h cmv 10/09/2004

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