CGEM BOSS 6.6.5.h
BESIII Offline Software System
Loading...
Searching...
No Matches
ConvolveWithConst.cxx
Go to the documentation of this file.
2
3//#include <cstdint>
4#include <complex>
5#include <vector>
6#include <cstring>
7#include "TVirtualFFT.h"
8#include <climits>
9#include <iostream>
10
11using std::cout;
12using std::cerr;
13using std::endl;
14typedef unsigned int uint32_tt;
15//static_assert( UINT_MAX == 4294967295U," a unsigned 32-bit int is needed for Bit Twidding Hack at ConvolveWithConst::ConvolveWithConst() ");
16#if not UINT_MAX == 4294967295U // i.e. uint is uint32_t
17 Compile Time Error A Unsigned 32-bit int is needed at ConvolveWithConst::ConvolveWithConst;
18#endif
19
20static const char options1[4][10]={"R2C ES K","R2C M K","R2C P K","R2C EX K"};
21static const char options2[4][10]={"C2R ES K","C2R M K","C2R P K","C2R EX K"};
22
23
25 int length;
27 //bool isR2C;// not ifft.
28 bool operator< (const convParams b) const{return (long)(this->length)*4+(long)(this->optOptim) <
29 (long)(b.length)*4+(long)(b.optOptim);// long should be longer than int here?
30 }
31};
33 TVirtualFFT * fft;
34 TVirtualFFT * ifft;
35 unsigned int refcount;// ++ when CWC init, -- when CWC final, delete when ==0U and CWC final
36 fft2(){fft=nullptr;ifft=nullptr;refcount=0U;}
37
38};
39std::map<ConvolveWithConst::convParams,ConvolveWithConst::fft2> ConvolveWithConst::m_map;
40//const std::string ConvolveWithConst::options1[1]="R2C ES K";
41//const std::string ConvolveWithConst::options1[2]="R2C M K" ;
42//const std::string ConvolveWithConst::options1[3]="R2C P K" ;
43//const std::string ConvolveWithConst::options1[4]="R2C EX K";
44//const std::string ConvolveWithConst::options2[1]="C2R ES K";
45//const std::string ConvolveWithConst::options2[2]="C2R M K" ;
46//const std::string ConvolveWithConst::options2[3]="C2R P K" ;
47//const std::string ConvolveWithConst::options2[4]="C2R EX K";
48
49ConvolveWithConst::ConvolveWithConst(const double* ConstArray,
50 const int ConstArrayLength,const int Blength,
52 m_initialized=false;
53 m_fft=nullptr;
54 m_ifft=nullptr;
55 this->init( ConstArray,
56 ConstArrayLength,Blength,
57 opt, optL);
58 }
59
60void ConvolveWithConst::init(const double* ConstArray,
61 const int ConstArrayLength,const int Blength,
63 if (m_initialized) {
64 std::cout << "CgemDigitizerSvc::ConvolveWithConst::init(): trying to initialize a instance that claimed itself initialized. may cause problem!!!!" << std::endl;
65 return;}// dont initialize it too many times.
66 m_optOptim=opt;
67 m_optLength=optL;
68 m_BLength=Blength;
69 switch(m_optLength){
70 uint32_tt len;
72 len=ConstArrayLength+Blength-1;
73 // Bit Twidding Hack. basically gets a greatest greater 2 power
74 len--;
75 len |= len >> 1;
76 len |= len >> 2;
77 len |= len >> 4;
78 len |= len >> 8;
79 len |= len >> 16;
80 m_length=len+1;
81 break;
83 m_length=ConstArrayLength+Blength-1;
84 break;
85 }
86 std::vector<double> A_tmp;
87
88 convParams pars={m_length,opt};
89 if (0==m_map[pars].fft){
90 m_map[pars].fft =TVirtualFFT::FFT(1, &m_length,options1[opt]);
91 m_map[pars].ifft=TVirtualFFT::FFT(1, &m_length,options2[opt]);
92
93 //std::cout<<"newed: fft at "<<m_map[pars].fft<<std::endl;
94 }
95 m_fft = m_map[pars].fft;
96 m_ifft = m_map[pars].ifft;
97 m_ref = m_map.find(pars);// should be same... as []
98 m_map[pars].refcount++;
99
100 //m_fft=TVirtualFFT::FFT(1, &m_length,"R2C EX K");
101 //m_ifft=TVirtualFFT::FFT(1, &m_length,"C2R EX K");
102
103
104 //m_fft=TVirtualFFT::FFT(1, &m_length,options1[m_optOptim]);
105 //m_ifft=TVirtualFFT::FFT(1, &m_length,options2[m_optOptim]);
106 zeros.clear();
107 zeros.resize(m_length*2);
108 A_fft.resize(m_length*2);
109
110 A_tmp.clear();
111
112 A_tmp.resize(m_length);
113
114
115 double *p_A_fft=&(A_fft.front());
116 double *p_A_tmp=&(A_tmp.front());
117
118 std::memcpy(p_A_tmp,ConstArray,ConstArrayLength*sizeof(double));
119 m_fft->SetPoints(p_A_tmp);
120 m_fft->Transform();
121 m_fft->GetPoints(p_A_fft);
122
123 //m_length=-1;
124 m_initialized=true;
125
126}
128 m_initialized=false;
129 m_fft=nullptr;
130 m_ifft=nullptr;
131}
132
133
135 //std::cout<<"m_fft:"<<m_fft<<" m_ifft:"<<m_ifft<<std::endl;
136 //sometimes due to problem of TVirtualFFT? the TVirtualFFT* is the global fft.
137 // consider rewrite. now we may roughly check if it is on stack
138 //if ((size_t)m_fft < 0x700000000000LU)
139 // delete m_fft;
140 //if ((size_t)m_ifft < 0x700000000000LU)
141 // delete m_ifft;
142 //delete[] A_fft, B_fft,AB_fft;//,out;
143 //std::cout<<"ConvolveWithConst::~ConvolveWithConst(), m_fft="<<m_fft<<" ";
144 if (not (m_fft==nullptr)){
145 m_ref->second.refcount--;
146 //std::cout<<"refcount --; now is "<<m_ref->second.refcount<<" ;";
147 if (m_ref->second.refcount==0){
148 //std::cout<<"thus deleted m_fft="<<m_ref->second.fft<<" ";
149 delete m_ref->second.fft;
150 delete m_ref->second.ifft;
151 m_map.erase(m_ref);
152 }
153 }
154 //std::cout<<std::endl;
155
156}
157/**
158 * @brief do a convolve of stored const A and B, and put results to output.
159 *
160 * @param output address of output, array of double needed since memcpy
161 * @param B array of input B
162 * @param leftindex output is copied from resuts[leftindex]
163 * @param sizeofOut to results[leftindex+sizeofOut], assuming results has indefinite trailing 0
164 * @param factor each value is multiplicated with factor, making output[:]*=factor
165 */
167 const double * B,
168 int leftIndex,int sizeofOut,double factor)const{
169 if (not m_initialized){throw "ConvolveWithConst::convolve: object not initialized";}
170 if (leftIndex > m_length) throw "ConvolveWithConst::convolve: leftIndex"
171 "should not be more than NA+NB-1, as there should be only 0";
172 if (leftIndex <0 ) throw "ConvolveWithConst::convolve: leftIndex should not be negative.";
173 //if (leftIndex + sizeofOut > zeros.size()+m_length) throw "ConvolveWithConst::convolve: leftIndex + sizeofOut too much larger than NA+NB-1";
174 B_tmp.clear();
175 B_tmp.resize(m_length);
176 B_fft.resize(m_length*2);
177 AB_fft.resize(m_length*2);
178
179 double *p_A_fft=&(A_fft.front());
180 double *p_B_fft=&(B_fft.front());
181 double *p_AB_fft=&(AB_fft.front());
182 //double *p_A_tmp=&(A_tmp.front());
183 double *p_B_tmp=&(B_tmp.front());
184 const double *p_zeros=&(zeros.front());
185
186 //std::memcpy(p_A_tmp,A,sizeofA*sizeof(double));// we do clear and memcpy to add "padding" zeros.
187 std::memcpy(p_B_tmp,B,m_BLength*sizeof(double));
188
189 m_fft->SetPoints(p_B_tmp);
190 m_fft->Transform();
191 m_fft->GetPoints(p_B_fft);
192 // the 2 fft just writes the left part,
193 //leaving the right part for us to mirror and conj.
194 //leaving a optimize point.
195
196 for (int i = 0; i < (m_length / 2 + 1); i++) {
197 ((Complex *)p_AB_fft)[i] = ((Complex *)p_A_fft)[i] * ((Complex *)p_B_fft)[i] / (double)m_length * factor; //simple complex product.
198 }
199 for (int i = m_length - 1; i >= (m_length / 2 + 1); i--) {
200 AB_fft[2 * i] = AB_fft[2 * (m_length - i)];
201 AB_fft[2 * i + 1] = -AB_fft[2 * (m_length - i) + 1];// mirror and conj
202 }
203 m_ifft->SetPoints(p_AB_fft);
204 m_ifft->Transform();
205 m_ifft->GetPoints(p_B_tmp);// since B_tmp already used and no longer needed in this session, we reuse this vector.
206 if (leftIndex+sizeofOut <=m_length){
207 std::memcpy(output,(p_B_tmp+leftIndex),sizeofOut*sizeof(double));
208 }
209 else{// add padding 0
210 std::memcpy(output,(p_B_tmp+leftIndex),(m_length-leftIndex)*sizeof(double));
211 while (leftIndex+sizeofOut -m_length > zeros.size()){
212 std::memcpy(output+m_length-leftIndex,(p_zeros),(zeros.size())*sizeof(double));
213 output+=zeros.size();
214 sizeofOut-=zeros.size();
215
216 }
217 std::memcpy(output+m_length-leftIndex,(p_zeros),(leftIndex+sizeofOut -m_length)*sizeof(double));
218 }
219
220}
221/**
222 * @brief multiply with ffted saved results and add them to output with factor;
223 * out += in* SavedConst*factor/L
224 * @param out
225 * @param in
226 * @param factor
227 */
228void ConvolveWithConst::MultiplyAndAdd(ConvolveWithConst::Complex* outHalfPlus1, const ConvolveWithConst::Complex* inHalfPlus1, double factor) const{
229 double *p_A_fft=&(A_fft.front());
230 for (int i = 0; i < (m_length / 2 + 1); i++) {
231 outHalfPlus1[i] += inHalfPlus1[i] * ((Complex *)p_A_fft)[i] / (double)m_length * factor; //simple complex product.
232 }
233}
234//void ConvolveWithConst::destoryAll(){
235// for(std::map<convParams,fft2>::iterator it=m_map.begin();it !=m_map.end();it++){
236//
237// delete it->second.fft;
238// delete it->second.ifft;
239// }
240// m_map.clear();
241//}
242
243/**
244 * @brief Do fft with respect of getLength();
245 *
246 * @param outHalfPlus1
247 * @param inNormalLength
248 * @param LengthOutAsDouble
249 * @param LengthIn
250 */
251void ConvolveWithConst::FFT(ConvolveWithConst::Complex* outHalfPlus1, const double * inNormalLength, int LengthOutAsDouble, int LengthIn) const{
252 if (not m_initialized){cerr<<"ConvolveWithConst::FFT: object not initialized"<<endl; throw "ConvolveWithConst::FFT: object not initialized";}
253 if (LengthOutAsDouble/2 < m_length / 2 +1) {cerr<<"ConvolveWithConst::FFT:LengthOutAsDouble too small" <<endl;throw "LengthOutAsDouble too small";} // opt_Nearst2Pow tested only.
254 B_tmp.clear();
255 B_tmp.resize(m_length);
256 double *p_B_tmp=&(B_tmp.front());
257 std::memcpy(p_B_tmp,inNormalLength,LengthIn*sizeof(double));
258
259 m_fft->SetPoints(p_B_tmp);
260 m_fft->Transform();
261 m_fft->GetPoints((double*)outHalfPlus1);
262}
263/**
264 * @brief Do ifft with respect of getLength();
265 *
266 * @param outHalfPlus1
267 * @param inNormalLength
268 * @param LengthOutAsDouble
269 * @param LengthIn
270 */
271void ConvolveWithConst::IFFT(double* outNormalLength, const ConvolveWithConst::Complex * inHalfPlus1, int lengthOut, int lengthInAsDouble) const{
272 if (not m_initialized){cerr<<"ConvolveWithConst::IFFT: object not initialized"<<endl; throw "ConvolveWithConst::IFFT: object not initialized";}
273 if (lengthInAsDouble/2 < m_length/2+1){ cerr<<"ConvolveWithConst::IFFT:LengthInAsDouble too small"<<endl;throw "LengthInAsDouble too small";}
274 AB_fft.resize(m_length*2);
275 double *p_AB_fft=&(AB_fft.front());
276 B_tmp.clear();
277 B_tmp.resize(m_length);
278 double *p_B_tmp=&(B_tmp.front());
279
280 //for (int i = 0; i < (m_length / 2 + 1); i++) {
281 // ((Complex *)p_AB_fft)[i] = ((Complex *)p_A_fft)[i] * ((Complex *)p_B_fft)[i] / (double)m_length * factor; //simple complex product.
282 //}
283 std::memcpy(p_AB_fft,inHalfPlus1,lengthInAsDouble*sizeof(double));
284 for (int i = m_length - 1; i >= (m_length / 2 + 1); i--) {
285 AB_fft[2 * i] = AB_fft[2 * (m_length - i)];
286 AB_fft[2 * i + 1] = -AB_fft[2 * (m_length - i) + 1];// mirror and conj
287 }
288
289
290
291
292 m_ifft->SetPoints(p_AB_fft);
293 m_ifft->Transform();
294 m_ifft->GetPoints(p_B_tmp);
295 if (lengthOut> m_length)lengthOut = m_length;
296 std::memcpy(outNormalLength,p_B_tmp,lengthOut*sizeof(double));
297
298}
299//void ConvolveWithConst::mirrorAndConjugateInPlace(ConvolveWithConst::Complex * inFullLength,int lengthInAsDouble) const{
300// if (lengthInAsDouble/2 < length) throw std::invalid_argument("LengthInAsDouble too small");
301//
302// for (int i = m_length - 1; i >= (m_length / 2 + 1); i--) {
303// inFullLength[2 * i] = inFullLength[2 * (m_length - i)];
304// inFullLength[2 * i + 1] = -inFullLength[2 * (m_length - i) + 1];// mirror and conj
305// }
306//}
unsigned int uint32_tt
************Class m_alfQCDMZ INTEGER m_KFfin INTEGER m_IVfin INTEGER m_ibox *COMMON c_DZface $ alphaQED at(Q^2=MZ^2) DIZET $ m_alfQCDMZ
*******INTEGER m_nBinMax INTEGER m_NdiMax !No of bins in histogram for cell exploration division $ !Last vertex $ !Last active cell $ !Last cell in buffer $ !No of sampling when dividing cell $ !No of function total $ !Flag for random ceel for $ !Flag for type of for WtMax $ !Flag which decides whether vertices are included in the sampling $ entire domain is hyp !Maximum effective eevents per saves r n generator level $ !Flag for chat level in output
Definition FoamA.h:89
void MultiplyAndAdd(Complex *outHalfPlus1, const Complex *inHalfPlus1, double factor=1) const
multiply with ffted saved results and add them to output with factor; out += in* SavedConst*factor/L
void FFT(Complex *outHalfPlus1, const double *inNormalLength, int LengthOutAsDouble, int LengthIn) const
Do fft with respect of getLength();.
void init(const double *ConstArray, const int ConstArrayLength, const int Blength, TransformOptimOpt opt=opt_EX, TransformLengthOpt optL=opt_AsShortAsPsb)
void convolve(double *output, const double *B, const int leftIndex, const int sizeofOut, double factor=1) const
do a convolve of stored const A and B, and put results to output.
void IFFT(double *outNormalLength, const Complex *inHalfPlus1, int lengthOut, int lengthInAsDouble) const
Do ifft with respect of getLength();.
std::complex< double > Complex
bool operator<(const convParams b) const
ConvolveWithConst::TransformOptimOpt optOptim