source: Sophya/trunk/Cosmo/SimLSS/geneutils.cc@ 3157

Last change on this file since 3157 was 3157, checked in by cmv, 19 years ago

intro du facteur de croissance dans la simul cmv 25/01/2007

File size: 6.8 KB
RevLine 
[3115]1#include "sopnamsp.h"
2#include "machdefs.h"
3#include <iostream>
4#include <stdlib.h>
5#include <stdio.h>
6#include <string.h>
7#include <math.h>
8#include <vector>
9
10#include "pexceptions.h"
11
12#include "histos.h"
13#include "hisprof.h"
14#include "srandgen.h"
15
16#include "geneutils.h"
17
18//-------------------------------------------------------------------
19// Classe d'interpolation lineaire:
20// Le vecteur y a n elements y_i tels que y_i = f(x_i)
[3157]21// ou les x_i sont regulierement espaces
22// et x_0=xmin et x_{n-1}=xmax (xmax inclus!)
[3115]23InterpFunc::InterpFunc(double xmin,double xmax,vector<double>& y)
24 : _xmin(xmin), _xmax(xmax), _y(y)
25{
26 if(_xmin>=_xmax || _y.size()<=2) { // au moins 3 points!
27 cout<<"InterpFunc::InterpFunc : bad arguments values"<<endl;
28 throw ParmError("InterpFunc::InterpFunc : bad arguments values");
29 }
30 _nm1 = _y.size()-1;
[3157]31 _dx = (_xmax-_xmin)/(double)_nm1;
[3115]32}
33
34double InterpFunc::Linear(double x,unsigned short& ok)
35{
36 ok=0; if(x<_xmin) ok=1; else if(x>_xmax) ok=2;
37 x -= _xmin;
[3157]38 long i = long(x/_dx); // On prend le "i" juste en dessous
[3115]39 if(i<0) i=0; else if(i>=_nm1) i=_nm1-1;
40 return _y[i] + (_y[i+1]-_y[i])/_dx*(x-i*_dx);
41}
42
43double InterpFunc::Parab(double x,unsigned short& ok)
44{
45 ok=0; if(x<_xmin) ok=1; else if(x>_xmax) ok=2;
46 x -= _xmin;
[3157]47 long i = long(x/_dx+0.5); // On prend le "i" le + proche
[3115]48 if(i<1) i=1; else if(i>=_nm1-1) i=_nm1-2;
49 double a = (_y[i+1]-2.*_y[i]+_y[i-1])/(2.*_dx*_dx);
50 double b = (_y[i+1]-_y[i-1])/(2.*_dx);
51 return _y[i] + (x-i*_dx)*(a*(x-i*_dx)+b);
52}
53
54//-------------------------------------------------------------------
[3157]55// Classe d'inversion d'une fonction STRICTEMENT MONOTONE CROISSANTE
56// - Le vecteur y a "Nin" elements y_i tels que "y_i = f(x_i)"
57// - On a x(i) < x(i+1) et y(i) < y(i+1)
58// - La classe renvoie ymin=y(0) , ymax=y(Nin -1)
59// et le vecteur x = f^-1(y) de "Nout" elements
60// Les y_i sont regulierement espaces et ymin et ymax
61// La re-interpolation inverse est faite par lineaire
62InverseFunc::InverseFunc(vector<double>& x,vector<double>& y)
63 : _ymin(0.) , _ymax(0.) , _x(x) , _y(y)
64{
65 int_4 ns = _x.size();
66 if(ns<3 || _y.size()<=0 || ns!=_y.size())
67 throw ParmError("InverseFunc::InverseFunc_Error: bad array size");
68
69 // Check "x" strictement monotone croissant
70 for(int_4 i=0;i<ns-1;i++)
71 if(_x[i+1]<=_x[i]) {
72 cout<<"InverseFunc::InverseFunc_Error: _x array not stricly growing"<<endl;
73 throw ParmError("InverseFunc::InverseFunc_Error: _x array not stricly growing");
74 }
75
76 // Check "y" monotone croissant
77 for(int_4 i=0;i<ns-1;i++)
78 if(_y[i+1]<_y[i]) {
79 cout<<"InverseFunc::InverseFunc_Error: _y array not growing"<<endl;
80 throw ParmError("InverseFunc::InverseFunc_Error: _y array not growing");
81 }
82
83 // define limits
84 _ymin = _y[0];
85 _ymax = _y[ns-1];
86
87}
88
89InverseFunc::~InverseFunc(void)
90{
91}
92
93int InverseFunc::ComputeLinear(long n,vector<double>& xfcty)
94{
95 if(n<3) return -1;
96
97 xfcty.resize(n);
98
99 long i1,i2;
100 double x;
101 for(int_4 i=0;i<n;i++) {
102 double y = _ymin + i*(_ymax-_ymin)/(n-1.);
103 find_in_y(y,i1,i2);
104 double dy = _y[i2]-_y[i1];
105 if(dy==0.) {
106 x = (_x[i2]+_x[i1])/2.; // la fct a inverser est plate!
107 } else {
108 x = _x[i1] + (_x[i2]-_x[i1])/dy * (y-_y[i1]);
109 }
110 xfcty[i] = x;
111 }
112
113 return 0;
114}
115
116int InverseFunc::ComputeParab(long n,vector<double>& xfcty)
117{
118 if(n<3) return -1;
119
120 xfcty.resize(n);
121
122 long i1,i2,i3;
123 double x;
124 for(int_4 i=0;i<n;i++) {
125 double y = _ymin + i*(_ymax-_ymin)/(n-1.);
126 find_in_y(y,i1,i2);
127 // On cherche le 3ieme point selon la position de y / au 2 premiers
128 double my = (_y[i1]+_y[i2])/2.;
129 if(y<my) {i3=i2; i2=i1; i1--;} else {i3=i2+1;}
130 // Protection
131 if(i1<0) {i1++; i2++; i3++;}
132 if(i3==_y.size()) {i1--; i2--; i3--;}
133 // Interpolation parabolique
134 double dy = _y[i3]-_y[i1];
135 if(dy==0.) {
136 x = (_x[i3]+_x[i1])/2.; // la fct a inverser est plate!
137 } else {
138 double X1=_x[i1]-_x[i2], X3=_x[i3]-_x[i2];
139 double Y1=_y[i1]-_y[i2], Y3=_y[i3]-_y[i2];
140 double den = Y1*Y3*dy;
141 double a = (X3*Y1-X1*Y3)/den;
142 double b = (X1*Y3*Y3-X3*Y1*Y1)/den;
143 y -= _y[i2];
144 x = (a*y+b)*y + _x[i2];
145 }
146 xfcty[i] = x;
147 }
148
149 return 0;
150}
151
152//-------------------------------------------------------------------
[3115]153int FuncToHisto(GenericFunc& func,Histo& h,bool logaxex)
154// Remplit l'histo 1D "h" avec la fonction "func"
155// INPUT:
156// logaxex = false : remplissage lineaire
157// les abscisses "x" des bins sont remplis avec f(x)
158// logaxex = true : remplissage logarithmique (base 10)
159// les abscisses "x" des bins sont remplis avec f(10^x)
160// RETURN:
161// 0 = OK
162// 1 = error
163{
164 if(h.NBins()<=0) return 1;
165
166 h.Zero();
167
168 for(int_4 i=0;i<h.NBins();i++) {
169 double x = h.BinCenter(i);
170 if(logaxex) x = pow(10.,x);
171 h.SetBin(i,func(x));
172 }
173
174 return 0;
175}
176
177int FuncToVec(GenericFunc& func,TVector<r_8>& v,double xmin,double xmax,bool logaxex)
178// Remplit le TVector avec la fonction "func"
179// INPUT:
180// logaxex = false : remplissage lineaire
181// les abscisses "x" des bins sont remplis avec f(x)
182// logaxex = true : remplissage logarithmique (base 10)
183// les abscisses "x" des bins sont remplis avec f(10^x)
184// RETURN:
185// 0 = OK
186// 1 = error
187// Remarque:
188// v(i) = f(xmin+i*dx) avec dx = (xmax-xmin)/v.NElts()
189{
190 if(v.NElts()<=0 || xmax<=xmin) return 1;
191
192 v = 0.;
193 double dx = (xmax-xmin)/v.NElts();
194
195 for(int_4 i=0;i<v.NElts();i++) {
196 double x = xmin + i * dx;;
197 if(logaxex) x = pow(10.,x);
198 v(i) = func(x);
199 }
200
201 return 0;
202}
203
204//-------------------------------------------------------------------
205double AngSol(double dtheta,double dphi,double theta0)
206// Retourne l'angle solide d'un "rectangle" et coordonnees spheriques
207// de DEMI-COTE "dtheta" x "dphi" et centre en "theta0"
208// Attention: Le "theta0" de l'equateur est Pi/2 (et non pas zero)
209// Les unites des angles sont en radians
210// theta0 in [0,Pi]
211// dtheta in [0,Pi]
212// dphi in [0,2Pi]
213// Return: l'angle solide en steradian
214{
215 double theta1 = theta0-dtheta, theta2 = theta0+dtheta;
216 if(theta1<0.) theta1=0.;
217 if(theta2>M_PI) theta2=M_PI;
218
219 return 2.*dphi * (cos(theta1)-cos(theta2));
220}
221
222double AngSol(double dtheta)
223// Retourne l'angle solide d'une calotte spherique de demi-ouverture "dtheta"
224// Attention: Les unites des angles sont en radians
225// dtheta in [0,Pi]
226// Return: l'angle solide en steradian
227// Approx pour theta petit: PI theta^2
228{
229 return 2.*M_PI * (1.-cos(dtheta));
230}
231
232//-------------------------------------------------------------------
233unsigned long PoissRandLimit(double mu,double mumax)
234{
235 double pp,ppi,x;
236 unsigned long n;
237
238 if(mu>=mumax) {
239 pp = sqrt(mu);
240 while( (x=pp*NorRand()) < -mu );
241 return (unsigned long)(mu+x+0.5);
242 }
243
244 ppi = pp = exp(-mu);
245 x = drand01();
246 n = 0;
247 while (x > ppi) {
248 n++;
249 pp = mu*pp/(double)n;
250 ppi += pp;
251 }
252 return n;
253}
Note: See TracBrowser for help on using the repository browser.