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

Last change on this file since 3201 was 2870, checked in by ansari, 20 years ago

Portage/compilation sur AIX-XlC (regatta): Ajout qualification de nom ou namespace SOPHYA pour instanciation explicite de template + correction ambiguite syntaxe new X* [] - Reza 3 Jan 2006

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