source: Sophya/trunk/SophyaLib/NTools/cspline.cc@ 753

Last change on this file since 753 was 710, checked in by ansari, 26 years ago

Introduction FFTServerInterface et FFTPackServer - Reza 21/01/2000

File size: 12.5 KB
Line 
1#include "machdefs.h"
2
3#include <stdlib.h>
4#include <stdio.h>
5#include <math.h>
6#include <iostream.h>
7
8#ifdef __MWERKS__
9 #include <iostream>
10#endif
11
12#include "nbtri.h"
13#include "cspline.h"
14
15//++
16// Class CSpline
17// Lib Outils++
18// include cspline.h
19//
20// Classe de spline 1D
21//--
22
23//++
24// Titre Constructeurs
25//--
26
27//////////////////////////////////////////////////////////////////////////////
28//++
29CSpline::CSpline(int n,double* x,double* y,double yp1,double ypn
30 ,int natural,bool order)
31//
32// Createur pour spline 3 sur "x[0->n],y[0->n]" avec "yp1,ypn" derivees
33// au premier et dernier points et "natural" indiquant les types de
34// contraintes sur les derivees 2sd au premier et dernier point.
35// "order" doit etre mis a "true" si le tableau de "x[]" n'est pas ordonne
36// dans l'ordre des "x" croissants ("x[i]<x[i+1]"): cette option
37// realloue la place pour les tableaux "x,y" autrement seule une
38// connection aux tableaux "x,y" externes est realisee.
39//--
40 : Nel(0), corrupt_Y2(true), XY_Created(false), Natural(natural)
41 , YP1(yp1), YPn(ypn), X(NULL), Y(NULL), Y2(NULL), tmp(NULL)
42{
43SetNewTab(n,x,y,order,true);
44if( x != NULL && y != NULL) ComputeCSpline();
45
46END_CONSTRUCTOR
47}
48
49//////////////////////////////////////////////////////////////////////////////
50//++
51CSpline::CSpline(double yp1,double ypn,int natural)
52//
53// Createur par defaut.
54//--
55 : Nel(0), corrupt_Y2(true), XY_Created(false), Natural(natural)
56 , YP1(yp1), YPn(ypn), X(NULL), Y(NULL), Y2(NULL), tmp(NULL)
57{
58END_CONSTRUCTOR
59}
60
61//////////////////////////////////////////////////////////////////////////////
62CSpline::~CSpline()
63// destructeur
64{
65DelTab();
66}
67
68//++
69// Titre Methodes
70//--
71
72//////////////////////////////////////////////////////////////////////////////
73//++
74void CSpline::SetNewTab(int n,double* x,double* y,bool order,bool force)
75//
76// Pour changer les tableaux sans recreer la classe,
77// memes arguments que dans le createur.
78// Pour connecter les tableaux "x[n],y[n]" aux pointeurs internes "X,Y"
79// Si "order=true", on considere que x n'est pas range par ordre
80// des "x" croissants. La methode alloue de la place pour des tableaux
81// internes "X,Y" qu'elle re-ordonne par "x" croissant.
82// "force=true" impose la reallocation des divers buffers, sinon
83// la reallocation n'a lieu que si le nombre de points augmente.
84//--
85{
86ASSERT( n>3 );
87
88// allocation des buffers Y2 et tmp
89if( n>Nel || force ) {
90 if( Y2 != NULL ) delete [] Y2;
91 if( tmp != NULL ) delete [] tmp;
92 Y2 = new double[n];
93 tmp = new double[n];
94}
95// des-allocation eventuelle de X,Y
96if( XY_Created ) {
97 if( !order || n>Nel || force ) {
98 if( X != NULL ) delete [] X; X = NULL;
99 if( Y != NULL ) delete [] Y; Y = NULL;
100 XY_Created = false;
101 }
102}
103// allocation eventuelle de X,Y
104if( order ) {
105 if( !XY_Created || n>Nel || force ) {
106 X = new double[n];
107 Y = new double[n];
108 XY_Created = true;
109 }
110}
111Nel = n;
112corrupt_Y2 = true;
113
114if( x==NULL || y==NULL ) return;
115
116// Classement eventuel par ordre des x croissants
117if( order ) {
118 if( tmp == NULL ) tmp = new double[n];
119 ind = (int_4 *) tmp;
120 tri_double(x,ind,(int_4) Nel);
121 for(int i=0;i<Nel;i++) {
122 X[i] = x[ind[i]];
123 Y[i] = y[ind[i]];
124 if( i>0 ) if( X[i-1]>= X[i] ) {
125 printf("CSpline::SetNewTab_Erreur: X[%d]>=X[%d] (%g>=%g)\n"
126 ,i-1,i,X[i-1],X[i]);
127 THROW(inconsistentErr);
128 }
129 }
130} else { X = x; Y = y; }
131
132}
133
134//////////////////////////////////////////////////////////////////////////////
135void CSpline::DelTab()
136// destruction des divers tableaux en tenant compte des allocations/connections
137{
138if( X != NULL && XY_Created ) delete [] X; X = NULL;
139if( Y != NULL && XY_Created ) delete [] Y; Y = NULL;
140if( Y2 != NULL ) delete [] Y2; Y2 = NULL;
141if( tmp != NULL ) delete [] tmp; tmp = NULL;
142}
143
144//////////////////////////////////////////////////////////////////////////////
145//++
146void CSpline::SetBound1er(double yp1,double ypn)
147//
148// Pour changer les valeurs des derivees 1ere au 1er et dernier points
149// Valeurs imposees des derivees 1ere au points "X[0]" et "X[Nel-1]".
150//--
151{
152if( yp1 == YP1 && ypn == YPn ) return;
153
154YP1 = yp1;
155YPn = ypn;
156
157corrupt_Y2 = true;
158}
159
160//////////////////////////////////////////////////////////////////////////////
161//++
162void CSpline::ComputeCSpline()
163//
164// Pour calculer les tableaux de coeff permettant le calcul
165// des interpolations spline.
166//--
167{
168// on ne fait rien si les tableaux ne sont pas connectes
169if( X == NULL || Y == NULL ) {
170 printf("CSpline::ComputeCSpline()_Erreur: tableaux non connectes X=%p Y=%p\n"
171 ,X,Y);
172 return;
173}
174// On ne fait rien si rien n'a change!
175if( ! corrupt_Y2 ) return;
176// protection si tmp a ete desalloue pour gain de place (ex: CSpline2)
177if( tmp == NULL ) tmp = new double[Nel];
178
179double p,qn,sig,un;
180
181if (Natural & Natural1)
182 Y2[0] = tmp[0] = 0.0;
183else {
184 Y2[0] = -0.5;
185 tmp[0] = (3.0/(X[1]-X[0]))*((Y[1]-Y[0])/(X[1]-X[0])-YP1);
186}
187
188for (int i=1;i<Nel-1;i++) {
189 sig = (X[i]-X[i-1])/(X[i+1]-X[i-1]);
190 p = sig * Y2[i-1] + 2.0;
191 Y2[i] = (sig-1.0)/p;
192 tmp[i]= (Y[i+1]-Y[i])/(X[i+1]-X[i]) - (Y[i]-Y[i-1])/(X[i]-X[i-1]);
193 tmp[i]= (6.0*tmp[i]/(X[i+1]-X[i-1])-sig*tmp[i-1])/p;
194}
195
196if (Natural & NaturalN)
197 qn = un = 0.0;
198else {
199 qn = 0.5;
200 un = (3.0/(X[Nel-1]-X[Nel-2]))
201 *(YPn-(Y[Nel-1]-Y[Nel-2])/(X[Nel-1]-X[Nel-2]));
202}
203Y2[Nel-1] = (un-qn*tmp[Nel-2])/(qn*Y2[Nel-2]+1.0);
204for (int k=Nel-2;k>=0;k--) Y2[k] = Y2[k]*Y2[k+1] + tmp[k];
205
206corrupt_Y2 = false;
207}
208
209//////////////////////////////////////////////////////////////////////////////
210//++
211double CSpline::CSplineInt(double x)
212//
213// Interpolation spline en "x"
214//--
215{
216int klo,khi,k;
217double h,b,a,y = 0.;
218
219if( corrupt_Y2 ) {
220 cout<<"CSpline::CSplineInt: calcul des coef du spline corrupted"<<endl;
221 THROW(inconsistentErr);
222}
223
224klo = 0;
225khi = Nel-1;
226while (khi-klo > 1) {
227 k = (khi+klo) >> 1;
228 if (X[k] > x) khi=k;
229 else klo=k;
230}
231h=X[khi]-X[klo];
232
233if (h == 0.0) {
234 cout<<"CSpline::CSplineInt: pout khi="<<khi<<" klo="<<klo
235 <<" memes valeurs de X[]: "<<X[khi]<<endl;
236 THROW(inconsistentErr);
237}
238
239a = (X[khi]-x)/h;
240b = (x-X[klo])/h;
241y = a*Y[klo]+b*Y[khi]+((a*a*a-a)*Y2[klo]+(b*b*b-b)*Y2[khi])*(h*h)/6.0;
242
243return y;
244}
245
246///////////////////////////////////////////////////////////////
247///////// rappel des inlines pour commentaires ////////////////
248///////////////////////////////////////////////////////////////
249
250//++
251// inline void SetNaturalCSpline(int type = NaturalAll)
252// Pour changer le type de contraintes sur les derivees 2sd
253//--
254//++
255// inline void Free_Tmp()
256// Pour liberer la place tampon qui ne sert que
257// dans ComputeCSpline() et pas dans CSplineInt
258//--
259
260//////////////////////////////////////////////////////////////////////////////
261//////////////////////////////////////////////////////////////////////////////
262
263//++
264// Class CSpline2
265// Lib Outils++
266// include cspline.h
267//
268// Classe de spline 2D
269//--
270
271//++
272// Titre Constructeurs
273//--
274
275//////////////////////////////////////////////////////////////////////////////
276//++
277CSpline2::CSpline2(int n1,double* x1,int n2,double* x2,double* y
278 ,int natural,bool order)
279//
280// Meme commentaire que pour CSpline avec:
281//| x1[n1]: liste des coordonnees selon l axe 1
282//| x2[n2]: liste des coordonnees selon l axe 2
283//| y[n1*n2]: liste des valeurs avec le rangement suivant
284//| x1[0]......x1[n1-1] x1[0]......x1[n1-1] ... x1[0]......x1[n1-1]
285//| | 0<=i<n1 | | 0<=i<n1 | ... | 0<=i<n1 |
286//| j=0 X2[0] j=1 X2[1] j=n2-1 X2[n2-1]
287//--
288 : Nel1(0), Nel2(0), corrupt_Y2(true), XY_Created(false), Natural(natural)
289 , X1(NULL), X2(NULL), Y(NULL), Y2(NULL)
290 , Nel_S(0), S(NULL), Sint(NULL), tmp(NULL)
291{
292SetNewTab(n1,x1,n2,x2,y,order,true);
293if( x1 != NULL && x2 != NULL && y != NULL) ComputeCSpline();
294
295END_CONSTRUCTOR
296}
297
298//////////////////////////////////////////////////////////////////////////////
299//++
300CSpline2::CSpline2(int natural)
301//
302// Createur par defaut.
303//--
304 : Nel1(0), Nel2(0), corrupt_Y2(true), XY_Created(false), Natural(natural)
305 , X1(NULL), X2(NULL), Y(NULL), Y2(NULL)
306 , Nel_S(0), S(NULL), Sint(NULL), tmp(NULL)
307{
308END_CONSTRUCTOR
309}
310
311//////////////////////////////////////////////////////////////////////////////
312CSpline2::~CSpline2()
313{
314DelTab();
315}
316
317//++
318// Titre Methodes
319//--
320
321//////////////////////////////////////////////////////////////////////////////
322//++
323void CSpline2::SetNewTab(int n1,double* x1,int n2,double* x2,double* y
324 ,bool order,bool force)
325//
326// Voir commentaire meme methode de CSpline
327//--
328{
329ASSERT( n1>3 && n2>3 );
330
331int n = ( n1 < n2 ) ? n2 : n1;
332
333// allocation des buffers Y2 et tmp et des CSpline 1D
334if( n1>Nel1 || n2>Nel2 || force ) {
335 if( Y2 != NULL ) delete [] Y2;
336 if( tmp != NULL ) delete [] tmp;
337 Y2 = new double[n1*n2];
338 tmp = new double[n];
339
340 // et les CSpline[n1] pour memoriser les interpolations sur x1(0->n1)
341 if( S != NULL ) {
342 for(int i=0;i<Nel_S;i++) if(S[i] != NULL) { delete S[i]; S[i]=NULL;}
343 delete S; S = NULL;
344 }
345 S = new CSpline * [n2];
346 for(int j=0;j<n2;j++) {
347 S[j] = new CSpline(n1,NULL,NULL,0.,0.,Natural);
348 S[j]->Free_Tmp();
349 }
350 Nel_S = n2;
351
352 if( S != NULL ) { delete Sint; Sint = NULL;}
353 Sint = new CSpline(n2,NULL,NULL,0.,0.,Natural);
354
355}
356// des-allocation eventuelle de X1,X2,Y
357if( XY_Created ) {
358 if( !order || n1>Nel1 || n2>Nel2 || force ) {
359 if( X1 != NULL ) delete [] X1; X1 = NULL;
360 if( X2 != NULL ) delete [] X2; X2 = NULL;
361 if( Y != NULL ) delete [] Y; Y = NULL;
362 XY_Created = false;
363 }
364}
365// allocation eventuelle de X1,X2,Y
366if( order ) {
367 if( !XY_Created || n1>Nel1 || n2>Nel1 || force ) {
368 X1 = new double[n1];
369 X2 = new double[n2];
370 Y = new double[n1*n2];
371 XY_Created = true;
372 }
373}
374Nel1 = n1; Nel2 = n2;
375corrupt_Y2 = true;
376
377if( x1==NULL || x2==NULL || y==NULL ) return;
378
379// Classement eventuel par ordre des x1 et x2 croissants
380if( order ) {
381
382 if( tmp == NULL ) tmp = new double[n];
383 ind = (int_4 *) tmp;
384 double* Ytmp = new double[n1*n2];
385
386 // tri par valeur croissantes de x1
387 tri_double(x1,ind,(int_4) Nel1);
388 for(int i=0;i<Nel1;i++) {
389 X1[i] = x1[ind[i]];
390 if( i>0 ) if( X1[i-1] >= X1[i] )
391 { printf("CSpline::SetNewTab_Erreur: X1[%d]>=X1[%d] (%g>=%g)\n"
392 ,i-1,i,X1[i-1],X1[i]);
393 THROW(inconsistentErr); }
394 for(int j=0;j<Nel2;j++) Ytmp[j*Nel1+i] = y[j*Nel1+ind[i]];
395 }
396
397 // tri par valeur croissantes de x2
398 tri_double(x2,ind,(int_4) Nel2);
399 for(int j=0;j<Nel2;j++) {
400 X2[j] = x2[ind[j]];
401 if( j>0 ) if( X2[j-1] >= X2[j] )
402 { printf("CSpline::SetNewTab_Erreur: X2[%d]>=X2[%d] (%g>=%g)\n"
403 ,j-1,j,X2[j-1],X2[j]);
404 THROW(inconsistentErr); }
405 for(int i=0;i<Nel1;i++) Y[j*Nel1+i] = Ytmp[j*Nel1+ind[i]];
406 }
407 delete [] Ytmp;
408
409} else {
410
411 X1 = x1;
412 X2 = x2;
413 Y = y;
414
415}
416
417}
418
419//////////////////////////////////////////////////////////////////////////////
420void CSpline2::DelTab()
421{
422if( X1 != NULL && XY_Created ) delete [] X1; X1 = NULL;
423if( X2 != NULL && XY_Created ) delete [] X2; X2 = NULL;
424if( Y != NULL && XY_Created ) delete [] Y; Y = NULL;
425if( Y2 != NULL ) delete [] Y2; Y2 = NULL;
426if( tmp != NULL ) delete [] tmp; tmp = NULL;
427if( S != NULL ) {
428 for(int i=0;i<Nel_S;i++) if(S[i] != NULL) { delete S[i]; S[i]=NULL;}
429 delete S; S = NULL;
430}
431if( Sint != NULL ) { delete Sint; Sint=NULL;}
432}
433
434//////////////////////////////////////////////////////////////////////////////
435//++
436void CSpline2::ComputeCSpline()
437//
438// Voir commentaire meme methode de CSpline
439//--
440{
441// on ne fait rien si X1 ou X2 ou Y non connectes
442if( X1 == NULL || X2 == NULL || Y == NULL ) return;
443// On ne fait rien si rien n'a change
444if( ! corrupt_Y2 ) return;
445
446for(int j=0; j<Nel2; j++) {
447 // on n'alloue pas de place nouvelle, on utilise CSpline2::tmp
448 S[j]->tmp = tmp;
449 // connection de X1,Y au spline 1D sans ordre demande
450 S[j]->SetNewTab(Nel1,X1,&Y[j*Nel1],false,false);
451 // calcul des coeff splien pour l'interpolation future
452 S[j]->ComputeCSpline();
453}
454
455corrupt_Y2 = false;
456}
457
458//////////////////////////////////////////////////////////////////////////////
459//++
460double CSpline2::CSplineInt(double x1,double x2)
461//
462// Voir commentaire meme methode de CSpline
463//--
464{
465// calcul de la valeur Y pour x=x1 et remplissage du tampon tmp
466for(int j=0;j<Nel2;j++) tmp[j] = S[j]->CSplineInt(x1);
467
468// connection X2,tmp pour interpolation selon x=x2
469Sint->SetNewTab(Nel2,X2,tmp,false,false);
470// calcul des coeff pour interpolation selon X2
471Sint->ComputeCSpline();
472// Interpolation finale
473return Sint->CSplineInt(x2);
474}
475
476///////////////////////////////////////////////////////////////
477///////// rappel des inlines pour commenatires ////////////////
478///////////////////////////////////////////////////////////////
479
480//++
481// inline void SetNaturalCSpline(int type = NaturalAll)
482// Voir commentaire meme methode de CSpline
483//--
Note: See TracBrowser for help on using the repository browser.