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

Last change on this file since 3712 was 3572, checked in by cmv, 17 years ago

char* -> const char* pour regler les problemes de deprecated string const... + comparaison unsigned signed + suppression EVOL_PLANCK rz+cmv 07/02/2009

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