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

Last change on this file since 3235 was 3235, checked in by ansari, 18 years ago

suppression include sopnamsp.h et mis la declaration namespace SOPHYA ds les fichiers .cc de NTools, quand DECL_TEMP_SPEC ds le fichier , cmv+reza 27/04/2007

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 (uint_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.