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

Last change on this file since 262 was 244, checked in by ansari, 26 years ago

beaucoup modifs rz+cmv 22/4/99

File size: 18.1 KB
Line 
1#include "machdefs.h"
2#include "poly.h"
3#include "linfit.h"
4
5//++
6// Class Poly
7// Lib Outils++
8// include poly.h
9//
10// Classe de calcul sur polynômes à une variable.
11//--
12
13//++
14// Links Parents
15// Vector
16//--
17
18//++
19// Titre Constructeurs
20//--
21
22
23//++
24// Poly::Poly(int degre=0)
25//
26// Crée un nouveau polynôme, en allouant de la place pour
27// le degré spécifié.
28//--
29
30Poly::Poly(int degre)
31: Vector(degre+1), dirty(0), deg(0)
32{
33 END_CONSTRUCTOR
34}
35
36
37void Poly::UpdateDeg() const
38{
39 int i = nalloc-1;
40 while (data[i] == 0 && i>0) i--;
41
42 (int&) deg = i; // bientot mutable dans ANSI C++
43 (int&) dirty = 0;
44}
45
46//++
47// Titre Méthodes
48//--
49
50//++
51// double& Poly::operator[](int i)
52// Permet d'accéder au coefficient de degré i (avec version
53// const).
54//--
55
56//++
57double Poly::operator()(double x) const
58//
59// Calcule la valeur du polynôme au point x.
60//--
61{
62 UpdateDegIfDirty();
63 double res = data[deg];
64 for (int i=deg-1; i>=0; i--) {
65 res *= x;
66 res += data[i];
67 }
68 return res;
69}
70
71//++
72void Poly::Derivate()
73//
74// Remplace le polynôme par le polynôme dérivé.
75//--
76{
77 UpdateDegIfDirty();
78 if (deg == 0) { data[0] = 0; return;}
79 for (int i=1; i<=deg; i++)
80 data[i-1] = data[i]*i;
81 data[deg] = 0;
82 deg--;
83}
84
85
86//++
87void Poly::Derivate(Poly& der) const
88//
89// Retourne dans der le polynôme dérivé.
90//--
91{
92 UpdateDegIfDirty();
93 der.Realloc(deg);
94// der.Zero(); // on sait que Realloc met a zero le reste.
95 for (int i=1; i<=deg; i++)
96 der.data[i-1] = data[i]*i;
97}
98
99
100//++
101int Poly::Roots(Vector& roots) const
102//
103// Retourne dans roots les racines réelles, si on sait
104// les calculer. Retourne le nombre de racines.
105//--
106{
107 UpdateDegIfDirty();
108
109 switch (deg)
110 {
111 case 0 : // degre 0
112 return 0;
113 case 1 : // degre 1
114 roots.Realloc(1);
115 return Root1(roots(0));
116 case 2 : // degre 2
117 roots.Realloc(2);
118 return Root2(roots(0),roots(1));
119 default :
120 THROW(parmErr);
121 }
122}
123
124
125//++
126int Poly::Root1(double& r) const
127//
128// Seulement si le polynôme est de degré 1: retourne
129// la racine dans "r". Retourne 1 (nombre de racines).
130//--
131{
132 UpdateDegIfDirty();
133 if (deg != 1) THROW(sizeMismatchErr);
134
135 if (data[1] == 0) return 0;
136 r = -data[0]/data[1];
137 return 1;
138}
139
140//++
141int Poly::Root2(double& r1, double& r2) const
142//
143// Seulement si le polynôme est de degre 2: retourne
144// les racines dans "r1" et "r2". Retourne 0, 1 ou 2
145// (nombre de racines).
146//--
147{
148 UpdateDegIfDirty();
149 if (deg != 2) THROW(sizeMismatchErr);
150
151 double delta = data[1]*data[1] - 4*data[0]*data[2];
152 if (delta < 0) return 0;
153 if (delta == 0) {
154 r1 = r2 = -data[1]/2/data[0];
155 return 1;
156 }
157 r1 = (-data[1] - sqrt(delta))/2/data[0];
158 r2 = (-data[1] + sqrt(delta))/2/data[0];
159 return 2;
160}
161
162//++
163Poly& Poly::operator = (Poly const& a)
164//
165// Opérateur d'affectation.
166//--
167{
168 if (this == &a) return *this;
169 Vector::operator=(a);
170
171 UpdateDeg();
172 return *this;
173}
174
175//++
176// Titres Opérations sur polynômes
177//--
178
179//++
180Poly& Poly::operator += (Poly const& b)
181//
182//--
183{
184 UpdateDegIfDirty();
185 b.UpdateDegIfDirty();
186
187 if (b.deg > deg)
188 Realloc(b.deg);
189
190 int n = (deg > b.deg) ? deg : b.deg;
191 for (int i=0; i<=n; i++)
192 data[i] += b.data[i];
193
194 UpdateDeg();
195 return *this;
196}
197
198//++
199Poly& Poly::operator -= (Poly const& b)
200//
201//--
202{
203 UpdateDegIfDirty();
204 b.UpdateDegIfDirty();
205
206 if (b.deg > deg)
207 Realloc(b.deg);
208
209 int n = (deg > b.deg) ? deg : b.deg;
210 for (int i=0; i<=n; i++)
211 data[i] -= b.data[i];
212
213 UpdateDeg();
214 return *this;
215}
216
217
218//++
219Poly operator+ (Poly const& a, Poly const& b)
220//
221//--
222#if HAS_NAMED_RETURN
223 return c((a.deg > b.deg)?(a.deg+1):(b.deg+1))
224#endif
225{
226#if !HAS_NAMED_RETURN
227Poly c((a.deg > b.deg)?(a.deg+1):(b.deg+1));
228#endif
229 c = a;
230 c += b;
231#if !HAS_NAMED_RETURN
232return c;
233#endif
234}
235
236//++
237Poly operator- (Poly const& a, Poly const& b)
238//
239//--
240#if HAS_NAMED_RETURN
241 return c((a.deg > b.deg)?(a.deg+1):(b.deg+1))
242#endif
243{
244#if !HAS_NAMED_RETURN
245Poly c((a.deg > b.deg)?(a.deg+1):(b.deg+1));
246#endif
247 c = a;
248 c -= b;
249#if !HAS_NAMED_RETURN
250return c;
251#endif
252}
253
254//++
255Poly operator* (Poly const& a, Poly const& b)
256//
257//--
258//#if HAS_NAMED_RETURN
259// return c(a.deg + b.deg)
260//#endif
261{
262//#if !HAS_NAMED_RETURN
263Poly c(a.deg + b.deg);
264//#endif
265 a.UpdateDegIfDirty();
266 b.UpdateDegIfDirty();
267
268 c.deg = a.deg + b.deg;
269
270 for (int i=0; i<=c.deg; i++) {
271 c[i] = 0;
272 int kmin = (i <= a.deg) ? 0 : i - a.deg;
273 int kmax = (i <= a.deg) ? i : a.deg;
274 for (int k=kmin; k<=kmax; k++)
275 c[i] += a[k] * b[i-k];
276 }
277//#if !HAS_NAMED_RETURN
278return c;
279//#endif
280}
281
282//++
283Poly& Poly::operator *= (double a)
284//
285//--
286{
287 UpdateDegIfDirty();
288
289 for (int i=0; i<=deg; i++)
290 data[i] *= a;
291
292 return *this;
293}
294
295
296//++
297Poly operator* (double a, Poly const& b)
298//
299//--
300#if HAS_NAMED_RETURN
301 return c(b)
302#endif
303{
304#if !HAS_NAMED_RETURN
305 Poly c(b);
306#endif
307
308 c *= a;
309
310#if !HAS_NAMED_RETURN
311 return c;
312#endif
313}
314
315
316void Poly::ReadSelf(PInPersist& s)
317{
318 int_4 dg;
319 s >> dg;
320 Realloc(dg, true);
321
322#ifdef DEBUG
323 int r = nr; int c = nc;
324#endif
325
326 Vector::ReadSelf(s);
327
328#ifdef DEBUG
329 DBASSERT(r == nr && c == nc);
330#endif
331 UpdateDeg();
332
333 #ifdef DEBUG
334 DBASSERT(dg == deg);
335 #endif
336}
337
338void Poly::WriteSelf(POutPersist& s) const
339{
340 UpdateDegIfDirty();
341 ((Poly*)(this))->Realloc(deg, true);
342 s << deg;
343 Vector::WriteSelf(s);
344}
345
346//++
347void Poly::Print(ostream& s) const
348//
349// Impresssion.
350//--
351{
352 UpdateDegIfDirty();
353 int nz=0;
354 for (int i = deg; i>=0; i--) {
355 if ((*this)[i] != 0) {
356 nz = 1;
357 if (i < deg && (*this)[i] > 0) s << "+";
358 s << (*this)[i];
359 if (i == 1) s << "*X ";
360 if (i > 1) s << "*X^" << i << " ";
361 }
362 }
363 if (!nz) s << " 0 ";
364}
365
366//++
367ostream& operator << (ostream& s, const Poly& a)
368//
369// Impressions sur le stream "s".
370//--
371{
372 a.Print(s);
373 return s;
374}
375
376//++
377double Poly::Fit(Vector const& x, Vector const& y, int degre)
378//
379// Ajustement polynomial par moindre carrés. Un polynôme de
380// degré "degre" est ajusté sur les données "x" et "y", et stocké dans
381// l'objet courant. Retourne le chi2.
382//--
383{
384 int n = x.NElts();
385 if (n != y.NElts()) THROW(sizeMismatchErr);
386
387 Realloc(degre);
388
389 Matrix a(degre+1, n);
390
391 for (int c=0; c<n; c++) {
392 double xpow = 1.0;
393 for (int l=0; l<=degre; l++) {
394 a(l,c) = xpow;
395 xpow *= x(c);
396 }
397 }
398
399 double rc = LinFit(a,y,(Vector&)*this);
400 UpdateDeg();
401 return rc;
402}
403
404//++
405double Poly::Fit(Vector const& x, Vector const& y, Vector const& erry2, int degre,
406 Vector& errCoef)
407//
408// Ajustement polynomial par moindre carrés. Un polynôme de
409// degré est ajusté sur les données x et y, et stocké dans
410// l'objet courant. erry2 contient le carre des erreurs sur y.
411// Retourne le chi2.
412//--
413{
414 int n = x.NElts();
415 if (n != y.NElts()) THROW(sizeMismatchErr);
416 if (n != erry2.NElts()) THROW(sizeMismatchErr);
417
418 Realloc(degre);
419 errCoef.Realloc(degre+1);
420
421 Matrix a(degre+1, n);
422
423 for (int c=0; c<n; c++) {
424 double xpow = 1.0;
425 for (int l=0; l<=degre; l++) {
426 a(l,c) = xpow;
427 xpow *= x(c);
428 }
429 }
430
431 double rc = LinFit(a,y,erry2,(Vector&)*this,errCoef);
432 UpdateDeg();
433 return rc;
434}
435
436int binomial(int n, int p)
437{
438 int c = 1;
439 for (int i=n-p+1; i<=n; i++) c *= i;
440 for (int j=2; j<=p; j++) c /= j;
441 return c;
442}
443
444
445//++
446// Poly Poly::power(int n) const
447//
448// Retourne le polynôme à la puissance n
449//--
450
451Poly Poly::power(int n) const // a accelerer !!!
452{
453 if (n < 0) THROW(rangeCheckErr);
454 if (n == 0) { Poly r(0); r[0] = 1; return r;}
455 if (n == 1) { return *this; }
456 return *this * power(n-1);
457}
458
459//++
460Poly Poly::operator() (Poly const& b) const
461//
462// Substitution d'un polynôme dans un autre.
463//--
464{
465 Poly c(b.Degre()*Degre());
466 for (int i=0; i<= Degre(); i++)
467 c += (*this)[i] * b.power(i);
468 return c;
469}
470
471
472// ******************* POLY 2 VARIABLES ******************
473
474//++
475// Class Poly2
476// Lib Outils++
477// include poly.h
478//
479// Classe de calcul sur polynômes à deux variables.
480//--
481
482//++
483// Links Parents
484// Vector
485//--
486
487//++
488// Titre Constructeurs
489//--
490
491//++
492Poly2::Poly2(int degreX, int degreY)
493//
494// Crée un polynôme de degrés partiels degreX et degreY.
495//--
496:Vector((degreX+1)*(degreY+1)), dirty(0),
497 maxDegX(degreX), maxDegY(degreY), degX(0), degY(0), deg(0)
498{
499 END_CONSTRUCTOR
500}
501
502//++
503Poly2::Poly2(Poly const& polX, Poly const& polY)
504//
505// Crée un polynôme à deux variables comme produit
506// de deux polynômes à une variable, p2(x,y)=px(x)py(y)
507//--
508:Vector((polX.Degre()+1)*(polY.Degre()+1)), dirty(0),
509 maxDegX(polX.Degre()), maxDegY(polY.Degre()),
510 degX(polX.Degre()), degY(polY.Degre()), deg(degX+degY)
511{
512 for (int i=0; i<=degX; i++)
513 for (int j=0; j<=degY; j++)
514 Coef(i,j) = polX[i]*polY[j];
515 END_CONSTRUCTOR
516}
517
518//++
519Poly2::Poly2(Poly2 const& a)
520//
521// Constructeur par copie.
522//--
523:Vector(a), dirty(a.dirty),
524 maxDegX(a.maxDegX), maxDegY(a.maxDegY),
525 degX(a.degX), degY(a.degY), deg(a.deg)
526{
527 END_CONSTRUCTOR
528}
529
530
531//++
532// Titre Méthodes
533//--
534
535//++
536Poly2& Poly2::operator = (Poly2 const& a)
537//
538// Opérateur d'affectation.
539//--
540{
541 if (this == &a) return *this;
542 if (maxDegX < a.DegX() || maxDegY < a.DegY())
543 Realloc(a.DegX(), a.DegY());
544
545
546 for (int i=0; i<= maxDegX; i++)
547 for (int j=0; j<= maxDegY; j++)
548 Coef(i,j) = a.Coef(i,j);
549
550 UpdateDeg();
551 return *this;
552}
553
554//++
555void Poly2::Realloc(int degreX, int degreY)
556//
557// Redimensionne le polynôme comme etant un
558// polynôme de degrés partiels degreX et degreY.
559//--
560{
561 UpdateDegIfDirty();
562 Poly2 tmp(*this);
563 Vector::Realloc((degreX+1)*(degreY+1));
564 Zero();
565 maxDegX = degreX;
566 maxDegY = degreY;
567
568 for (int i=0; i<= tmp.degX; i++)
569 for (int j=0; j<= tmp.degY; j++)
570 Coef(i,j) = tmp.Coef(i,j);
571}
572
573
574void Poly2::UpdateDeg() const
575{
576 (int&)degX=(int&)degY=(int&)deg=0;
577
578 for (int dx=0; dx<=maxDegX; dx++)
579 for (int dy=0; dy<=maxDegY; dy++)
580 if (Coef(dx,dy) != 0) {
581 if (dx > degX) (int&)degX = dx;
582 if (dy > degY) (int&)degY = dy;
583 if (dx+dy > deg) (int&)deg = dx+dy;
584 }
585
586 (int&)dirty = 0;
587}
588
589//++
590// int Poly2::DegX() const
591// Degré partiel en X.
592// int Poly2::DegY() const
593// Degré partiel en Y
594// int Poly2::MaxDegX() const
595// Degré partiel maximum (alloué) en X
596// int Poly2::MaxDegY() const
597// Degré partiel maximum (alloué) en Y
598// int Poly2::Deg() const
599// Degré total.
600//--
601
602//++
603// double& Poly2::Coef(int dx, int dy)
604// Retourne le coefficient de x^dx y^dy
605// (avec aussi version const).
606//--
607
608//++
609double Poly2::operator()(double x, double y) const
610//
611// Retourne la valeur en (x,y).
612//--
613{
614 UpdateDegIfDirty();
615 double res = 0;
616 double xPow = 1;
617 for (int dx=0; dx<=maxDegX; dx++) {
618 double yPow = 1;
619 for (int dy=0; dy<=maxDegY; dy++) {
620 res += Coef(dx,dy) * xPow * yPow;
621 yPow *= y;
622 }
623 xPow *= x;
624 }
625 return res;
626}
627
628//++
629double Poly2::Fit(Vector const& x, Vector const& y, Vector const& z,
630 int degreX, int degreY)
631//
632// Ajustement par moindre carrés z = P(x,y), degrés partiels imposés.
633//--
634{
635 int n = x.NElts();
636 if (n != y.NElts()) THROW(sizeMismatchErr);
637 if (n != z.NElts()) THROW(sizeMismatchErr);
638
639 Realloc(degreX, degreY);
640
641 Matrix a((degreX+1)*(degreY+1), n);
642
643 for (int c=0; c<n; c++) {
644 double xPow = 1.0;
645 for (int dx = 0; dx <= degreX; dx++) {
646 double yPow = 1.0;
647 for (int dy = 0; dy <= degreY; dy++) {
648 a(IndCoef(dx,dy), c) = xPow*yPow;
649 yPow *= y(c);
650 }
651 xPow *= x(c);
652 }
653 }
654
655 double rc = LinFit(a,z,(Vector&)*this);
656 UpdateDeg();
657 return rc;
658}
659
660
661//++
662double Poly2::Fit(Vector const& x, Vector const& y, Vector const& z,
663 Vector const& errz2, int degreX, int degreY,
664 Vector& errCoef)
665//
666// Ajustement par moindre carrés z = P(x,y), degrés partiels imposés,
667// et erreurs^2 sur z dans errz2.
668//--
669{
670 int n = x.NElts();
671 if (n != y.NElts()) THROW(sizeMismatchErr);
672 if (n != z.NElts()) THROW(sizeMismatchErr);
673 if (n != errz2.NElts()) THROW(sizeMismatchErr);
674
675 Realloc(degreX, degreY);
676 errCoef.Realloc((degreX+1)*(degreY+1));
677
678 Matrix a((degreX+1)*(degreY+1), n);
679
680 for (int c=0; c<n; c++) {
681 double xPow = 1.0;
682 for (int dx = 0; dx <= degreX; dx++) {
683 double yPow = 1.0;
684 for (int dy = 0; dy <= degreY; dy++) {
685 a(IndCoef(dx,dy), c) = xPow*yPow;
686 yPow *= y(c);
687 }
688 xPow *= x(c);
689 }
690 }
691
692 double rc = LinFit(a,z,errz2,(Vector&)*this,errCoef);
693 UpdateDeg();
694 return rc;
695}
696
697//++
698double Poly2::Fit(Vector const& x, Vector const& y, Vector const& z,
699 int degre)
700//
701// Ajustement par moindre carrés z = P(x,y), degré total imposé.
702//--
703{
704 int n = x.NElts();
705 if (n != y.NElts()) THROW(sizeMismatchErr);
706 if (n != z.NElts()) THROW(sizeMismatchErr);
707
708 Realloc(degre, degre); // certains vaudront 0, impose.
709
710 Matrix a((degre+1)*(degre+2)/2, n);
711 Vector cf((degre+1)*(degre+2)/2);
712#define C_INDEX(i,j) ((i) + (j)*(2*degre+3-(j))/2)
713
714 for (int c=0; c<n; c++) {
715 double xPow = 1.0;
716 for (int dx = 0; dx <= degre; dx++) {
717 double yPow = 1.0;
718 for (int dy = 0; dy <= degre; dy++) {
719 if (dy+dx <= degre)
720 a(C_INDEX(dx,dy), c) = xPow*yPow;
721 yPow *= y(c);
722 }
723 xPow *= x(c);
724 }
725 }
726
727 double rc = LinFit(a,z,cf);
728
729 for (int dx = 0; dx <= degre; dx++)
730 for (int dy = 0; dy <= degre; dy++)
731 if (dx+dy <= degre)
732 Coef(dx,dy) = cf(C_INDEX(dx,dy));
733 else
734 Coef(dx,dy) = 0;
735
736 UpdateDeg();
737 return rc;
738}
739
740
741//++
742double Poly2::Fit(Vector const& x, Vector const& y, Vector const& z,
743 Vector const& errz2, int degre,
744 Vector& errCoef)
745//
746// Ajustement par moindre carrés z = P(x,y), degré total imposé,
747// et erreurs^2 sur z dans errz2.
748//--
749{
750 int n = x.NElts();
751 if (n != y.NElts()) THROW(sizeMismatchErr);
752 if (n != z.NElts()) THROW(sizeMismatchErr);
753 if (n != errz2.NElts()) THROW(sizeMismatchErr);
754
755 Realloc(degre, degre);
756 errCoef.Realloc((degre+1)*(degre+1));
757#define C_INDEX(i,j) ((i) + (j)*(2*degre+3-(j))/2)
758
759 Matrix a((degre+1)*(degre+2)/2, n);
760 Vector cf((degre+1)*(degre+2)/2);
761 Vector ecf((degre+1)*(degre+2)/2);
762
763 for (int c=0; c<n; c++) {
764 double xPow = 1.0;
765 for (int dx = 0; dx <= degre; dx++) {
766 double yPow = 1.0;
767 for (int dy = 0; dy <= degre; dy++) {
768 if (dy+dx <= degre)
769 a(C_INDEX(dx,dy), c) = xPow*yPow;
770 yPow *= y(c);
771 }
772 xPow *= x(c);
773 }
774 }
775
776 double rc = LinFit(a,z,errz2,cf,ecf);
777
778
779 for (int dx = 0; dx <= degre; dx++)
780 for (int dy = 0; dy <= degre; dy++)
781 if (dx+dy <= degre) {
782 Coef(dx,dy) = cf(C_INDEX(dx,dy));
783 errCoef(IndCoef(dx,dy)) = ecf(C_INDEX(dx,dy));
784 } else {
785 Coef(dx,dy) = 0;
786 errCoef(IndCoef(dx,dy)) = 0;
787 }
788 UpdateDeg();
789 return rc;
790}
791
792
793void Poly2::ReadSelf(PInPersist& s)
794{
795 int_4 dgx, dgy;
796 s >> dgx >> dgy;
797
798 Realloc(dgx, dgy);
799
800#ifdef DEBUG
801 int r = nr; int c = nc;
802#endif
803
804 Vector::ReadSelf(s);
805
806#ifdef DEBUG
807 DBASSERT(r == nr && c == nc);
808#endif
809 UpdateDeg();
810}
811
812void Poly2::WriteSelf(POutPersist& s) const
813{
814 s << maxDegX << maxDegY;
815 Vector::WriteSelf(s);
816}
817
818//++
819void Poly2::Print(ostream& s) const
820//
821// Impression sur stream s.
822//--
823{
824 UpdateDegIfDirty();
825 int nz=0;
826 int notfirst=0;
827 for (int dx = degX; dx>=0; dx--)
828 for (int dy= degY; dy>=0; dy--) {
829 double c = Coef(dx,dy);
830 if (c != 0) {
831 nz = 1;
832 if (notfirst && c > 0) {
833 s << "+";
834 notfirst = 1;
835 }
836 s << c << " ";
837 if (dx == 1) s << "* X ";
838 if (dx > 1) s << "* X^" << dx << " ";
839 if (dy == 1) s << "* Y ";
840 if (dy > 1) s << "* Y^" << dy << " ";
841 s << endl;
842 }
843 }
844 if (!nz) s << " 0 ";
845}
846
847//++
848ostream& operator << (ostream& s, const Poly2& a)
849//
850// Impression sur stream s.
851//--
852{
853 a.Print(s);
854 return s;
855}
856
857
858//++
859// Titre Opérations
860//--
861
862//++
863Poly2& Poly2::operator += (Poly2 const& b)
864//
865//--
866{
867 if (maxDegX < b.DegX() || maxDegY < b.DegY())
868 Realloc(b.DegX(),b.DegY());
869
870 UpdateDegIfDirty();
871
872 int mx = b.DegX();
873 int my = b.DegY();
874 for (int i=0; i<= mx; i++)
875 for (int j=0; j<= my; j++)
876 Coef(i,j) += b.Coef(i,j);
877
878 UpdateDeg();
879 return *this;
880}
881
882//++
883Poly2& Poly2::operator -= (Poly2 const& b)
884//
885//--
886{
887 if (maxDegX < b.DegX() || maxDegY < b.DegY())
888 Realloc(b.DegX(),b.DegY());
889
890 UpdateDegIfDirty();
891
892 int mx = b.DegX();
893 int my = b.DegY();
894 for (int i=0; i<= mx; i++)
895 for (int j=0; j<= my; j++)
896 Coef(i,j) -= b.Coef(i,j);
897
898 UpdateDeg();
899 return *this;
900}
901
902//++
903Poly2 operator+ (Poly2 const& a, Poly2 const& b)
904//
905//--
906#if HAS_NAMED_RETURN
907 return c(a)
908#endif
909{
910#if !HAS_NAMED_RETURN
911Poly2 c(a);
912#endif
913 c += b;
914#if !HAS_NAMED_RETURN
915return c;
916#endif
917}
918
919//++
920Poly2 operator- (Poly2 const& a, Poly2 const& b)
921//
922//--
923#if HAS_NAMED_RETURN
924 return c(a)
925#endif
926{
927#if !HAS_NAMED_RETURN
928Poly2 c(a);
929#endif
930 c -= b;
931#if !HAS_NAMED_RETURN
932return c;
933#endif
934}
935
936//++
937Poly2& Poly2::operator *= (double a)
938//
939//--
940{
941 for (int i=0; i<NElts(); i++)
942 data[i] *= a;
943
944 return *this;
945}
946
947//++
948Poly2 operator * (double a, Poly2 const& b)
949//
950//--
951#if HAS_NAMED_RETURN
952 return c(b)
953#endif
954{
955#if !HAS_NAMED_RETURN
956Poly2 c(b);
957#endif
958 c *= a;
959#if !HAS_NAMED_RETURN
960return c;
961#endif
962}
963
964//++
965Poly2 operator* (Poly2 const& a, Poly2 const& b)
966//
967//--
968{
969 Poly2 c(a.DegX() + b.DegX(), a.DegY() + b.DegY());
970 a.UpdateDegIfDirty();
971 b.UpdateDegIfDirty();
972
973 for (int i=0; i<=a.DegX(); i++)
974 for (int j=0; j<=a.DegY(); j++)
975 for (int k=0; k<=b.DegX(); k++)
976 for (int l=0; l<=b.DegY(); l++)
977 c.Coef(i+k,j+l) += a.Coef(i,j)*b.Coef(k,l);
978 return c;
979}
980
981//++
982Poly2 Poly2::power(int n) const
983//
984// Calcule le polynôme P(x,y)^n
985//--
986{
987 if (n < 0) THROW(rangeCheckErr);
988 if (n == 0) { Poly2 r(0); r.Coef(0,0) = 1; return r;}
989 if (n == 1) { return *this; }
990 return *this * power(n-1);
991}
992
993
994//++
995Poly2 Poly2::operator() (Poly const& a, Poly const& b) const
996//
997// Substitution de deux polynômes en X et Y,
998// P2(pa(x), pb(y)).
999//--
1000{
1001 UpdateDegIfDirty();
1002 Poly2 c(maxDegX*a.Degre(), maxDegY*b.Degre());
1003
1004 for (int i=0; i<= degX; i++)
1005 for (int j=0; j<= degY; j++) {
1006 Poly2 d(a.power(i), b.power(j));
1007 c += Coef(i,j) * d;
1008 }
1009
1010 return c;
1011}
1012
1013//++
1014Poly2 Poly::operator() (Poly2 const& a) const
1015//
1016// Substitution d'un polynôme à deux variables dans
1017// un polynôme à une variable, P(P2(x,y)).
1018//--
1019{
1020 Poly2 c(a.MaxDegX()*Degre(), a.MaxDegY()*Degre());
1021
1022 for (int i=0; i<= Degre(); i++)
1023 c += (*this)[i] * a.power(i);
1024 return c;
1025}
1026
1027
Note: See TracBrowser for help on using the repository browser.