source: Sophya/trunk/SophyaLib/SkyMap/spherehealpix.cc@ 2763

Last change on this file since 2763 was 2615, checked in by cmv, 21 years ago

using namespace sophya enleve de machdefs.h, nouveau sopnamsp.h cmv 10/09/2004

File size: 17.8 KB
Line 
1#include "sopnamsp.h"
2#include "machdefs.h"
3#include <math.h>
4#include <complex>
5
6#include "pexceptions.h"
7#include "fiondblock.h"
8#include "spherehealpix.h"
9#include "strutil.h"
10
11extern "C"
12{
13#include <stdio.h>
14#include <stdlib.h>
15#include <unistd.h>
16}
17
18using namespace SOPHYA;
19
20/*!
21 \class SOPHYA::SphereHEALPix
22 \ingroup SkyMap
23 Class implementing spherical maps, in the HEALPix pixelisation scheme,
24 with template data types (double, float, complex, ...)
25
26
27\verbatim
28
29 -----------------------------------------------------------------------
30 version 0.8.2 Aug97 TAC Eric Hivon, Kris Gorski
31 -----------------------------------------------------------------------
32
33 the sphere is split in 12 diamond-faces containing nside**2 pixels each
34 the numbering of the pixels (in the nested scheme) is similar to
35 quad-cube
36 In each face the first pixel is in the lowest corner of the diamond
37 the faces are (x,y) coordinate on each face
38
39 . . . . <--- North Pole
40 / \ / \ / \ / \ ^ ^
41 . 0 . 1 . 2 . 3 . <--- z = 2/3 \ /
42 \ / \ / \ / \ / y \ / x
43 4 . 5 . 6 . 7 . 4 <--- equator \ /
44 / \ / \ / \ / \ \/
45 . 8 . 9 .10 .11 . <--- z = -2/3 (0,0) : lowest corner
46 \ / \ / \ / \ /
47 . . . . <--- South Pole
48\endverbatim
49 phi:0 2Pi
50
51 in the ring scheme pixels are numbered along the parallels
52 the first parallel is the one closest to the north pole and so on
53 on each parallel, pixels are numbered starting from the one closest
54 to phi = 0
55
56 nside MUST be a power of 2 (<= 8192)
57
58*/
59
60/* --Methode-- */
61
62template<class T>
63SphereHEALPix<T>::SphereHEALPix() : pixels_(), sliceBeginIndex_(),
64 sliceLenght_()
65
66
67{
68 InitNul();
69}
70
71/*! \fn SOPHYA::SphereHEALPix::SphereHEALPix(int_4 m)
72
73 \param <m> : "nside" of the Healpix algorithm
74
75 The total number of pixels will be Npix = 12*nside**2
76
77 nside MUST be a power of 2 (<= 8192)
78*/
79
80template<class T>
81SphereHEALPix<T>::SphereHEALPix(int_4 m)
82
83{
84
85 if(m <= 0 || m > 8192)
86 {
87 cout << "SphereHEALPix : m hors bornes [0,8192], m= " << m << endl;
88 throw RangeCheckError("SphereHEALPix<T>::SphereHEALPix() - Out of bound nside (< 8192)!");
89 }
90 // verifier que m est une puissance de deux
91 int x= m;
92 while(x%2 == 0) x/=2;
93 if(x != 1)
94 {
95 cout<<"SphereHEALPix: m doit etre une puissance de deux, m= "<<m<<endl;
96 throw ParmError("SphereHEALPix<T>::SphereHEALPix() - nside != 2^n !");
97 }
98 InitNul();
99 Pixelize(m);
100 SetThetaSlices();
101}
102//++
103template<class T>
104SphereHEALPix<T>::SphereHEALPix(const SphereHEALPix<T>& s, bool share)
105 : pixels_(s.pixels_, share), sliceBeginIndex_(s.sliceBeginIndex_, share),
106 sliceLenght_(s.sliceLenght_, share)
107// copy constructor
108//--
109{
110 nSide_= s.nSide_;
111 nPix_ = s.nPix_;
112 omeg_ = s.omeg_;
113 if(s.mInfo_) mInfo_= new DVList(*s.mInfo_);
114}
115//++
116template<class T>
117SphereHEALPix<T>::SphereHEALPix(const SphereHEALPix<T>& s)
118 : pixels_(s.pixels_), sliceBeginIndex_(s.sliceBeginIndex_),
119 sliceLenght_(s.sliceLenght_)
120// copy constructor
121//--
122{
123 nSide_= s.nSide_;
124 nPix_ = s.nPix_;
125 omeg_ = s.omeg_;
126 if(s.mInfo_) mInfo_= new DVList(*s.mInfo_);
127 // CloneOrShare(s);
128}
129
130//! Clone if \b a is not temporary, share if temporary
131/*! \sa NDataBlock::CloneOrShare(const NDataBlock<T>&) */
132template<class T>
133void SphereHEALPix<T>::CloneOrShare(const SphereHEALPix<T>& a)
134{
135 nSide_= a.nSide_;
136 nPix_ = a.nPix_;
137 omeg_ = a.omeg_;
138 pixels_.CloneOrShare(a.pixels_);
139 sliceBeginIndex_.CloneOrShare(a.sliceBeginIndex_);
140 sliceLenght_.CloneOrShare(a.sliceLenght_);
141 if (mInfo_) {delete mInfo_; mInfo_ = NULL;}
142 if (a.mInfo_) mInfo_ = new DVList(*(a.mInfo_));
143}
144
145//! Share data with a
146template<class T>
147void SphereHEALPix<T>::Share(const SphereHEALPix<T>& a)
148{
149 nSide_= a.nSide_;
150 nPix_ = a.nPix_;
151 omeg_ = a.omeg_;
152 pixels_.Share(a.pixels_);
153 sliceBeginIndex_.Share(a.sliceBeginIndex_);
154 sliceLenght_.Share(a.sliceLenght_);
155 if (mInfo_) {delete mInfo_; mInfo_ = NULL;}
156 if (a.mInfo_) mInfo_ = new DVList(*(a.mInfo_));
157}
158
159////////////////////////// methodes de copie/share
160template<class T>
161SphereHEALPix<T>& SphereHEALPix<T>::Set(const SphereHEALPix<T>& a)
162{
163 if (this != &a)
164 {
165
166 if (a.NbPixels() < 1)
167 throw RangeCheckError("SphereHEALPix<T>::Set(a ) - SphereHEALPix a not allocated ! ");
168 if (NbPixels() < 1) CloneOrShare(a);
169 else CopyElt(a);
170
171
172 if (mInfo_) delete mInfo_;
173 mInfo_ = NULL;
174 if (a.mInfo_) mInfo_ = new DVList(*(a.mInfo_));
175 }
176 return(*this);
177}
178
179template<class T>
180SphereHEALPix<T>& SphereHEALPix<T>::CopyElt(const SphereHEALPix<T>& a)
181{
182 if (NbPixels() < 1)
183 throw RangeCheckError("SphereHEALPix<T>::CopyElt(const SphereHEALPix<T>& ) - Not Allocated SphereHEALPix ! ");
184 if (NbPixels() != a.NbPixels())
185 throw(SzMismatchError("SphereHEALPix<T>::CopyElt(const SphereHEALPix<T>&) SizeMismatch")) ;
186 nSide_= a.nSide_;
187 nPix_ = a.nPix_;
188 omeg_ = a.omeg_;
189 int k;
190 for (k=0; k< nPix_; k++) pixels_(k) = a.pixels_(k);
191 for (k=0; k< a.sliceBeginIndex_.Size(); k++) sliceBeginIndex_(k) = a.sliceBeginIndex_(k);
192 for (k=0; k< a.sliceLenght_.Size(); k++) sliceLenght_(k) = a.sliceLenght_(k);
193 return(*this);
194}
195
196
197
198//++
199// Titre Destructor
200//--
201//++
202template<class T>
203SphereHEALPix<T>::~SphereHEALPix()
204
205//--
206{
207}
208
209//++
210// Titre Public Methods
211//--
212
213/*! \fn void SOPHYA::SphereHEALPix::Resize(int_4 m)
214 \param <m> "nside" of the Gorski algorithm
215
216 The total number of pixels will be Npix = 12*nside**2
217
218 nside MUST be a power of 2 (<= 8192)
219*/
220template<class T>
221void SphereHEALPix<T>::Resize(int_4 m)
222
223
224{
225 if (m<=0 || m> 8192) {
226 cout << "SphereHEALPix : m hors bornes [0,8192], m= " << m << endl;
227 exit(1);
228 }
229 // verifier que m est une puissance de deux
230 int x= m;
231 while (x%2==0) x/=2;
232 if(x != 1)
233 {
234 cout<<"SphereHEALPix: m doit etre une puissance de deux, m= "<<m<<endl;
235 exit(1);
236 }
237 InitNul();
238 Pixelize(m);
239 SetThetaSlices();
240}
241
242template<class T>
243void SphereHEALPix<T>::Pixelize( int_4 m)
244
245// prépare la pixelisation Gorski (m a la même signification
246// que pour le constructeur)
247//
248//
249{
250 // On memorise les arguments d'appel
251 nSide_= m;
252
253 // Nombre total de pixels sur la sphere entiere
254 nPix_= 12*nSide_*nSide_;
255
256 // pour le moment les tableaux qui suivent seront ranges dans l'ordre
257 // de l'indexation GORSKY "RING"
258 // on pourra ulterieurement changer de strategie et tirer profit
259 // de la dualite d'indexation GORSKY (RING et NEST) : tout dependra
260 // de pourquoi c'est faire
261
262 // Creation et initialisation du vecteur des contenus des pixels
263 pixels_.ReSize(nPix_);
264 pixels_.Reset();
265
266 // solid angle per pixel
267 omeg_= 4.0*Pi/nPix_;
268}
269
270template<class T>
271void SphereHEALPix<T>::InitNul()
272//
273// initialise à zéro les variables de classe
274{
275 nSide_= 0;
276 nPix_ = 0;
277 omeg_ = 0.;
278// pixels_.Reset(); - Il ne faut pas mettre les pixels a zero si share !
279}
280
281/* --Methode-- */
282/* Nombre de pixels du decoupage */
283/*! \fn int_4 SOPHYA::SphereHEALPix::NbPixels() const
284
285 Return number of pixels of the splitting
286*/
287template<class T>
288int_4 SphereHEALPix<T>::NbPixels() const
289{
290 return(nPix_);
291}
292
293
294/*! \fn uint_4 SOPHYA::SphereHEALPix::NbThetaSlices() const
295
296 \return number of slices in theta direction on the sphere
297*/
298template<class T>
299uint_4 SphereHEALPix<T>::NbThetaSlices() const
300{
301 uint_4 nbslices = uint_4(4*nSide_-1);
302 if (nSide_<=0)
303 {
304 nbslices = 0;
305 throw PException(" sphere not pixelized, NbSlice=0 ");
306 }
307 return nbslices;
308}
309
310/*! \fn void SOPHYA::SphereHEALPix::GetThetaSlice(int_4 index,r_8& theta,TVector<r_8>& phi,TVector<T>& value) const
311
312 For a theta-slice with index 'index', return :
313
314 the corresponding "theta"
315
316 a vector containing the phi's of the pixels of the slice
317
318 a vector containing the corresponding values of pixels
319*/
320template<class T>
321void SphereHEALPix<T>::GetThetaSlice(int_4 index,r_8& theta,TVector<r_8>& phi,TVector<T>& value) const
322
323{
324
325 if (index<0 || index >= NbThetaSlices())
326 {
327 cout << " SphereHEALPix::GetThetaSlice : Pixel index out of range" <<endl;
328 throw RangeCheckError(" SphereHEALPix::GetThetaSlice : Pixel index out of range");
329 }
330
331
332 int_4 iring= sliceBeginIndex_(index);
333 int_4 lring = sliceLenght_(index);
334
335 phi.ReSize(lring);
336 value.ReSize(lring);
337
338 double TH= 0.;
339 double FI= 0.;
340 for(int_4 kk = 0; kk < lring;kk++)
341 {
342 PixThetaPhi(kk+iring,TH,FI);
343 phi(kk)= FI;
344 value(kk)= PixVal(kk+iring);
345 }
346 theta= TH;
347}
348/*! \fn void SOPHYA::SphereHEALPix::GetThetaSlice(int_4 sliceIndex,r_8& theta, r_8& phi0, TVector<int_4>& pixelIndices,TVector<T>& value) const
349
350 For a theta-slice with index 'index', return :
351
352 the corresponding "theta"
353
354 the corresponding "phi" for first pixel of the slice
355
356 a vector containing indices of the pixels of the slice
357
358 (equally distributed in phi)
359
360 a vector containing the corresponding values of pixels
361*/
362
363template<class T>
364void SphereHEALPix<T>::GetThetaSlice(int_4 sliceIndex,r_8& theta, r_8& phi0, TVector<int_4>& pixelIndices,TVector<T>& value) const
365
366{
367
368 if (sliceIndex<0 || sliceIndex >= NbThetaSlices())
369 {
370 cout << " SphereHEALPix::GetThetaSlice : Pixel index out of range" <<endl;
371 throw RangeCheckError(" SphereHEALPix::GetThetaSlice : Pixel index out of range");
372 }
373 int_4 iring= sliceBeginIndex_(sliceIndex);
374 int_4 lring = sliceLenght_(sliceIndex);
375 pixelIndices.ReSize(lring);
376 value.ReSize(lring);
377
378 for(int_4 kk = 0; kk < lring;kk++)
379 {
380 pixelIndices(kk)= kk+iring;
381 value(kk)= PixVal(kk+iring);
382 }
383 PixThetaPhi(iring, theta, phi0);
384}
385
386template<class T>
387void SphereHEALPix<T>::SetThetaSlices()
388{
389 sliceBeginIndex_.ReSize(4*nSide_-1);
390 sliceLenght_.ReSize(4*nSide_-1);
391 int sliceIndex;
392 for (sliceIndex=0; sliceIndex< nSide_-1; sliceIndex++)
393 {
394 sliceBeginIndex_(sliceIndex) = 2*sliceIndex*(sliceIndex+1);
395 sliceLenght_(sliceIndex) = 4*(sliceIndex+1);
396 }
397 for (sliceIndex= nSide_-1; sliceIndex< 3*nSide_; sliceIndex++)
398 {
399 sliceBeginIndex_(sliceIndex) = 2*nSide_*(2*sliceIndex-nSide_+1);
400 sliceLenght_(sliceIndex) = 4*nSide_;
401 }
402 for (sliceIndex= 3*nSide_; sliceIndex< 4*nSide_-1; sliceIndex++)
403 {
404 int_4 nc= 4*nSide_-1-sliceIndex;
405 sliceBeginIndex_(sliceIndex) = nPix_-2*nc*(nc+1);
406 sliceLenght_(sliceIndex) = 4*nc;
407 }
408}
409
410
411/*! \fn T& SOPHYA::SphereHEALPix::PixVal(int_4 k)
412
413 \return value of pixel with "RING" index k
414*/
415template<class T>
416T& SphereHEALPix<T>::PixVal(int_4 k)
417
418{
419 if((k < 0) || (k >= nPix_))
420 {
421 throw RangeCheckError("SphereHEALPix::PIxVal Pixel index out of range");
422 }
423 return pixels_(k);
424}
425
426/*! \fn T const& SOPHYA::SphereHEALPix::PixVal(int_4 k) const
427
428 \return value of pixel with "RING" index k
429*/
430template<class T>
431T const& SphereHEALPix<T>::PixVal(int_4 k) const
432
433{
434 if((k < 0) || (k >= nPix_))
435 {
436 throw RangeCheckError("SphereHEALPix::PIxVal Pixel index out of range");
437 }
438 return *(pixels_.Data()+k);
439}
440
441/*! \fn T& SOPHYA::SphereHEALPix::PixValNest(int_4 k)
442
443 \return value of pixel with "NESTED" index k
444*/
445template<class T>
446T& SphereHEALPix<T>::PixValNest(int_4 k)
447
448//--
449{
450 if((k < 0) || (k >= nPix_))
451 {
452 throw RangeCheckError("SphereHEALPix::PIxValNest Pixel index out of range");
453 }
454 return pixels_(nest2ring(nSide_,k));
455}
456
457/*! \fn T const& SOPHYA::SphereHEALPix::PixValNest(int_4 k) const
458
459 \return value of pixel with "NESTED" index k
460*/
461
462template<class T>
463T const& SphereHEALPix<T>::PixValNest(int_4 k) const
464
465{
466 if((k < 0) || (k >= nPix_))
467 {
468 throw RangeCheckError("SphereHEALPix::PIxValNest Pixel index out of range");
469 }
470 int_4 pix= nest2ring(nSide_,k);
471 return *(pixels_.Data()+pix);
472}
473
474/*! \fn bool SOPHYA::SphereHEALPix::ContainsSph(double theta, double phi) const
475
476\return true if teta,phi in map
477*/
478template<class T>
479bool SphereHEALPix<T>::ContainsSph(double theta, double phi) const
480{
481return(true);
482}
483
484/*! \fn int_4 SOPHYA::SphereHEALPix::PixIndexSph(double theta,double phi) const
485
486 \return "RING" index of the pixel corresponding to direction (theta, phi).
487 */
488template<class T>
489int_4 SphereHEALPix<T>::PixIndexSph(double theta,double phi) const
490
491{
492 return ang2pix_ring(nSide_,theta,phi);
493}
494
495/*! \fn int_4 SOPHYA::SphereHEALPix::PixIndexSphNest(double theta,double phi) const
496
497 \return "NESTED" index of the pixel corresponding to direction (theta, phi).
498 */
499template<class T>
500int_4 SphereHEALPix<T>::PixIndexSphNest(double theta,double phi) const
501
502{
503 return ang2pix_nest(nSide_,theta,phi);
504}
505
506
507/* --Methode-- */
508/*! \fn void SOPHYA::SphereHEALPix::PixThetaPhi(int_4 k,double& theta,double& phi) const
509 \return (theta,phi) coordinates of middle of pixel with "RING" index k
510 */
511template<class T>
512void SphereHEALPix<T>::PixThetaPhi(int_4 k,double& theta,double& phi) const
513{
514 pix2ang_ring(nSide_,k,theta,phi);
515}
516
517/*! \fn T SOPHYA::SphereHEALPix::SetPixels(T v)
518
519Set all pixels to value v
520*/
521template <class T>
522T SphereHEALPix<T>::SetPixels(T v)
523{
524pixels_.Reset(v);
525return(v);
526}
527
528
529
530/*! \fn void SOPHYA::SphereHEALPix::PixThetaPhiNest(int_4 k,double& theta,double& phi) const
531
532 \return (theta,phi) coordinates of middle of pixel with "NESTED" index k
533 */
534template<class T>
535void SphereHEALPix<T>::PixThetaPhiNest(int_4 k,double& theta,double& phi) const
536
537{
538 pix2ang_nest(nSide_,k,theta,phi);
539}
540
541
542/*! \fn int_4 SOPHYA::SphereHEALPix::NestToRing(int_4 k) const
543
544 translation from NESTED index into RING index
545*/
546template<class T>
547int_4 SphereHEALPix<T>::NestToRing(int_4 k) const
548
549{
550 return nest2ring(nSide_,k);
551}
552
553
554/*! \fn int_4 SOPHYA::SphereHEALPix::RingToNest(int_4 k) const
555
556 translation from RING index into NESTED index
557*/
558template<class T>
559int_4 SphereHEALPix<T>::RingToNest(int_4 k) const
560{
561 return ring2nest(nSide_,k);
562}
563
564// ...... Operations de calcul ......
565
566//! Fill a SphereHEALPix with a constant value \b a
567template <class T>
568SphereHEALPix<T>& SphereHEALPix<T>::SetT(T a)
569{
570 if (NbPixels() < 1)
571 throw RangeCheckError("SphereHEALPix<T>::SetT(T ) - SphereHEALPix not dimensionned ! ");
572 pixels_ = a;
573 return (*this);
574}
575
576/*! Add a constant value \b x to a SphereHEALPix */
577template <class T>
578SphereHEALPix<T>& SphereHEALPix<T>::Add(T a)
579 {
580 cout << " c'est mon Add " << endl;
581 if (NbPixels() < 1)
582 throw RangeCheckError("SphereHEALPix<T>::Add(T ) - SphereHEALPix not dimensionned ! ");
583 // pixels_ += a;
584 pixels_.Add(a);
585 return (*this);
586}
587
588/*! Substract a constant value \b a to a SphereHEALPix */
589template <class T>
590SphereHEALPix<T>& SphereHEALPix<T>::Sub(T a,bool fginv)
591{
592 if (NbPixels() < 1)
593 throw RangeCheckError("SphereHEALPix<T>::Sub(T ) - SphereHEALPix not dimensionned ! ");
594 pixels_.Sub(a,fginv);
595 return (*this);
596}
597
598/*! multiply a SphereHEALPix by a constant value \b a */
599template <class T>
600SphereHEALPix<T>& SphereHEALPix<T>::Mul(T a)
601{
602 if (NbPixels() < 1)
603 throw RangeCheckError("SphereHEALPix<T>::Mul(T ) - SphereHEALPix not dimensionned ! ");
604 pixels_ *= a;
605 return (*this);
606}
607
608/*! divide a SphereHEALPix by a constant value \b a */
609template <class T>
610SphereHEALPix<T>& SphereHEALPix<T>::Div(T a)
611{
612 if (NbPixels() < 1)
613 throw RangeCheckError("SphereHEALPix<T>::Div(T ) - SphereHEALPix not dimensionned ! ");
614 pixels_ /= a;
615 return (*this);
616}
617
618// >>>> Operations avec 2nd membre de type SphereHEALPix
619//! Add two SphereHEALPix
620
621template <class T>
622SphereHEALPix<T>& SphereHEALPix<T>::AddElt(const SphereHEALPix<T>& a)
623{
624 if (NbPixels() != a.NbPixels() )
625 {
626 throw(SzMismatchError("SphereHEALPix<T>::AddElt(const SphereHEALPix<T>&) SizeMismatch")) ;
627 }
628 pixels_ += a.pixels_;
629 return (*this);
630}
631
632//! Substract two SphereHEALPix
633template <class T>
634SphereHEALPix<T>& SphereHEALPix<T>::SubElt(const SphereHEALPix<T>& a)
635{
636 if (NbPixels() != a.NbPixels() )
637 {
638 throw(SzMismatchError("SphereHEALPix<T>::SubElt(const SphereHEALPix<T>&) SizeMismatch")) ;
639 }
640 pixels_ -= a.pixels_;
641 return (*this);
642}
643
644//! Multiply two SphereHEALPix (elements by elements)
645template <class T>
646SphereHEALPix<T>& SphereHEALPix<T>::MulElt(const SphereHEALPix<T>& a)
647{
648 if (NbPixels() != a.NbPixels() )
649 {
650 throw(SzMismatchError("SphereHEALPix<T>::MulElt(const SphereHEALPix<T>&) SizeMismatch")) ;
651 }
652 pixels_ *= a.pixels_;
653 return (*this);
654}
655
656//! Divide two SphereHEALPix (elements by elements) - No protection for divide by 0
657template <class T>
658SphereHEALPix<T>& SphereHEALPix<T>::DivElt(const SphereHEALPix<T>& a)
659{
660 if (NbPixels() != a.NbPixels() )
661 {
662 throw(SzMismatchError("SphereHEALPix<T>::DivElt(const SphereHEALPix<T>&) SizeMismatch")) ;
663 }
664 pixels_ /= a.pixels_;
665 return (*this);
666}
667
668
669
670
671template <class T>
672void SphereHEALPix<T>::print(ostream& os) const
673{
674 if(mInfo_) os << " DVList Info= " << *mInfo_ << endl;
675 //
676 os << " nSide_ = " << nSide_ << endl;
677 os << " nPix_ = " << nPix_ << endl;
678 os << " omeg_ = " << omeg_ << endl;
679
680 os << " content of pixels : ";
681 for(int i=0; i < nPix_; i++)
682 {
683 if(i%5 == 0) os << endl;
684 os << pixels_(i) <<", ";
685 }
686 os << endl;
687
688
689}
690
691
692
693//*******************************************************************
694
695#ifdef __CXX_PRAGMA_TEMPLATES__
696#pragma define_template SphereHEALPix<uint_2>
697#pragma define_template SphereHEALPix<int_4>
698#pragma define_template SphereHEALPix<r_8>
699#pragma define_template SphereHEALPix<r_4>
700#pragma define_template SphereHEALPix< complex<r_4> >
701#pragma define_template SphereHEALPix< complex<r_8> >
702#endif
703#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
704template class SphereHEALPix<uint_2>;
705template class SphereHEALPix<int_4>;
706template class SphereHEALPix<r_8>;
707template class SphereHEALPix<r_4>;
708template class SphereHEALPix< complex<r_4> >;
709template class SphereHEALPix< complex<r_8> >;
710#endif
711
Note: See TracBrowser for help on using the repository browser.