Imported healpix tree

This commit is contained in:
Guilhem Lavaux 2012-10-30 13:56:48 -04:00
parent 4182c30485
commit 4bfb62f177
136 changed files with 26534 additions and 0 deletions

632
external/healpix/cxxsupport/arr.h vendored Normal file
View file

@ -0,0 +1,632 @@
/*
* This file is part of libcxxsupport.
*
* libcxxsupport is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* libcxxsupport is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with libcxxsupport; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik
* and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
* (DLR).
*/
/*! \file arr.h
* Various high-performance array classes used by the Planck LevelS package.
*
* Copyright (C) 2002 - 2010 Max-Planck-Society
* \author Martin Reinecke
*/
#ifndef PLANCK_ARR_H
#define PLANCK_ARR_H
#include <algorithm>
#include <cstdlib>
#include "cxxutils.h"
/*! \defgroup arraygroup Array classes */
/*! \{ */
template <typename T> class normalAlloc__
{
public:
T *alloc(tsize sz) const { return (sz>0) ? new T[sz] : 0; }
void dealloc (T *ptr) const { delete[] ptr; }
};
template <typename T, int align> class alignAlloc__
{
public:
T *alloc(tsize sz) const
{
using namespace std;
if (sz==0) return 0;
void *res;
planck_assert(posix_memalign(&res,align,sz*sizeof(T))==0,
"error in posix_memalign()");
return static_cast<T *>(res);
}
void dealloc(T *ptr) const
{
using namespace std;
if (ptr) free(ptr);
}
};
/*! View of a 1D array */
template <typename T> class arr_ref
{
protected:
tsize s;
T *d;
public:
/*! Constructs an \a arr_ref of size \a s_, starting at \a d_. */
arr_ref(T *d_, tsize s_) : s(s_),d(d_) {}
/*! Returns the current array size. */
tsize size() const { return s; }
/*! Writes \a val into every element of the array. */
void fill (const T &val)
{ for (tsize m=0; m<s; ++m) d[m]=val; }
/*! Returns a reference to element \a n */
template<typename T2> T &operator[] (T2 n) {return d[n];}
/*! Returns a constant reference to element \a n */
template<typename T2> const T &operator[] (T2 n) const {return d[n];}
/*! Returns a pointer to the first array element, or NULL if the array
is zero-sized. */
T *begin() { return d; }
/*! Returns a pointer to the one-past-last array element, or NULL if the
array is zero-sized. */
T *end() { return d+s; }
/*! Returns a constant pointer to the first array element, or NULL if the
array is zero-sized. */
const T *begin() const { return d; }
/*! Returns a constant pointer to the one-past-last array element, or NULL
if the array is zero-sized. */
const T *end() const { return d+s; }
/*! Copies all array elements to \a ptr. */
template<typename T2> void copyToPtr (T *ptr) const
{ for (tsize m=0; m<s; ++m) ptr[m]=d[m]; }
/*! Sorts the elements in the array, in ascending order. */
void sort()
{ std::sort (d,d+s); }
/*! Sorts the elements in the array, such that \a comp(d[i],d[j])==true
for \a i<j. */
template<typename Comp> void sort(Comp comp)
{ std::sort (d,d+s,comp); }
/*! Helper function for linear interpolation (or extrapolation).
\a idx and \a val are computed such that
\a val=d[idx]+frac*(d[idx+1]-d[idx]). If \a val<d[0], \a frac will be
negative, if \a val>d[s-1], frac will be larger than 1. In all other
cases \a 0<=frac<=1.
The array must be ordered in ascending order; no two values may be
equal. */
void interpol_helper (const T &val, tsize &idx, double &frac) const
{ ::interpol_helper (d, d+s, val, idx, frac); }
/*! Helper function for linear interpolation (or extrapolation).
\a idx and \a val are computed such that
\a val=d[idx]+frac*(d[idx+1]-d[idx]). If \a comp(val,d[0])==true,
\a frac will be negative, if \a comp(val,d[s-1])==false, frac will be
larger than 1. In all other cases \a 0<=frac<=1.
The array must be ordered such that \a comp(d[i],d[j])==true
for \a i<j; no two values may be equal. */
template<typename Comp> void interpol_helper (const T &val, Comp comp,
tsize &idx, double &frac) const
{ ::interpol_helper (d, d+s, val, comp, idx, frac); }
/*! Returns the minimum and maximum entry in \a minv and \a maxv,
respectively. Throws an exception if the array is zero-sized. */
void minmax (T &minv, T &maxv) const
{
planck_assert(s>0,"trying to find min and max of a zero-sized array");
minv=maxv=d[0];
for (tsize m=1; m<s; ++m)
{
if (d[m]<minv) minv=d[m];
else if (d[m]>maxv) maxv=d[m];
}
}
/*! Returns \a true, if \a val is found in the array, else \a false. */
bool contains (const T &val) const
{
for (tsize m=0; m<s; ++m)
if (d[m]==val) return true;
return false;
}
/*! Returns the index of the first occurrence of \a val in the array.
If it is not found, an exception is thrown. */
tsize find (const T &val) const
{
for (tsize m=0; m<s; ++m)
if (d[m]==val) return m;
planck_fail ("entry '"+dataToString(val)+"' not found in array");
}
};
/*! An array whose size is known at compile time. Very useful for storing
small arrays on the stack, without need for \a new and \a delete(). */
template <typename T, tsize sz> class fix_arr
{
private:
T d[sz];
public:
/*! Returns the size of the array. */
tsize size() const { return sz; }
/*! Returns a reference to element \a n */
template<typename T2> T &operator[] (T2 n) {return d[n];}
/*! Returns a constant reference to element \a n */
template<typename T2> const T &operator[] (T2 n) const {return d[n];}
};
/*! One-dimensional array type, with selectable storage management. */
template <typename T, typename storageManager> class arrT: public arr_ref<T>
{
private:
storageManager stm;
bool own;
void reset()
{ this->d=0; this->s=0; own=true; }
public:
/*! Creates a zero-sized array. */
arrT() : arr_ref<T>(0,0), own(true) {}
/*! Creates an array with \a sz entries. */
arrT(tsize sz) : arr_ref<T>(stm.alloc(sz),sz), own(true) {}
/*! Creates an array with \a sz entries, and initializes them with
\a inival. */
arrT(tsize sz, const T &inival) : arr_ref<T>(stm.alloc(sz),sz), own(true)
{ arr_ref<T>::fill(inival); }
/*! Creates an array with \a sz entries, which uses the memory pointed
to by \a ptr.
\note \a ptr will <i>not</i> be deallocated by the destructor.
\warning Only use this if you REALLY know what you are doing.
In particular, this is only safely usable if
<ul>
<li>\a T is a POD type</li>
<li>\a ptr survives during the lifetime of the array object</li>
<li>\a ptr is not subject to garbage collection</li>
</ul>
Other restrictions may apply. You have been warned. */
arrT (T *ptr, tsize sz): arr_ref<T>(ptr,sz), own(false) {}
/*! Creates an array which is a copy of \a orig. The data in \a orig
is duplicated. */
arrT (const arrT &orig): arr_ref<T>(stm.alloc(orig.s),orig.s), own(true)
{ for (tsize m=0; m<this->s; ++m) this->d[m] = orig.d[m]; }
/*! Frees the memory allocated by the object. */
~arrT() { if (own) stm.dealloc(this->d); }
/*! Allocates space for \a sz elements. The content of the array is
undefined on exit. \a sz can be 0. If \a sz is the
same as the current size, no reallocation is performed. */
void alloc (tsize sz)
{
if (sz==this->s) return;
if (own) stm.dealloc(this->d);
this->s = sz;
this->d = stm.alloc(sz);
own = true;
}
/*! Allocates space for \a sz elements. If \a sz is the
same as the current size, no reallocation is performed.
All elements are set to \a inival. */
void allocAndFill (tsize sz, const T &inival)
{ alloc(sz); this->fill(inival); }
/*! Deallocates the memory held by the array, and sets the array size
to 0. */
void dealloc() {if (own) stm.dealloc(this->d); reset();}
/*! Changes the array to be a copy of \a orig. */
arrT &operator= (const arrT &orig)
{
if (this==&orig) return *this;
alloc (orig.s);
for (tsize m=0; m<this->s; ++m) this->d[m] = orig.d[m];
return *this;
}
/*! Reserves space for \a sz elements, then copies \a sz elements
from \a ptr into the array. */
template<typename T2> void copyFromPtr (const T2 *ptr, tsize sz)
{
alloc(sz);
for (tsize m=0; m<this->s; ++m) this->d[m]=ptr[m];
}
/*! Assigns the contents and size of \a other to the array.
\note On exit, \a other is zero-sized! */
void transfer (arrT &other)
{
if (own) stm.dealloc(this->d);
this->d=other.d;
this->s=other.s;
own=other.own;
other.reset();
}
/*! Swaps contents and size with \a other. */
void swap (arrT &other)
{
std::swap(this->d,other.d);
std::swap(this->s,other.s);
std::swap(own,other.own);
}
};
/*! One-dimensional array type. */
template <typename T>
class arr: public arrT<T,normalAlloc__<T> >
{
public:
/*! Creates a zero-sized array. */
arr() : arrT<T,normalAlloc__<T> >() {}
/*! Creates an array with \a sz entries. */
arr(tsize sz) : arrT<T,normalAlloc__<T> >(sz) {}
/*! Creates an array with \a sz entries, and initializes them with
\a inival. */
arr(tsize sz, const T &inival) : arrT<T,normalAlloc__<T> >(sz,inival) {}
/*! Creates an array with \a sz entries, which uses the memory pointed
to by \a ptr.
\note \a ptr will <i>not</i> be deallocated by the destructor.
\warning Only use this if you REALLY know what you are doing.
In particular, this is only safely usable if
<ul>
<li>\a T is a POD type</li>
<li>\a ptr survives during the lifetime of the array object</li>
<li>\a ptr is not subject to garbage collection</li>
</ul>
Other restrictions may apply. You have been warned. */
arr (T *ptr, tsize sz): arrT<T,normalAlloc__<T> >(ptr,sz) {}
};
/*! One-dimensional array type, with selectable storage alignment. */
template <typename T, int align>
class arr_align: public arrT<T,alignAlloc__<T,align> >
{
public:
/*! Creates a zero-sized array. */
arr_align() : arrT<T,alignAlloc__<T,align> >() {}
/*! Creates an array with \a sz entries. */
arr_align(tsize sz) : arrT<T,alignAlloc__<T,align> >(sz) {}
/*! Creates an array with \a sz entries, and initializes them with
\a inival. */
arr_align(tsize sz, const T &inival)
: arrT<T,alignAlloc__<T,align> >(sz,inival) {}
};
/*! Two-dimensional array type, with selectable storage management.
The storage ordering is the same as in C.
An entry is located by address arithmetic, not by double dereferencing.
The indices start at zero. */
template <typename T, typename storageManager> class arr2T
{
private:
tsize s1, s2;
arrT<T, storageManager> d;
public:
/*! Creates a zero-sized array. */
arr2T() : s1(0), s2(0) {}
/*! Creates an array with the dimensions \a sz1 and \a sz2. */
arr2T(tsize sz1, tsize sz2)
: s1(sz1), s2(sz2), d(s1*s2) {}
/*! Creates an array with the dimensions \a sz1 and \a sz2
and initializes them with \a inival. */
arr2T(tsize sz1, tsize sz2, const T &inival)
: s1(sz1), s2(sz2), d (s1*s2)
{ fill(inival); }
/*! Creates the array as a copy of \a orig. */
arr2T(const arr2T &orig)
: s1(orig.s1), s2(orig.s2), d(orig.d) {}
/*! Frees the memory associated with the array. */
~arr2T() {}
/*! Returns the first array dimension. */
tsize size1() const { return s1; }
/*! Returns the second array dimension. */
tsize size2() const { return s2; }
/*! Returns the total array size, i.e. the product of both dimensions. */
tsize size () const { return s1*s2; }
/*! Allocates space for an array with \a sz1*sz2 elements.
The content of the array is undefined on exit.
\a sz1 or \a sz2 can be 0. If \a sz1*sz2 is the same as the
currently allocated space, no reallocation is performed. */
void alloc (tsize sz1, tsize sz2)
{
if (sz1*sz2 != d.size())
d.alloc(sz1*sz2);
s1=sz1; s2=sz2;
}
/*! Allocates space for an array with \a sz1*sz2 elements.
All elements are set to \a inival.
\a sz1 or \a sz2 can be 0. If \a sz1*sz2 is the same as the
currently allocated space, no reallocation is performed. */
void allocAndFill (tsize sz1, tsize sz2, const T &inival)
{ alloc(sz1,sz2); fill(inival); }
/*! Allocates space for an array with \a sz1*sz2 elements.
The content of the array is undefined on exit.
\a sz1 or \a sz2 can be 0. If \a sz1*sz2 is smaller than the
currently allocated space, no reallocation is performed. */
void fast_alloc (tsize sz1, tsize sz2)
{
if (sz1*sz2<=d.size())
{ s1=sz1; s2=sz2; }
else
alloc(sz1,sz2);
}
/*! Deallocates the space and makes the array zero-sized. */
void dealloc () {d.dealloc(); s1=0; s2=0;}
/*! Sets all array elements to \a val. */
void fill (const T &val)
{ for (tsize m=0; m<s1*s2; ++m) d[m]=val; }
/*! Changes the array to be a copy of \a orig. */
arr2T &operator= (const arr2T &orig)
{
if (this==&orig) return *this;
alloc (orig.s1, orig.s2);
d = orig.d;
return *this;
}
/*! Returns a pointer to the beginning of slice \a n. */
template<typename T2> T *operator[] (T2 n) {return &d[n*s2];}
/*! Returns a constant pointer to the beginning of slice \a n. */
template<typename T2> const T *operator[] (T2 n) const {return &d[n*s2];}
/*! Returns a reference to the element with the indices \a n1 and \a n2. */
template<typename T2, typename T3> T &operator() (T2 n1, T3 n2)
{return d[n1*s2 + n2];}
/*! Returns a constant reference to the element with the indices
\a n1 and \a n2. */
template<typename T2, typename T3> const T &operator() (T2 n1, T3 n2) const
{return d[n1*s2 + n2];}
/*! Returns the minimum and maximum entry in \a minv and \a maxv,
respectively. Throws an exception if the array is zero-sized. */
void minmax (T &minv, T &maxv) const
{
planck_assert(s1*s2>0,
"trying to find min and max of a zero-sized array");
minv=maxv=d[0];
for (tsize m=1; m<s1*s2; ++m)
{
if (d[m]<minv) minv=d[m];
if (d[m]>maxv) maxv=d[m];
}
}
/*! Swaps contents and sizes with \a other. */
void swap (arr2T &other)
{
d.swap(other.d);
std::swap(s1,other.s1);
std::swap(s2,other.s2);
}
/*! Returns \c true if the array and \a other have the same dimensions,
else \c false. */
template<typename T2, typename T3> bool conformable
(const arr2T<T2,T3> &other) const
{ return (other.size1()==s1) && (other.size2()==s2); }
};
/*! Two-dimensional array type. The storage ordering is the same as in C.
An entry is located by address arithmetic, not by double dereferencing.
The indices start at zero. */
template <typename T>
class arr2: public arr2T<T,normalAlloc__<T> >
{
public:
/*! Creates a zero-sized array. */
arr2() : arr2T<T,normalAlloc__<T> > () {}
/*! Creates an array with the dimensions \a sz1 and \a sz2. */
arr2(tsize sz1, tsize sz2) : arr2T<T,normalAlloc__<T> > (sz1,sz2) {}
/*! Creates an array with the dimensions \a sz1 and \a sz2
and initializes them with \a inival. */
arr2(tsize sz1, tsize sz2, const T &inival)
: arr2T<T,normalAlloc__<T> > (sz1,sz2,inival) {}
};
/*! Two-dimensional array type, with selectable storage alignment.
The storage ordering is the same as in C.
An entry is located by address arithmetic, not by double dereferencing.
The indices start at zero. */
template <typename T, int align>
class arr2_align: public arr2T<T,alignAlloc__<T,align> >
{
public:
/*! Creates a zero-sized array. */
arr2_align() : arr2T<T,alignAlloc__<T,align> > () {}
/*! Creates an array with the dimensions \a sz1 and \a sz2. */
arr2_align(tsize sz1, tsize sz2)
: arr2T<T,alignAlloc__<T,align> > (sz1,sz2) {}
/*! Creates an array with the dimensions \a sz1 and \a sz2
and initializes them with \a inival. */
arr2_align(tsize sz1, tsize sz2, const T &inival)
: arr2T<T,alignAlloc__<T,align> > (sz1,sz2,inival) {}
};
/*! Two-dimensional array type. An entry is located by double dereferencing,
i.e. via an array of pointers. The indices start at zero. */
template <typename T> class arr2b
{
private:
tsize s1, s2;
arr<T> d;
arr<T *> d1;
void fill_d1()
{ for (tsize m=0; m<s1; ++m) d1[m] = &d[m*s2]; }
public:
/*! Creates a zero-sized array. */
arr2b() : s1(0), s2(0), d(0), d1(0) {}
/*! Creates an array with the dimensions \a sz1 and \a sz2. */
arr2b(tsize sz1, tsize sz2)
: s1(sz1), s2(sz2), d(s1*s2), d1(s1)
{ fill_d1(); }
/*! Creates the array as a copy of \a orig. */
arr2b(const arr2b &orig)
: s1(orig.s1), s2(orig.s2), d(orig.d), d1(s1)
{ fill_d1(); }
/*! Frees the memory associated with the array. */
~arr2b() {}
/*! Returns the first array dimension. */
tsize size1() const { return s1; }
/*! Returns the second array dimension. */
tsize size2() const { return s2; }
/*! Returns the total array size, i.e. the product of both dimensions. */
tsize size () const { return s1*s2; }
/*! Allocates space for an array with \a sz1*sz2 elements.
The content of the array is undefined on exit. */
void alloc (tsize sz1, tsize sz2)
{
if ((s1==sz1) && (s2==sz2)) return;
s1=sz1; s2=sz2;
d.alloc(s1*s2);
d1.alloc(s1);
fill_d1();
}
/*! Deallocates the space and makes the array zero-sized. */
void dealloc () {d.dealloc(); d1.dealloc(); s1=0; s2=0;}
/*! Sets all array elements to \a val. */
void fill (const T &val)
{ d.fill(val); }
/*! Changes the array to be a copy of \a orig. */
arr2b &operator= (const arr2b &orig)
{
if (this==&orig) return *this;
alloc (orig.s1, orig.s2);
for (tsize m=0; m<s1*s2; ++m) d[m] = orig.d[m];
return *this;
}
/*! Returns a pointer to the beginning of slice \a n. */
template<typename T2> T *operator[] (T2 n) {return d1[n];}
/*! Returns a constant pointer to the beginning of slice \a n. */
template<typename T2> const T *operator[] (T2 n) const {return d1[n];}
/*! Returns a pointer to the beginning of the pointer array. */
T **p0() {return &d1[0];}
};
/*! Three-dimensional array type. The storage ordering is the same as in C.
An entry is located by address arithmetic, not by multiple dereferencing.
The indices start at zero. */
template <typename T> class arr3
{
private:
tsize s1, s2, s3, s2s3;
arr<T> d;
public:
/*! Creates a zero-sized array. */
arr3() : s1(0), s2(0), s3(0), s2s3(0), d(0) {}
/*! Creates an array with the dimensions \a sz1, \a sz2 and \a sz3. */
arr3(tsize sz1, tsize sz2, tsize sz3)
: s1(sz1), s2(sz2), s3(sz3), s2s3(s2*s3), d(s1*s2*s3) {}
/*! Creates the array as a copy of \a orig. */
arr3(const arr3 &orig)
: s1(orig.s1), s2(orig.s2), s3(orig.s3), s2s3(orig.s2s3), d(orig.d) {}
/*! Frees the memory associated with the array. */
~arr3() {}
/*! Returns the first array dimension. */
tsize size1() const { return s1; }
/*! Returns the second array dimension. */
tsize size2() const { return s2; }
/*! Returns the third array dimension. */
tsize size3() const { return s3; }
/*! Returns the total array size, i.e. the product of all dimensions. */
tsize size () const { return s1*s2*s3; }
/*! Allocates space for an array with \a sz1*sz2*sz3 elements.
The content of the array is undefined on exit. */
void alloc (tsize sz1, tsize sz2, tsize sz3)
{
d.alloc(sz1*sz2*sz3);
s1=sz1; s2=sz2; s3=sz3; s2s3=s2*s3;
}
/*! Deallocates the space and makes the array zero-sized. */
void dealloc () {d.dealloc(); s1=0; s2=0; s3=0; s2s3=0;}
/*! Sets all array elements to \a val. */
void fill (const T &val)
{ d.fill(val); }
/*! Changes the array to be a copy of \a orig. */
arr3 &operator= (const arr3 &orig)
{
if (this==&orig) return *this;
alloc (orig.s1, orig.s2, orig.s3);
d = orig.d;
return *this;
}
/*! Returns a reference to the element with the indices
\a n1, \a n2 and \a n3. */
template<typename T2, typename T3, typename T4> T &operator()
(T2 n1, T3 n2, T4 n3)
{return d[n1*s2s3 + n2*s3 + n3];}
/*! Returns a constant reference to the element with the indices
\a n1, \a n2 and \a n3. */
template<typename T2, typename T3, typename T4> const T &operator()
(T2 n1, T3 n2, T4 n3) const
{return d[n1*s2s3 + n2*s3 + n3];}
/*! Swaps contents and sizes with \a other. */
void swap (arr3 &other)
{
d.swap(other.d);
std::swap(s1,other.s1);
std::swap(s2,other.s2);
std::swap(s3,other.s3);
std::swap(s2s3,other.s2s3);
}
/*! Returns \c true if the array and \a other have the same dimensions,
else \c false. */
template<typename T2> bool conformable (const arr3<T2> &other) const
{ return (other.size1()==s1)&&(other.size2()==s2)&&(other.size3()==s3); }
};
/*! \} */
#endif

266
external/healpix/cxxsupport/bstream.h vendored Normal file
View file

@ -0,0 +1,266 @@
/*
* This file is part of libcxxsupport.
*
* libcxxsupport is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* libcxxsupport is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with libcxxsupport; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik
* and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
* (DLR).
*/
/*! \file bstream.h
* Classes for binary I/O with streams
*
* Copyright (C) 2010 Max-Planck-Society
* \author Martin Reinecke
*/
#ifndef PLANCK_BSTREAM_H
#define PLANCK_BSTREAM_H
#include <iostream>
#include <fstream>
#include <algorithm>
#include "datatypes.h"
/*! An object of this class can be cast to a \a bool, which indicates whether
the computer architecture is big-endian (true) or little-endian (false). */
class EndianTest__
{
private:
bool big_end;
public:
EndianTest__()
{
union { uint16 i16; uint8 i8; } tmp;
tmp.i16 = 1;
big_end = (tmp.i8==0);
}
operator bool() const { return big_end; }
};
const EndianTest__ big_endian;
template<size_t size> inline void byteswap_helper__ (char *);
template<> inline void byteswap_helper__<1> (char *)
{}
template<> inline void byteswap_helper__<2> (char *val)
{
using namespace std;
swap (val[0],val[1]);
}
template<> inline void byteswap_helper__<4> (char *val)
{
using namespace std;
swap (val[0],val[3]); swap (val[1],val[2]);
}
template<> inline void byteswap_helper__<8> (char *val)
{
using namespace std;
swap (val[0],val[7]); swap (val[1],val[6]);
swap (val[2],val[5]); swap (val[3],val[4]);
}
/*! Performs an endianness conversion on \a val.
\note \a T must be a primitive data type! */
template<typename T> inline void byteswap (T &val)
{ byteswap_helper__<sizeof(T)> (reinterpret_cast<char *> (&val)); }
const bool file_is_lsb=big_endian, file_is_msb=!big_endian,
file_is_natural=false;
/*! Class for writing binary data to a stream. */
class bostream
{
private:
std::ostream &s;
bool doswap;
public:
/*! Creates a new object which is attached to \a s_ and performs
endianness conversion if \a doswap_==true. */
bostream (std::ostream &s_, bool doswap_=false)
: s(s_), doswap(doswap_) {}
/*! Writes a binary representation of \a num objects of type \a T
(stored in \a data) to the attached stream. Endianness conversion
is performed if requested in the constructor.
\note \a T must be a primitive data type! */
template<typename T> bostream &put (const T *data, size_t num)
{
if ((sizeof(T)>1) && doswap)
for (size_t m=0; m<num; ++m)
{
T tmp=data[m];
byteswap (tmp);
s.write (reinterpret_cast<const char *> (&tmp), sizeof(T));
}
else
s.write (reinterpret_cast<const char *> (data), num*sizeof(T));
return *this;
}
/*! Writes a binary representation of \a data to the attached stream.
Endianness conversion is performed if requested in the constructor.
\note \a T must be a primitive data type! */
template<typename T> bostream &operator<< (const T &data)
{
put(&data,1);
return *this;
}
bool getSwap() const
{ return doswap; }
void setSwap(bool newswap)
{ doswap=newswap; }
void flipSwap()
{ doswap=!doswap; }
};
/*! Class for reading binary data from a stream. */
class bistream
{
private:
std::istream &s;
bool doswap;
public:
/*! Creates a new object which is attached to \a s_ and performs
endianness conversion if \a doswap_==true. */
bistream (std::istream &s_, bool doswap_=false)
: s(s_), doswap(doswap_) {}
/*! Reads a binary representation of \a num objects of type \a T
from the attached stream and stores them in \a data. Endianness
conversion is performed if requested in the constructor.
\note \a T must be a primitive data type! */
template<typename T> bistream &get (T *data, size_t num)
{
s.read (reinterpret_cast<char *> (data), num*sizeof(T));
if ((sizeof(T)>1) && doswap)
for (size_t m=0; m<num; ++m)
byteswap (data[m]);
return *this;
}
/*! Reads a binary representation of \a data from the attached stream.
Endianness conversion is performed if requested in the constructor.
\note \a T must be a primitive data type! */
template<typename T> bistream &operator>> (T &data)
{
get (&data,1);
return *this;
}
bool getSwap() const
{ return doswap; }
void setSwap(bool newswap)
{ doswap=newswap; }
void flipSwap()
{ doswap=!doswap; }
};
class bofstream: public std::ofstream
{
private:
bool doswap;
public:
/*! */
bofstream (const char *fname, bool doswap_)
: std::ofstream(fname,std::ios::binary), doswap(doswap_) {}
template<typename T> bofstream &operator<< (const T &data)
{
if (doswap)
{
T tmp = data;
byteswap (tmp);
write (reinterpret_cast<const char *> (&tmp), sizeof(T));
}
else
write (reinterpret_cast<const char *> (&data), sizeof(T));
return *this;
}
template<typename T> bofstream &put (const T *data, size_t num)
{
if (doswap)
for (size_t m=0; m<num; ++m)
{
T tmp=data[m];
byteswap (tmp);
write (reinterpret_cast<const char *> (&tmp), sizeof(T));
}
else
write (reinterpret_cast<const char *> (data), num*sizeof(T));
return *this;
}
bool getSwap() const
{ return doswap; }
void setSwap(bool newswap)
{ doswap=newswap; }
void flipSwap()
{ doswap=!doswap; }
};
class bifstream: public std::ifstream
{
private:
bool doswap;
public:
/*! */
bifstream ()
: doswap(false) {}
bifstream (const char *fname, bool doswap_)
: std::ifstream(fname,std::ios::binary), doswap(doswap_) {}
void open (const char *fname, bool doswap_)
{
doswap=doswap_;
std::ifstream::open(fname,std::ios::binary);
}
template<typename T> bifstream &operator>> (T &data)
{
read (reinterpret_cast<char *> (&data), sizeof(T));
if (doswap) byteswap (data);
return *this;
}
template<typename T> bifstream &get (T *data, size_t num)
{
read (reinterpret_cast<char *> (data), num*sizeof(T));
if (doswap)
for (size_t m=0; m<num; ++m)
byteswap (data[m]);
return *this;
}
void rewind()
{ seekg(0,std::ios::beg); }
void skip(std::streamoff nbytes)
{ seekg(nbytes,std::ios::cur); }
bool getSwap() const
{ return doswap; }
void setSwap(bool newswap)
{ doswap=newswap; }
void flipSwap()
{ doswap=!doswap; }
};
#endif

View file

@ -0,0 +1,4 @@
/*! \mainpage LevelS C++ support library documentation
Please refer to the <a href="modules.html">Modules</a> page for an overview
of the supplied functionality.
*/

304
external/healpix/cxxsupport/cxxutils.cc vendored Normal file
View file

@ -0,0 +1,304 @@
/*
* This file is part of libcxxsupport.
*
* libcxxsupport is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* libcxxsupport is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with libcxxsupport; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik
* and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
* (DLR).
*/
/*
* This file contains the implementation of various convenience functions
* used by the Planck LevelS package.
*
* Copyright (C) 2002 - 2010 Max-Planck-Society
* Authors: Martin Reinecke, Reinhard Hell
*/
// if we are using g++, check for version 3.0 or higher
#ifdef __GNUC__
#if (__GNUC__<3)
#error your C++ compiler is too old. g++ version 3.0 or higher is required.
#endif
#endif
#include <fstream>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <string>
#include <cstring>
#include "cxxutils.h"
#include "datatypes.h"
#include "openmp_support.h"
#include "sse_utils.h"
using namespace std;
string trim (const string &orig)
{
string::size_type p1=orig.find_first_not_of(" \t");
if (p1==string::npos) return "";
string::size_type p2=orig.find_last_not_of(" \t");
return orig.substr(p1,p2-p1+1);
}
template<typename T> string dataToString (const T &x)
{
ostringstream strstrm;
strstrm << x;
return trim(strstrm.str());
}
template<> string dataToString (const bool &x)
{ return x ? "T" : "F"; }
template<> string dataToString (const string &x)
{ return trim(x); }
template<> string dataToString (const float &x)
{
ostringstream strstrm;
strstrm << setprecision(8) << x;
return trim(strstrm.str());
}
template<> string dataToString (const double &x)
{
ostringstream strstrm;
strstrm << setprecision(16) << x;
return trim(strstrm.str());
}
template string dataToString (const signed char &x);
template string dataToString (const unsigned char &x);
template string dataToString (const short &x);
template string dataToString (const unsigned short &x);
template string dataToString (const int &x);
template string dataToString (const unsigned int &x);
template string dataToString (const long &x);
template string dataToString (const unsigned long &x);
template string dataToString (const long long &x);
template string dataToString (const unsigned long long &x);
string intToString(int64 x, tsize width)
{
ostringstream strstrm;
strstrm << setw(width) << setfill('0') << x;
return trim(strstrm.str());
}
namespace {
void end_stringToData (const string &x, const char *tn, istringstream &strstrm)
{
string error = string("conversion error in stringToData<")+tn+">(\""+x+"\")";
planck_assert (strstrm,error);
string rest;
strstrm >> rest;
// rest=trim(rest);
planck_assert (rest.length()==0,error);
}
} // unnamed namespace
template<typename T> void stringToData (const string &x, T &value)
{
istringstream strstrm(x);
strstrm >> value;
end_stringToData (x,type2typename<T>(),strstrm);
}
template<> void stringToData (const string &x, string &value)
{ value = trim(x); }
template<> void stringToData (const string &x, bool &value)
{
const char *x2 = x.c_str();
const char *fval[] = {"F","f","n","N","false",".false.","FALSE",".FALSE." };
const char *tval[] = {"T","t","y","Y","true",".true.","TRUE",".TRUE." };
for (tsize i=0; i< sizeof(fval)/sizeof(fval[0]); ++i)
if (strcmp(x2,fval[i])==0) { value=false; return; }
for (tsize i=0; i< sizeof(tval)/sizeof(tval[0]); ++i)
if (strcmp(x2,tval[i])==0) { value=true; return; }
planck_fail("conversion error in stringToData<bool>(\""+x+"\")");
}
template void stringToData (const string &x, signed char &value);
template void stringToData (const string &x, unsigned char &value);
template void stringToData (const string &x, short &value);
template void stringToData (const string &x, unsigned short &value);
template void stringToData (const string &x, int &value);
template void stringToData (const string &x, unsigned int &value);
template void stringToData (const string &x, long &value);
template void stringToData (const string &x, unsigned long &value);
template void stringToData (const string &x, long long &value);
template void stringToData (const string &x, unsigned long long &value);
template void stringToData (const string &x, float &value);
template void stringToData (const string &x, double &value);
bool equal_nocase (const string &a, const string &b)
{
if (a.size()!=b.size()) return false;
for (tsize m=0; m<a.size(); ++m)
if (tolower(a[m])!=tolower(b[m])) return false;
return true;
}
string tolower(const string &input)
{
string result=input;
for (tsize m=0; m<result.size(); ++m)
result[m]=char(tolower(result[m]));
return result;
}
namespace {
void openmp_status()
{
int threads = openmp_max_threads();
if (threads>1)
cout << "OpenMP active: max. " << threads << " threads. " << endl;
}
void SSE_status()
{
#if(defined(PLANCK_HAVE_SSE)||defined(PLANCK_HAVE_SSE2))
cout << "Processor features detected: ";
#if(defined(PLANCK_HAVE_SSE)&&defined(PLANCK_HAVE_SSE2))
cout << "SSE, SSE2" << endl;
#elif(defined(PLANCK_HAVE_SSE))
cout << "SSE" << endl;
#else
cout << "SSE2" << endl;
#endif
#endif
}
} //unnamed namespace
void announce (const string &name)
{
string version = "v2.20";
string name2 = name+" "+version;
cout << endl << "+-";
for (tsize m=0; m<name2.length(); ++m) cout << "-";
cout << "-+" << endl;
cout << "| " << name2 << " |" << endl;
cout << "+-";
for (tsize m=0; m<name2.length(); ++m) cout << "-";
cout << "-+" << endl << endl;
SSE_status();
openmp_status();
cout << endl;
}
void module_startup (const string &name, int argc, const char **,
int argc_expected, const string &argv_expected, bool verbose)
{
if (verbose) announce (name);
if (argc==argc_expected) return;
cerr << "Usage: " << name << " " << argv_expected << endl;
planck_fail_quietly ("Incorrect usage");
}
void parse_file (const string &filename, map<string,string> &dict)
{
int lineno=0;
dict.clear();
ifstream inp(filename.c_str());
planck_assert (inp,"Could not open parameter file '"+filename+"'.");
while (inp)
{
string line;
getline(inp, line);
++lineno;
// remove potential carriage returns at the end of the line
line=line.substr(0,line.find("\r"));
line=line.substr(0,line.find("#"));
line=trim(line);
if (line.size()>0)
{
string::size_type eqpos=line.find("=");
if (eqpos!=string::npos)
{
string key=trim(line.substr(0,eqpos)),
value=trim(line.substr(eqpos+1,string::npos));
if (key=="")
cerr << "Warning: empty key in '" << filename << "', line "
<< lineno << endl;
else
{
if (dict.find(key)!=dict.end())
cerr << "Warning: key '" << key << "' multiply defined in '"
<< filename << "', line " << lineno << endl;
dict[key]=value;
}
}
else
cerr << "Warning: unrecognized format in '" << filename << "', line "
<< lineno << ":\n" << line << endl;
}
}
}
void calcShareGeneral (int64 glo, int64 ghi, int64 nshares, int64 myshare,
int64 &lo, int64 &hi)
{
int64 nwork = ghi-glo;
int64 nbase = nwork/nshares;
int64 additional = nwork%nshares;
lo = glo+myshare*nbase + ((myshare<additional) ? myshare : additional);
hi = lo+nbase+(myshare<additional);
}
namespace {
template<typename T> void split (istream &stream, vector<T> &list)
{
while (stream)
{
string word;
stream >> word;
planck_assert (stream||stream.eof(),
string("error while splitting stream into ") + type2typename<T>()
+ "components");
if (stream) list.push_back(stringToData<T>(word));
}
}
} // unnamed namespace
template<typename T> void split (const string &inp, vector<T> &list)
{
istringstream stream(inp);
split (stream,list);
}
template void split (const string &inp, vector<string> &list);
template void split (const string &inp, vector<float> &list);
template void split (const string &inp, vector<double> &list);
template void split (const string &inp, vector<int> &list);
template void split (const string &inp, vector<long> &list);
void tokenize (const string &inp, char delim, vector<string> &list)
{
istringstream stream(inp);
string token;
list.clear();
while (getline(stream,token,delim))
list.push_back(token);
}

383
external/healpix/cxxsupport/cxxutils.h vendored Normal file
View file

@ -0,0 +1,383 @@
/*
* This file is part of libcxxsupport.
*
* libcxxsupport is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* libcxxsupport is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with libcxxsupport; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik
* and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
* (DLR).
*/
/*! \file cxxutils.h
* Various convenience functions used by the Planck LevelS package.
*
* Copyright (C) 2002 - 2010 Max-Planck-Society
* \author Martin Reinecke \author Reinhard Hell
*/
#ifndef PLANCK_CXXUTILS_H
#define PLANCK_CXXUTILS_H
#include <algorithm>
#include <string>
#include <map>
#include <vector>
#include <cmath>
#include "error_handling.h"
#include "datatypes.h"
/*! \defgroup mathutilsgroup Mathematical helper functions */
/*! \{ */
/*! Returns \e true if | \a a-b | < \a epsilon * | \a b |, else \e false. */
template<typename F> inline bool approx (F a, F b, F epsilon=1e-5)
{
using namespace std;
return abs(a-b) < (epsilon*abs(b));
}
/*! Returns \e true if | \a a-b | < \a epsilon, else \e false. */
template<typename F> inline bool abs_approx (F a, F b, F epsilon=1e-5)
{
using namespace std;
return abs(a-b) < epsilon;
}
/*! Returns the largest integer which is smaller than (or equal to) \a arg. */
template<typename I, typename F> inline I ifloor (F arg)
{
using namespace std;
return I(floor(arg));
}
/*! Returns the integer which is nearest to \a arg. */
template<typename I, typename F> inline I nearest (F arg)
{ return ifloor<I>(arg+0.5); }
/*! Returns \a v1+v2 if \a v1<0, \a v1-v2 if \a v1>=v2, else \a v1.
\a v1 can be positive or negative; \a v2 must be positive. */
template<typename T> inline T weak_modulo (T v1, T v2)
{ return (v1>=0) ? ((v1<v2) ? v1 : (v1-v2)) : (v1+v2); }
/*! Returns the remainder of the division \a v1/v2.
The result is non-negative.
\a v1 can be positive or negative; \a v2 must be positive. */
inline double fmodulo (double v1, double v2)
{
using namespace std;
return (v1>=0) ? ((v1<v2) ? v1 : fmod(v1,v2)) : (fmod(v1,v2)+v2);
}
/*! Returns the remainder of the division \a v1/v2.
The result is non-negative.
\a v1 can be positive or negative; \a v2 must be positive. */
template<typename I> inline I imodulo (I v1, I v2)
{ I v=v1%v2; return (v>=0) ? v : v+v2; }
/*! Returns -1 if \a signvalue is negative, else +1. */
template<typename T> inline T sign (const T& signvalue)
{ return (signvalue>=0) ? 1 : -1; }
/*! Returns \a val*pow(-1,m) */
template<typename T, typename I> inline T xpow (I m, T val)
{ return (m&1) ? -val : val; }
template <typename I, bool g4> struct isqrt_helper__
{};
template <typename I> struct isqrt_helper__ <I, false>
{
static uint32 isqrt (I arg)
{
using namespace std;
return uint32 (sqrt(arg+0.5));
}
};
template <typename I> struct isqrt_helper__ <I, true>
{
static uint32 isqrt (I arg)
{
using namespace std;
long double arg2 = static_cast<long double>(arg)+0.5;
return uint32 (sqrt(arg2));
}
};
/*! Returns the integer \a n, which fulfills \a n*n<=arg<(n+1)*(n+1). */
template<typename I> inline uint32 isqrt (I arg)
{ return isqrt_helper__<I,(sizeof(I)>4)>::isqrt(arg); }
/*! Returns the largest integer \a n that fulfills \a 2^n<=arg. */
template<typename I> inline unsigned int ilog2 (I arg)
{
unsigned int res=0;
while (arg > 0x0000FFFF) { res+=16; arg>>=16; }
if (arg > 0x000000FF) { res|=8; arg>>=8; }
if (arg > 0x0000000F) { res|=4; arg>>=4; }
if (arg > 0x00000003) { res|=2; arg>>=2; }
if (arg > 0x00000001) { res|=1; }
return res;
}
/*! Returns \a atan2(y,x) if \a x!=0 or \a y!=0; else returns 0. */
inline double safe_atan2 (double y, double x)
{
using namespace std;
return ((x==0.) && (y==0.)) ? 0.0 : atan2(y,x);
}
/*! Helper function for linear interpolation (or extrapolation).
The array must be ordered in ascending order; no two values may be equal. */
template<typename T, typename Iter, typename Comp> inline void interpol_helper
(const Iter &begin, const Iter &end, const T &val, Comp comp, tsize &idx,
T &frac)
{
using namespace std;
planck_assert((end-begin)>1,"sequence too small for interpolation");
idx = lower_bound(begin,end,val,comp)-begin;
if (idx>0) --idx;
idx = min(tsize(end-begin-2),idx);
frac = (val-begin[idx])/(begin[idx+1]-begin[idx]);
}
/*! Helper function for linear interpolation (or extrapolation).
The array must be ordered in ascending order; no two values may be equal. */
template<typename T, typename Iter> inline void interpol_helper
(const Iter &begin, const Iter &end, const T &val, tsize &idx, T &frac)
{ interpol_helper (begin,end,val,std::less<T>(),idx,frac); }
/*! \} */
template<typename T> inline bool multiequal (const T &a, const T &b, const T &c)
{ return (a==b) && (a==c); }
template<typename T> inline bool multiequal (const T &a, const T &b, const T &c,
const T &d)
{ return (a==b) && (a==c) && (a==d); }
template<typename T> inline bool multiequal (const T &a, const T &b, const T &c,
const T &d, const T &e)
{ return (a==b) && (a==c) && (a==d) && (a==e); }
template<typename T> inline bool multiequal (const T &a, const T &b, const T &c,
const T &d, const T &e, const T &f)
{ return (a==b) && (a==c) && (a==d) && (a==e) && (a==f); }
template<typename It, typename Comp> class IdxComp__
{
private:
It begin;
Comp comp;
public:
IdxComp__ (It begin_, Comp comp_): begin(begin_), comp(comp_) {}
bool operator() (std::size_t a, std::size_t b) const
{ return comp(*(begin+a),*(begin+b)); }
};
/*! Performs an indirect sort on the supplied iterator range and returns in
\a idx a \a vector containing the indices of the smallest, second smallest,
third smallest, etc. element, according to \a comp. */
template<typename It, typename T2, typename Comp>
inline void buildIndex (It begin, It end, std::vector<T2> &idx, Comp comp)
{
using namespace std;
T2 num=end-begin;
idx.resize(num);
for (T2 i=0; i<num; ++i) idx[i] = i;
sort (idx.begin(),idx.end(),IdxComp__<It,Comp>(begin,comp));
}
/*! Performs an indirect sort on the supplied iterator range and returns in
\a idx a \a vector containing the indices of the smallest, second smallest,
third smallest, etc. element. */
template<typename It, typename T2> inline void buildIndex (It begin, It end,
std::vector<T2> &idx)
{
using namespace std;
typedef typename iterator_traits<It>::value_type T;
buildIndex(begin,end,idx,less<T>());
}
/*! Sorts the supplied iterator range according to the order given by \a idx.
The operation is done out of place and requires temporary extra storage. */
template<typename It, typename T2> inline void sortByIndex (It begin, It end,
const std::vector<T2> &idx)
{
using namespace std;
typedef typename iterator_traits<It>::value_type T;
T2 num=end-begin;
T *tmp= new T[num];
for (T2 i=0; i<num; ++i) tmp[i]=*(begin+i);
for (T2 i=0; i<num; ++i) *(begin+i) = tmp[idx[i]];
delete[] tmp;
}
/*! Sorts the supplied iterator range according to the order given by \a idx.
The operation is done in place. */
template<typename It, typename T2> inline void sortByIndex_inplace
(It begin, It end, const std::vector<T2> &idx)
{
using namespace std;
typedef typename iterator_traits<It>::value_type T;
T2 num=end-begin;
vector<bool> done(num,false);
T2 cnt=0;
while (cnt<num)
{
if (!done[cnt]) // new cycle
{
T tmp(*(begin+cnt));
T2 cnt2 = cnt;
T2 cnt3 = idx[cnt];
while (cnt3!=cnt)
{
done[cnt2]=true;
*(begin+cnt2)=*(begin+cnt3);
cnt2=cnt3;
cnt3=idx[cnt3];
}
*(begin+cnt2) = tmp;
}
++cnt;
}
}
template<typename It, typename Comp> inline void indirectSort (It begin, It end,
Comp comp)
{
using namespace std;
typedef typename iterator_traits<It>::value_type T;
vector<std::size_t> idx;
buildIndex (begin,end,idx,comp);
sortByIndex (begin,end,idx);
}
template<typename It> inline void indirectSort (It begin, It end)
{
using namespace std;
typedef typename iterator_traits<It>::value_type T;
indirectSort(begin,end,less<T>());
}
/*! \defgroup stringutilsgroup String handling helper functions */
/*! \{ */
/*! Returns the string \a orig without leading and trailing whitespace. */
std::string trim (const std::string &orig);
/*! Returns a string containing the text representation of \a x.
Care is taken that no information is lost in the conversion. */
template<typename T> std::string dataToString(const T &x);
template<> std::string dataToString (const bool &x);
template<> std::string dataToString (const std::string &x);
template<> std::string dataToString (const float &x);
template<> std::string dataToString (const double &x);
/*! Returns a string containing the text representation of \a x, padded
with leading zeroes to \a width characters. */
std::string intToString(int64 x, tsize width);
/*! Reads a value of a given datatype from a string */
template<typename T> void stringToData (const std::string &x, T &value);
template<> void stringToData (const std::string &x, std::string &value);
template<> void stringToData (const std::string &x, bool &value);
/*! Reads a value of a given datatype from a string */
template<typename T> inline T stringToData (const std::string &x)
{ T result; stringToData(x,result); return result; }
/*! Parses the file \a filename and returns the key/value pairs in \a dict. */
void parse_file (const std::string &filename,
std::map<std::string,std::string> &dict);
/*! Case-insensitive string comparison
Returns \a true, if \a a and \a b differ only in capitalisation,
else \a false. */
bool equal_nocase (const std::string &a, const std::string &b);
/*! Returns lowercase version of \a input. */
std::string tolower(const std::string &input);
/*! \} */
/*! Prints a banner containing \a name, as well as some information about the
source code and the parallelisation techniques enabled. */
void announce (const std::string &name);
/*! Prints a banner containing \a name and checks if \a argc==argc_expected.
If not, a usage description is given and the program is terminated. */
void module_startup (const std::string &name, int argc, const char **argv,
int argc_expected, const std::string &argv_expected, bool verbose=true);
/*! Divides the index range [\a glo; \a ghi) into \a nshares approximately
equal parts, and returns the sub-range [\a lo; \a hi) of the
part with the number \a myshare (first part has index 0). */
void calcShareGeneral (int64 glo, int64 ghi, int64 nshares, int64 myshare,
int64 &lo, int64 &hi);
/*! Helper class for dividing a range of work items into chunks of specified
size. */
class chunkMaker
{
private:
uint64 s_full, s_chunk, offset;
public:
/*! Creates an object that produces chunk information for \a s_full_
work items and a desired chunk size of \a s_chunk_. */
chunkMaker (uint64 s_full_, uint64 s_chunk_)
: s_full(s_full_), s_chunk(s_chunk_), offset(0) {}
/*! Returns the total number of chunks. */
uint64 nchunks() const
{ return (s_full+s_chunk-1)/s_chunk; }
/*! Returns the start index of the next chunk in \a start, and its size
in \a size. If all chunks have been processed already, the return
value is \a false, else \a true. */
bool getNext (uint64 &start, uint64 &size)
{
using namespace std;
if (offset>=s_full) return false;
start=offset;
size=min(s_chunk,s_full-offset);
offset+=s_chunk;
return true;
}
};
/*! Tries to split \a inp into a white-space separated list of values of
type \a T, and appends them to \a list. */
template<typename T> void split (const std::string &inp, std::vector<T> &list);
/*! Resizes \a container to zero and releases its memory. Typically used for
std::vector.
Taken from http://www.gotw.ca/gotw/054.htm */
template<typename T> inline void releaseMemory (T &container)
{ T().swap(container); }
/*! Releases all unused memory that \a container might have. Typically used for
std::vector.
Taken from http://www.gotw.ca/gotw/054.htm */
template<typename T> inline void shrinkToFit (T &container)
{ T(container).swap(container); }
/*! Breaks the string \a inp into tokens separated by \a delim, and returns them
in \a list. */
void tokenize (const std::string &inp, char delim,
std::vector<std::string> &list);
#endif

284
external/healpix/cxxsupport/datatypes.h vendored Normal file
View file

@ -0,0 +1,284 @@
/*
* This file is part of libcxxsupport.
*
* libcxxsupport is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* libcxxsupport is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with libcxxsupport; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik
* and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
* (DLR).
*/
/*! \file datatypes.h
* This file defines various platform-independent data types.
* If any of the requested types is not available, compilation aborts
* with an error (unfortunately a rather obscure one).
*
* Copyright (C) 2004, 2008, 2009, 2010 Max-Planck-Society
* \author Martin Reinecke
*/
#ifndef PLANCK_DATATYPES_H
#define PLANCK_DATATYPES_H
#include <string>
#include <cstddef>
#include "error_handling.h"
// Template magic to select the proper data types. These templates
// should not be used outside this file.
template <typename T, bool equalSize> struct sizeChooserHelper__
{ typedef void TYPE; };
template <typename T> struct sizeChooserHelper__<T,true>
{ typedef T TYPE; };
template <typename T1, typename T2, typename T3> struct sizeChooserHelper2__
{ typedef T1 TYPE; };
template <typename T2, typename T3> struct sizeChooserHelper2__ <void, T2, T3>
{ typedef T2 TYPE; };
template <typename T3> struct sizeChooserHelper2__ <void, void, T3>
{ typedef T3 TYPE; };
template <> struct sizeChooserHelper2__ <void, void, void>
{ };
template <int sz, typename T1, typename T2=char, typename T3=char>
struct sizeChooser__
{
typedef typename sizeChooserHelper2__
<typename sizeChooserHelper__<T1,sizeof(T1)==sz>::TYPE,
typename sizeChooserHelper__<T2,sizeof(T2)==sz>::TYPE,
typename sizeChooserHelper__<T3,sizeof(T3)==sz>::TYPE >::TYPE TYPE;
};
typedef signed char int8;
typedef unsigned char uint8;
typedef sizeChooser__<2, short, int>::TYPE
int16;
typedef sizeChooser__<2, unsigned short, unsigned int>::TYPE
uint16;
typedef sizeChooser__<4, int, long, short>::TYPE
int32;
typedef sizeChooser__<4, unsigned int, unsigned long, unsigned short>::TYPE
uint32;
typedef sizeChooser__<8, long, long long>::TYPE
int64;
typedef sizeChooser__<8, unsigned long, unsigned long long>::TYPE
uint64;
typedef sizeChooser__<4, float, double>::TYPE
float32;
typedef sizeChooser__<8, double, long double>::TYPE
float64;
/*! unsigned integer type which should be used for array sizes */
typedef std::size_t tsize;
/*! signed integer type which should be used for relative array indices */
typedef std::ptrdiff_t tdiff;
/*! mapping of Planck data types to integer constants */
enum PDT {
PLANCK_INT8 = 0,
PLANCK_UINT8 = 1,
PLANCK_INT16 = 2,
PLANCK_UINT16 = 3,
PLANCK_INT32 = 4,
PLANCK_UINT32 = 5,
PLANCK_INT64 = 6,
PLANCK_UINT64 = 7,
PLANCK_FLOAT32 = 8,
PLANCK_FLOAT64 = 9,
PLANCK_BOOL = 10,
PLANCK_STRING = 11,
PLANCK_INVALID = -1 };
/*! Returns the \a PDT constant associated with \a T. */
template<typename T> inline PDT planckType();
template<> inline PDT planckType<int8> () { return PLANCK_INT8; }
template<> inline PDT planckType<uint8> () { return PLANCK_UINT8; }
template<> inline PDT planckType<int16> () { return PLANCK_INT16; }
template<> inline PDT planckType<uint16> () { return PLANCK_UINT16; }
template<> inline PDT planckType<int32> () { return PLANCK_INT32; }
template<> inline PDT planckType<uint32> () { return PLANCK_UINT32; }
template<> inline PDT planckType<int64> () { return PLANCK_INT64; }
template<> inline PDT planckType<uint64> () { return PLANCK_UINT64; }
template<> inline PDT planckType<float32> () { return PLANCK_FLOAT32;}
template<> inline PDT planckType<float64> () { return PLANCK_FLOAT64;}
template<> inline PDT planckType<bool> () { return PLANCK_BOOL; }
template<> inline PDT planckType<std::string>() { return PLANCK_STRING; }
/*! Returns the size (in bytes) of the Planck data type \a type. */
inline int type2size (PDT type)
{
switch (type)
{
case PLANCK_INT8 :
case PLANCK_UINT8 :
case PLANCK_BOOL :
case PLANCK_STRING : return 1;
case PLANCK_INT16 :
case PLANCK_UINT16 : return 2;
case PLANCK_INT32 :
case PLANCK_UINT32 :
case PLANCK_FLOAT32: return 4;
case PLANCK_INT64 :
case PLANCK_UINT64 :
case PLANCK_FLOAT64: return 8;
default:
planck_fail ("type2size: unsupported data type");
}
}
/*! Converts the string \a type to a \a PDT. */
inline PDT string2type(const std::string &type)
{
if (type=="FLOAT64") return PLANCK_FLOAT64;
if (type=="FLOAT32") return PLANCK_FLOAT32;
if (type=="INT8") return PLANCK_INT8;
if (type=="UINT8") return PLANCK_UINT8;
if (type=="INT16") return PLANCK_INT16;
if (type=="UINT16") return PLANCK_UINT16;
if (type=="INT32") return PLANCK_INT32;
if (type=="UINT32") return PLANCK_UINT32;
if (type=="INT64") return PLANCK_INT64;
if (type=="UINT64") return PLANCK_UINT64;
if (type=="BOOL") return PLANCK_BOOL;
if (type=="STRING") return PLANCK_STRING;
planck_fail ("string2type: unknown data type '"+type+"'");
}
/*! Converts the Planck data type \a type to a C string. */
inline const char *type2string (PDT type)
{
switch (type)
{
case PLANCK_INT8 : return "INT8";
case PLANCK_UINT8 : return "UINT8";
case PLANCK_INT16 : return "INT16";
case PLANCK_UINT16 : return "UINT16";
case PLANCK_INT32 : return "INT32";
case PLANCK_UINT32 : return "UINT32";
case PLANCK_INT64 : return "INT64";
case PLANCK_UINT64 : return "UINT64";
case PLANCK_FLOAT32: return "FLOAT32";
case PLANCK_FLOAT64: return "FLOAT64";
case PLANCK_BOOL : return "BOOL";
case PLANCK_STRING : return "STRING";
default:
planck_fail ("type2string: unsupported data type");
}
}
/*! Returns a C string describing the data type \a T. */
template<typename T> inline const char *type2typename ();
template<> inline const char *type2typename<signed char> ()
{ return "signed char"; }
template<> inline const char *type2typename<unsigned char> ()
{ return "unsigned char"; }
template<> inline const char *type2typename<short> ()
{ return "short"; }
template<> inline const char *type2typename<unsigned short> ()
{ return "unsigned short"; }
template<> inline const char *type2typename<int> ()
{ return "int"; }
template<> inline const char *type2typename<unsigned int> ()
{ return "unsigned int"; }
template<> inline const char *type2typename<long> ()
{ return "long"; }
template<> inline const char *type2typename<unsigned long> ()
{ return "unsigned long"; }
template<> inline const char *type2typename<long long> ()
{ return "long long"; }
template<> inline const char *type2typename<unsigned long long> ()
{ return "unsigned long long"; }
template<> inline const char *type2typename<float> ()
{ return "float"; }
template<> inline const char *type2typename<double> ()
{ return "double"; }
template<> inline const char *type2typename<bool> ()
{ return "bool"; }
template<> inline const char *type2typename<std::string> ()
{ return "std::string"; }
/*! mapping of "native" data types to integer constants */
enum NDT {
NAT_CHAR,
NAT_SCHAR,
NAT_UCHAR,
NAT_SHORT,
NAT_USHORT,
NAT_INT,
NAT_UINT,
NAT_LONG,
NAT_ULONG,
NAT_LONGLONG,
NAT_ULONGLONG,
NAT_FLOAT,
NAT_DOUBLE,
NAT_LONGDOUBLE,
NAT_BOOL };
/*! Returns the \a NDT constant associated with \a T. */
template<typename T> inline NDT nativeType();
template<> inline NDT nativeType<char> () { return NAT_CHAR; }
template<> inline NDT nativeType<signed char> () { return NAT_SCHAR; }
template<> inline NDT nativeType<unsigned char> () { return NAT_UCHAR; }
template<> inline NDT nativeType<short> () { return NAT_SHORT; }
template<> inline NDT nativeType<unsigned short> () { return NAT_USHORT; }
template<> inline NDT nativeType<int> () { return NAT_INT; }
template<> inline NDT nativeType<unsigned int> () { return NAT_UINT; }
template<> inline NDT nativeType<long> () { return NAT_LONG; }
template<> inline NDT nativeType<unsigned long> () { return NAT_ULONG; }
template<> inline NDT nativeType<long long> () { return NAT_LONGLONG; }
template<> inline NDT nativeType<unsigned long long>() { return NAT_ULONGLONG; }
template<> inline NDT nativeType<float> () { return NAT_FLOAT; }
template<> inline NDT nativeType<double> () { return NAT_DOUBLE; }
template<> inline NDT nativeType<long double> () { return NAT_LONGDOUBLE;}
template<> inline NDT nativeType<bool> () { return NAT_BOOL; }
/*! Returns the size (in bytes) of the native data type \a type. */
inline int ndt2size (NDT type)
{
switch (type)
{
case NAT_CHAR :
case NAT_SCHAR :
case NAT_UCHAR : return sizeof(char);
case NAT_SHORT :
case NAT_USHORT : return sizeof(short);
case NAT_INT :
case NAT_UINT : return sizeof(int);
case NAT_LONG :
case NAT_ULONG : return sizeof(long);
case NAT_LONGLONG :
case NAT_ULONGLONG : return sizeof(long long);
case NAT_FLOAT : return sizeof(float);
case NAT_DOUBLE : return sizeof(double);
case NAT_LONGDOUBLE: return sizeof(long double);
case NAT_BOOL : return sizeof(bool);
default:
planck_fail ("ndt2size: unsupported data type");
}
}
#endif

View file

@ -0,0 +1,56 @@
/*
* This file is part of libcxxsupport.
*
* libcxxsupport is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* libcxxsupport is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with libcxxsupport; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik
* and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
* (DLR).
*/
/*
* Utilities for error reporting
*
* Copyright (C) 2003 - 2010 Max-Planck-Society
* Author: Martin Reinecke
*/
#include "error_handling.h"
#include <iostream>
#include <string>
using namespace std;
PlanckError::PlanckError(const string &message) : msg (message) {}
PlanckError::PlanckError(const char *message) : msg (message) {}
void planck_failure__(const char *file, int line, const char *func,
const string &msg)
{
cerr << "Error encountered at " << file << ", line " << line << endl;
if (func) cerr << "(function " << func << ")" << endl;
if (msg!="") cerr << endl << msg << endl;
cerr << endl;
}
void planck_failure__(const char *file, int line, const char *func,
const char *msg)
{ planck_failure__ (file,line,func,string(msg)); }
void killjob__()
{ throw; }

View file

@ -0,0 +1,100 @@
/*
* This file is part of libcxxsupport.
*
* libcxxsupport is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* libcxxsupport is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with libcxxsupport; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik
* and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
* (DLR).
*/
/*
* Utilities for error reporting
*
* Copyright (C) 2003 - 2010 Max-Planck-Society
* Authors: Reinhard Hell, Martin Reinecke
*/
#ifndef PLANCK_ERROR_HANDLING_H
#define PLANCK_ERROR_HANDLING_H
#include <string>
#include <iostream>
#if defined (__GNUC__)
#define PLANCK_FUNC_NAME__ __PRETTY_FUNCTION__
#else
#define PLANCK_FUNC_NAME__ 0
#endif
void planck_failure__(const char *file, int line, const char *func,
const std::string &msg);
void planck_failure__(const char *file, int line, const char *func,
const char *msg);
void killjob__();
class PlanckError
{
private:
std::string msg;
public:
explicit PlanckError(const std::string &message);
explicit PlanckError(const char *message);
virtual const char* what() const
{ return msg.c_str(); }
virtual ~PlanckError() {}
};
/*! \defgroup errorgroup Error handling */
/*! \{ */
/*! Writes diagnostic output and exits with an error status. */
#define planck_fail(msg) \
do { planck_failure__(__FILE__,__LINE__,PLANCK_FUNC_NAME__,msg); \
throw PlanckError(msg); } while(0)
/*! Throws a PlanckError without diagnostic message. */
#define planck_fail_quietly(msg) \
do { throw PlanckError(msg); } while(0)
/*! Writes diagnostic output and exits with an error status if \a testval
is \a false. */
#define planck_assert(testval,msg) \
do { if (testval); else planck_fail(msg); } while(0)
/*! Macro for improving error diagnostics. Should be placed immediately
after the opening brace of \c main(). Must be used in conjunction with
\c PLANCK_DIAGNOSIS_END. */
#define PLANCK_DIAGNOSIS_BEGIN try {
/*! Macro for improving error diagnostics. Should be placed immediately
before the closing brace of \c main(). Must be used in conjunction with
\c PLANCK_DIAGNOSIS_BEGIN. */
#define PLANCK_DIAGNOSIS_END \
} \
catch (PlanckError &) \
{ killjob__(); /* no need for further diagnostics; they were shown already */ } \
catch (std::exception &e) \
{ std::cerr << "std::exception: " << e.what() << std::endl; killjob__(); } \
catch (...) \
{ std::cerr << "Unknown exception" << std::endl; killjob__(); }
/*! \} */
#endif

View file

@ -0,0 +1,109 @@
/*
* This file is part of libcxxsupport.
*
* libcxxsupport is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* libcxxsupport is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with libcxxsupport; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik
* and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
* (DLR).
*/
/*
* Copyright (C) 2004-2010 Max-Planck-Society
* \author Martin Reinecke
*/
#ifndef PLANCK_FFTPACK_SUPPORT_H
#define PLANCK_FFTPACK_SUPPORT_H
#include "ls_fft.h"
#include "arr.h"
#include "xcomplex.h"
class cfft
{
private:
tsize n;
complex_plan plan;
public:
cfft () : n(0), plan(0) {}
cfft (tsize size_)
: n(size_), plan(make_complex_plan(size_)) {}
~cfft ()
{ if (plan!=0) kill_complex_plan (plan); }
void Set (tsize size_)
{
if (plan!=0) kill_complex_plan (plan);
n=size_;
plan=make_complex_plan(size_);
}
tsize size() const
{ return n; }
void forward (double *data)
{ complex_plan_forward(plan,data); }
void backward (double *data)
{ complex_plan_backward(plan,data); }
void forward (xcomplex<double> *data)
{ complex_plan_forward(plan,&(data->re)); }
void backward (xcomplex<double> *data)
{ complex_plan_backward(plan,&(data->re)); }
void forward (arr<xcomplex<double> >&data)
{ forward(&(data[0].re)); }
void backward (arr<xcomplex<double> >&data)
{ backward(&(data[0].re)); }
};
class rfft
{
private:
tsize n;
real_plan plan;
public:
rfft () : n(0), plan(0) {}
rfft (tsize size_)
: n(size_), plan(make_real_plan(size_)) {}
~rfft ()
{ if (plan!=0) kill_real_plan (plan); }
void Set (tsize size_)
{
if (plan!=0) kill_real_plan (plan);
n=size_;
plan=make_real_plan(size_);
}
tsize size() const
{ return n; }
void forward_fftpack (double *data)
{ real_plan_forward_fftpack(plan,data); }
void backward_fftpack (double *data)
{ real_plan_backward_fftpack(plan,data); }
void forward_fftpack (arr<double> &data)
{ forward_fftpack(&(data[0])); }
void backward_fftpack (arr<double> &data)
{ backward_fftpack(&(data[0])); }
void forward_c (arr<xcomplex<double> >&data)
{ real_plan_forward_c(plan,&(data[0].re)); }
void backward_c (arr<xcomplex<double> >&data)
{ real_plan_backward_c(plan,&(data[0].re)); }
};
#endif

View file

@ -0,0 +1,792 @@
/*
* This file is part of libcxxsupport.
*
* libcxxsupport is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* libcxxsupport is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with libcxxsupport; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik
* and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
* (DLR).
*/
/*
* This file contains the implementation of the FITS I/O helper class
* used by the Planck LevelS package.
*
* Copyright (C) 2002 - 2009 Max-Planck-Society
* Author: Martin Reinecke
*/
#include <sstream>
#include <cstring>
#include <vector>
#include "fitsio.h"
#include "fitshandle.h"
#include "cxxutils.h"
#include "safe_cast.h"
#define FPTR (static_cast<fitsfile *> (fptr))
#define OFPTR (static_cast<fitsfile *> (orig.fptr))
using namespace std;
namespace {
template<typename T> inline int fitsType();
template<> inline int fitsType<float> () { return TFLOAT; }
template<> inline int fitsType<double>() { return TDOUBLE; }
int type2bitpix (PDT type)
{
switch (type)
{
case PLANCK_FLOAT32: return FLOAT_IMG;
case PLANCK_FLOAT64: return DOUBLE_IMG;
default: planck_fail ("unsupported component type");
}
}
/*! Converts a FITS type code (i.e. the data type of a FITS column) to the
corresponding Planck type code. */
PDT ftc2type (int ftc)
{
switch (ftc)
{
case TLOGICAL : return PLANCK_BOOL;
case TBYTE : return PLANCK_INT8;
case TSHORT : return PLANCK_INT16;
case TINT :
case TINT32BIT: return PLANCK_INT32;
case TLONGLONG: return PLANCK_INT64;
case TFLOAT : return PLANCK_FLOAT32;
case TDOUBLE : return PLANCK_FLOAT64;
case TSTRING : return PLANCK_STRING;
default: planck_fail ("unsupported component type");
}
}
/*! Converts a Planck type code to the corresponding FITS type code
(i.e. the data type of a FITS column). */
int type2ftc (PDT type)
{
switch (type)
{
case PLANCK_BOOL : return TLOGICAL;
case PLANCK_INT8 :
case PLANCK_UINT8 : return TBYTE;
case PLANCK_INT16 : return TSHORT;
case PLANCK_INT32 : return TINT;
case PLANCK_INT64 : return TLONGLONG;
case PLANCK_FLOAT32: return TFLOAT;
case PLANCK_FLOAT64: return TDOUBLE;
case PLANCK_STRING : return TSTRING;
default: planck_fail ("unsupported component type");
}
}
const char *type2fitschar (PDT type)
{
switch (type)
{
case PLANCK_BOOL : return "L";
case PLANCK_FLOAT32: return "E";
case PLANCK_FLOAT64: return "D";
case PLANCK_INT8 :
case PLANCK_UINT8 : return "B";
case PLANCK_INT16 : return "I";
case PLANCK_INT32 : return "J";
case PLANCK_INT64 : return "K";
case PLANCK_STRING : return "A";
default:
planck_fail(string("unknown data type ")+type2string(type));
}
}
const char *type2asciiform (PDT type)
{
switch (type)
{
case PLANCK_FLOAT32: return "E14.7";
case PLANCK_FLOAT64: return "D23.15";
case PLANCK_UINT8 : return "I3";
case PLANCK_INT8 : return "I4";
case PLANCK_INT16 : return "I6";
case PLANCK_INT32 : return "I11";
case PLANCK_INT64 : return "I22";
default:
planck_fail(string("unknown data type ")+type2string(type));
}
}
string fixkey (const string &key)
{
for (tsize m=0; m<key.size(); ++m)
if (islower(key[m])) return string("HIERARCH "+key);
return key;
}
} // unnamed namespace
fitscolumn::fitscolumn()
: repcount_(0), type_(PLANCK_INVALID) {}
fitscolumn::fitscolumn (const string &nm, const string &un, int64 rc, PDT tp)
: name_(nm), unit_(un), repcount_(rc), type_(tp) {}
void fitshandle::check_errors() const
{
char msg[81];
if (status==0)
{
while (fits_read_errmsg(msg))
cerr << "STALE FITS ERROR MESSAGE: " << msg << endl;
fits_clear_errmsg();
return;
}
fits_get_errstatus (status, msg);
cerr << msg << endl;
while (fits_read_errmsg(msg)) cerr << msg << endl;
fits_clear_errmsg();
status=0;
planck_fail("FITS error");
}
void fitshandle::clean_data()
{
if (!fptr) return;
axes_.clear();
columns_.clear();
hdutype_=INVALID;
bitpix_=INVALID;
nrows_=0;
}
void fitshandle::clean_all()
{
if (!fptr) return;
clean_data();
fits_close_file (FPTR, &status);
check_errors();
fptr=0;
}
bool fitshandle::table_hdu (tsize col) const
{
if ((hdutype_!=ASCII_TBL) && (hdutype_!=BINARY_TBL)) return false;
if ((col<=0) || (col>columns_.size())) return false;
return true;
}
bool fitshandle::image_hdu () const
{ return hdutype_==IMAGE_HDU; }
void fitshandle::init_image()
{
int naxis;
fits_get_img_type (FPTR, &bitpix_, &status);
fits_get_img_dim (FPTR, &naxis, &status);
check_errors();
arr<LONGLONG> naxes(naxis);
fits_get_img_sizell (FPTR, naxis, &naxes[0], &status);
for (long m=0; m<naxis; ++m) axes_.push_back(naxes[naxis-m-1]);
check_errors();
}
void fitshandle::init_asciitab()
{
char ttype[81], tunit[81], tform[81];
int ncol, typecode;
fits_get_num_cols (FPTR, &ncol, &status);
{ LONGLONG tmp; fits_get_num_rowsll (FPTR, &tmp, &status); nrows_=tmp; }
check_errors();
for (int m=1; m<=ncol; ++m)
{
fits_get_acolparms (FPTR, m, ttype, 0, tunit, tform,
0, 0, 0, 0, &status);
fits_ascii_tform (tform, &typecode, 0,0, &status);
check_errors();
columns_.push_back (fitscolumn (ttype,tunit,1,ftc2type(typecode)));
}
}
void fitshandle::init_bintab()
{
char ttype[81], tunit[81], tform[81];
LONGLONG repc;
int ncol, typecode;
fits_get_num_cols (FPTR, &ncol, &status);
{ LONGLONG tmp; fits_get_num_rowsll (FPTR, &tmp, &status); nrows_=tmp; }
check_errors();
for (int m=1; m<=ncol; ++m)
{
fits_get_bcolparmsll (FPTR, m, ttype, tunit, tform, &repc,
0, 0, 0, 0, &status);
fits_binary_tform (tform, &typecode, 0,0, &status);
check_errors();
columns_.push_back (fitscolumn (ttype,tunit,repc,ftc2type(typecode)));
}
}
void fitshandle::init_data()
{
clean_data();
fits_get_hdu_type (FPTR, &hdutype_, &status);
check_errors();
switch(hdutype_)
{
case IMAGE_HDU:
init_image(); break;
case ASCII_TBL:
init_asciitab(); break;
case BINARY_TBL:
init_bintab(); break;
default:
planck_fail("init_data(): unsupported HDU type"); break;
}
}
void fitshandle::read_col (int colnum, void *data, int64 ndata, PDT type,
int64 offset) const
{
planck_assert(table_hdu(colnum),"incorrect FITS table access");
int64 repc = columns_[colnum-1].repcount();
planck_assert (ndata<=(repc*nrows_-offset),"read_column(): array too large");
int64 frow = offset/repc+1;
int64 felem = offset%repc+1;
fits_read_col (FPTR, type2ftc(type), colnum, frow, felem, ndata, 0, data, 0,
&status);
check_errors();
}
void fitshandle::write_col (int colnum, const void *data, int64 ndata,
PDT type, int64 offset)
{
planck_assert(table_hdu(colnum),"incorrect FITS table access");
int64 repc = columns_[colnum-1].repcount();
int64 frow = offset/repc+1;
int64 felem = offset%repc+1;
fits_write_col (FPTR, type2ftc(type), colnum, frow, felem, ndata,
const_cast<void *>(data), &status);
nrows_ = max(nrows_,offset+ndata);
check_errors();
}
void fitshandle::getKeyHelper(const string &name) const
{
if (status==KEY_NO_EXIST)
{
fits_clear_errmsg();
status=0;
planck_fail("fitshandle::get_key(): key '"+name+"' not found");
}
check_errors();
}
void fitshandle::open (const string &fname)
{
clean_all();
fitsfile *ptr;
fits_open_file(&ptr, fname.c_str(), READONLY, &status);
fptr=ptr;
check_errors();
init_data();
}
void fitshandle::create (const string &fname)
{
clean_all();
fitsfile *ptr;
fits_create_file(&ptr, fname.c_str(), &status);
fptr=ptr;
fits_write_imghdr(FPTR, 8, 0, 0, &status); // insert empty PHDU
fits_write_date(FPTR, &status);
check_errors();
init_data();
}
// static
void fitshandle::delete_file (const string &name)
{
fitsfile *ptr;
int stat = 0;
fits_open_file(&ptr, name.c_str(), READWRITE, &stat);
fits_delete_file(ptr, &stat);
if (stat==0) return;
char msg[81];
fits_get_errstatus (stat, msg);
cerr << msg << endl;
while (fits_read_errmsg(msg)) cerr << msg << endl;
planck_fail("FITS error");
}
void fitshandle::goto_hdu (int hdu)
{
int curhdu;
fits_get_hdu_num(FPTR,&curhdu);
if (curhdu!=hdu)
{
fits_movabs_hdu(FPTR, hdu, &hdutype_, &status);
check_errors();
init_data();
}
}
int fitshandle::num_hdus () const
{
int result;
fits_get_num_hdus (FPTR, &result, &status);
check_errors();
return result;
}
void fitshandle::insert_bintab (const vector<fitscolumn> &cols,
const string &extname)
{
clean_data();
int ncol=cols.size();
arr2b<char> ttype(ncol,81), tform(ncol,81), tunit(ncol,81);
for (long m=0; m<ncol; ++m)
{
strcpy (ttype[m], cols[m].name().c_str());
strcpy (tunit[m], cols[m].unit().c_str());
ostringstream x;
x << cols[m].repcount() << type2fitschar(cols[m].type());
strcpy (tform[m], x.str().c_str());
}
fits_insert_btbl (FPTR, nrows_, ncol, ttype.p0(), tform.p0(), tunit.p0(),
const_cast<char *>(extname.c_str()), 0, &status);
check_errors();
init_data();
}
void fitshandle::insert_asctab (const vector<fitscolumn> &cols,
const string &extname)
{
clean_data();
int ncol=cols.size();
arr2b<char> ttype(ncol,81), tform(ncol,81), tunit(ncol,81);
for (long m=0; m<ncol; ++m)
{
strcpy (ttype[m], cols[m].name().c_str());
strcpy (tunit[m], cols[m].unit().c_str());
ostringstream x;
if (cols[m].type()!=TSTRING)
{
planck_assert (cols[m].repcount()==1,"bad repcount for ASCII table");
x << type2asciiform(cols[m].type());
}
else
{
x << "A" << dataToString(cols[m].repcount());
}
strcpy (tform[m], x.str().c_str());
}
fits_insert_atbl (FPTR, 0, nrows_, ncol, ttype.p0(), 0, tform.p0(),
tunit.p0(), const_cast<char *>(extname.c_str()), &status);
check_errors();
init_data();
}
void fitshandle::insert_image (PDT type, const vector<int64> &Axes)
{
clean_data();
arr<LONGLONG> tmpax(Axes.size());
for (long m=0; m<long(Axes.size()); m++) tmpax[m]=Axes[Axes.size()-1-m];
fits_insert_imgll (FPTR, type2bitpix(type), Axes.size(), &tmpax[0], &status);
check_errors();
init_data();
}
template<typename T>
void fitshandle::insert_image (PDT type, const arr2<T> &data)
{
clean_data();
arr<LONGLONG> tmpax(2);
tmpax[0] = data.size2(); tmpax[1] = data.size1();
fits_insert_imgll (FPTR, type2bitpix(type), 2, &tmpax[0], &status);
arr2<T> &tmparr = const_cast<arr2<T> &> (data);
fits_write_img (FPTR, fitsType<T>(), 1, tmpax[0]*tmpax[1],
&tmparr[0][0], &status);
check_errors();
init_data();
}
template void fitshandle::insert_image (PDT type, const arr2<double> &data);
template void fitshandle::insert_image (PDT type, const arr2<float> &data);
void fitshandle::write_checksum()
{
planck_assert(connected(),"handle not connected to a file");
fits_write_chksum (FPTR, &status);
check_errors();
}
const vector<int64> &fitshandle::axes() const
{
planck_assert(image_hdu(),"not connected to an image");
return axes_;
}
const string &fitshandle::colname(int i) const
{
planck_assert(table_hdu(i),"incorrect FITS table access");
return columns_[i-1].name();
}
const string &fitshandle::colunit(int i) const
{
planck_assert(table_hdu(i),"incorrect FITS table access");
return columns_[i-1].unit();
}
int64 fitshandle::repcount(int i) const
{
planck_assert(table_hdu(i),"incorrect FITS table access");
return columns_[i-1].repcount();
}
PDT fitshandle::coltype(int i) const
{
planck_assert(table_hdu(i),"incorrect FITS table access");
return columns_[i-1].type();
}
int fitshandle::ncols() const
{
planck_assert(table_hdu(1),"incorrect FITS table access");
return columns_.size();
}
int64 fitshandle::nrows() const
{
planck_assert(table_hdu(1),"incorrect FITS table access");
return nrows_;
}
int64 fitshandle::nelems(int i) const
{
planck_assert(table_hdu(i),"incorrect FITS table access");
if (columns_[i-1].type()==PLANCK_STRING) return nrows_;
return nrows_*columns_[i-1].repcount();
}
int64 fitshandle::efficientChunkSize(int i) const
{
planck_assert(table_hdu(1),"incorrect FITS table access");
long int res;
fits_get_rowsize(FPTR, &res, &status);
planck_assert(res>=1,"bad recommended FITS chunk size");
check_errors();
return res*columns_[i-1].repcount();
}
void fitshandle::get_all_keys(vector<string> &keys) const
{
keys.clear();
char card[81];
const char *inclist[] = { "*" };
planck_assert(connected(),"handle not connected to a file");
fits_read_record (FPTR, 0, card, &status);
check_errors();
while (true)
{
fits_find_nextkey (FPTR, const_cast<char **>(inclist), 1,
0, 0, card, &status);
if (status!=0) break;
if (fits_get_keyclass(card)==TYP_USER_KEY)
{
char keyname[80];
int dummy;
fits_get_keyname(card, keyname, &dummy, &status);
check_errors();
keys.push_back(trim(keyname));
}
check_errors();
}
if (status==KEY_NO_EXIST) { fits_clear_errmsg(); status=0; }
check_errors();
}
void fitshandle::set_key_void (const string &key, const void *value,
PDT type, const string &comment)
{
planck_assert(connected(),"handle not connected to a file");
string key2 = fixkey(key);
switch (type)
{
case PLANCK_INT8:
case PLANCK_UINT8:
case PLANCK_INT16:
case PLANCK_INT32:
case PLANCK_INT64:
case PLANCK_FLOAT32:
case PLANCK_FLOAT64:
fits_update_key (FPTR, type2ftc(type), const_cast<char *>(key2.c_str()),
const_cast<void *>(value), const_cast<char *>(comment.c_str()),
&status);
break;
case PLANCK_BOOL:
{
int val = *(static_cast<const bool *>(value));
fits_update_key (FPTR, TLOGICAL, const_cast<char *>(key2.c_str()),
&val, const_cast<char *>(comment.c_str()), &status);
break;
}
case PLANCK_STRING:
{
string val = *(static_cast<const string *>(value));
fits_update_key_longstr (FPTR, const_cast<char *>(key2.c_str()),
const_cast<char *>(val.c_str()), const_cast<char *>(comment.c_str()),
&status);
break;
}
default:
planck_fail ("unsupported data type in set_key_void()");
}
check_errors();
}
void fitshandle::get_key_void (const string &name, void *value, PDT type) const
{
planck_assert(connected(),"handle not connected to a file");
switch (type)
{
case PLANCK_INT8:
case PLANCK_UINT8:
case PLANCK_INT16:
case PLANCK_INT32:
case PLANCK_INT64:
case PLANCK_FLOAT32:
case PLANCK_FLOAT64:
fits_read_key (FPTR, type2ftc(type), const_cast<char *>(name.c_str()),
value, 0, &status);
getKeyHelper(name);
break;
case PLANCK_BOOL:
{
int val;
fits_read_key (FPTR, TLOGICAL, const_cast<char *>(name.c_str()), &val, 0,
&status);
getKeyHelper(name);
*(static_cast<bool *>(value))=val;
break;
}
case PLANCK_STRING:
{
char *tmp=0;
fits_read_key_longstr (FPTR, const_cast<char *>(name.c_str()), &tmp, 0,
&status);
getKeyHelper(name);
*(static_cast<string *>(value))=tmp;
if (tmp) free(tmp);
break;
}
default:
planck_fail ("unsupported data type in get_key_void()");
}
check_errors();
}
void fitshandle::delete_key (const string &name)
{
planck_assert(connected(),"handle not connected to a file");
fits_delete_key (FPTR, const_cast<char *>(name.c_str()), &status);
check_errors();
}
void fitshandle::add_comment(const string &comment)
{
planck_assert(connected(),"handle not connected to a file");
fits_write_comment(FPTR,const_cast<char *>(comment.c_str()),&status);
check_errors();
}
bool fitshandle::key_present(const string &name) const
{
char card[81];
planck_assert(connected(),"handle not connected to a file");
fits_read_card(FPTR, const_cast<char *>(name.c_str()), card, &status);
if (status==KEY_NO_EXIST)
{ fits_clear_errmsg(); status=0; return false; }
check_errors();
return true;
}
void fitshandle::assert_pdmtype (const string &pdmtype) const
{
string type;
get_key("PDMTYPE",type);
if (pdmtype==type) return;
cerr << "PDMTYPE " << pdmtype << " expected, but found " << type << endl;
}
void fitshandle::read_column_raw_void
(int colnum, void *data, PDT type, int64 num, int64 offset) const
{
switch (type)
{
case PLANCK_INT8:
case PLANCK_UINT8:
case PLANCK_INT16:
case PLANCK_INT32:
case PLANCK_INT64:
case PLANCK_FLOAT32:
case PLANCK_FLOAT64:
case PLANCK_BOOL:
read_col (colnum, data, num, type, offset); break;
case PLANCK_STRING:
{
string *data2 = static_cast<string *> (data);
planck_assert(table_hdu(colnum),"incorrect FITS table access");
planck_assert (num<=(nrows_-offset),
"read_column(): array too large");
arr2b<char> tdata(safe_cast<tsize>(num),
safe_cast<tsize>(columns_[colnum-1].repcount()+1));
fits_read_col (FPTR, TSTRING, colnum, offset+1, 1, num,
0, tdata.p0(), 0, &status);
check_errors();
for (long m=0;m<num;++m) data2[m]=tdata[m];
break;
}
default:
planck_fail ("unsupported data type in read_column_raw_void()");
}
}
void fitshandle::write_column_raw_void
(int colnum, const void *data, PDT type, int64 num, int64 offset)
{
switch (type)
{
case PLANCK_INT8:
case PLANCK_UINT8:
case PLANCK_INT16:
case PLANCK_INT32:
case PLANCK_INT64:
case PLANCK_FLOAT32:
case PLANCK_FLOAT64:
case PLANCK_BOOL:
write_col (colnum, data, num, type, offset); break;
case PLANCK_STRING:
{
const string *data2 = static_cast<const string *> (data);
planck_assert(table_hdu(colnum),"incorrect FITS table access");
tsize stringlen = safe_cast<tsize>(columns_[colnum-1].repcount()+1);
arr2b<char> tdata(safe_cast<tsize>(num), stringlen);
for (long m=0;m<num;++m)
{
strncpy(tdata[m],data2[m].c_str(),stringlen-1);
tdata[m][stringlen-1] = '\0';
}
fits_write_col (FPTR, TSTRING, colnum, offset+1, 1, num,
tdata.p0(), &status);
nrows_ = max(nrows_,offset+num);
check_errors();
break;
}
default:
planck_fail ("unsupported data type in write_column_raw_void()");
}
}
void fitshandle::write_image2D_void (const void *data, PDT type, tsize s1,
tsize s2)
{
planck_assert(image_hdu(),"not connected to an image");
planck_assert (axes_.size()==2, "wrong number of dimensions");
planck_assert (axes_[0]==int64(s1), "wrong size of dimension 1");
planck_assert (axes_[1]==int64(s2), "wrong size of dimension 2");
fits_write_img (FPTR, type2ftc(type), 1, axes_[0]*axes_[1],
const_cast<void *>(data), &status);
check_errors();
}
void fitshandle::write_subimage_void (const void *data, PDT type, tsize sz,
int64 offset)
{
planck_assert(image_hdu(),"not connected to an image");
fits_write_img (FPTR, type2ftc(type), 1+offset, sz, const_cast<void *>(data),
&status);
check_errors();
}
template<typename T> void fitshandle::read_image (arr2<T> &data) const
{
planck_assert(image_hdu(),"not connected to an image");
planck_assert (axes_.size()==2, "wrong number of dimensions");
data.alloc(safe_cast<tsize>(axes_[0]), safe_cast<tsize>(axes_[1]));
fits_read_img (FPTR, fitsType<T>(), 1, axes_[0]*axes_[1], 0, &data[0][0], 0,
&status);
check_errors();
}
template void fitshandle::read_image (arr2<float> &data) const;
template void fitshandle::read_image (arr2<double> &data) const;
template<typename T> void fitshandle::read_image (arr3<T> &data) const
{
planck_assert(image_hdu(),"not connected to an image");
planck_assert (axes_.size()==3, "wrong number of dimensions");
data.alloc(safe_cast<tsize>(axes_[0]), safe_cast<tsize>(axes_[1]),
safe_cast<tsize>(axes_[2]));
fits_read_img (FPTR, fitsType<T>(), 1, axes_[0]*axes_[1]*axes_[2],
0, &data(0,0,0), 0, &status);
check_errors();
}
template void fitshandle::read_image (arr3<float> &data) const;
template void fitshandle::read_image (arr3<double> &data) const;
template<typename T> void fitshandle::read_subimage
(arr2<T> &data, int xl, int yl) const
{
planck_assert(image_hdu(),"not connected to an image");
planck_assert (axes_.size()==2, "wrong number of dimensions");
for (tsize m=0; m<data.size1(); ++m)
fits_read_img (FPTR, fitsType<T>(), (xl+m)*axes_[1]+yl+1,
data.size2(), 0, &data[m][0], 0, &status);
check_errors();
}
template void fitshandle::read_subimage
(arr2<float> &data, int xl, int yl) const;
template void fitshandle::read_subimage
(arr2<double> &data, int xl, int yl) const;
void fitshandle::read_subimage_void (void *data, PDT type, tsize ndata,
int64 offset) const
{
planck_assert(image_hdu(),"not connected to an image");
fits_read_img (FPTR, type2ftc(type), 1+offset, ndata, 0, data, 0, &status);
check_errors();
}
namespace {
class cfitsio_checker
{
public:
cfitsio_checker()
{
float fitsversion;
planck_assert(fits_get_version(&fitsversion),
"error calling fits_get_version()");
int v_header = nearest<int>(1000.*CFITSIO_VERSION),
v_library = nearest<int>(1000.*fitsversion);
if (v_header!=v_library)
cerr << endl << "WARNING: version mismatch between CFITSIO header (v"
<< dataToString(v_header*0.001) << ") and linked library (v"
<< dataToString(v_library*0.001) << ")." << endl << endl;
}
};
cfitsio_checker Cfitsio_Checker;
} // unnamed namespace

301
external/healpix/cxxsupport/fitshandle.h vendored Normal file
View file

@ -0,0 +1,301 @@
/*
* This file is part of libcxxsupport.
*
* libcxxsupport is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* libcxxsupport is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with libcxxsupport; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik
* and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
* (DLR).
*/
/*! \file fitshandle.h
* Declaration of the FITS I/O helper class used by LevelS
*
* Copyright (C) 2002 - 2009 Max-Planck-Society
* \author Martin Reinecke
*/
#ifndef PLANCK_FITSHANDLE_H
#define PLANCK_FITSHANDLE_H
#include <string>
#include <vector>
#include "arr.h"
#include "datatypes.h"
#include "safe_cast.h"
/*! \defgroup fitsgroup FITS-related functionality */
/*! \{ */
/*! Class containing information about a single column in a FITS table. */
class fitscolumn
{
private:
std::string name_, unit_;
int64 repcount_;
PDT type_;
public:
fitscolumn();
/*! Creates a \a fitscolumn with name \a nm, unit \a un, a repetition
count of \a rc, and a Planck type of \a tp. */
fitscolumn (const std::string &nm, const std::string &un, int64 rc, PDT tp);
/*! Returns the column name. */
const std::string &name() const {return name_;}
/*! Returns the column unit string. */
const std::string &unit() const {return unit_;}
/*! Returns the repetition count of the column. */
int64 repcount() const {return repcount_;}
/*! Returns the Planck type of the column. */
PDT type() const {return type_;}
};
/*! Class for performing I/O from/to FITS files. */
class fitshandle
{
private:
enum { INVALID = -4711 };
mutable int status;
void *fptr;
int hdutype_, bitpix_;
std::vector<int64> axes_;
std::vector<fitscolumn> columns_;
int64 nrows_;
void check_errors() const;
void clean_data();
void clean_all();
bool connected() const { return (hdutype_!=INVALID); }
bool table_hdu (tsize col) const;
bool image_hdu () const;
void init_image();
void init_asciitab();
void init_bintab();
void init_data();
void read_col (int colnum, void *data, int64 ndata, PDT type,
int64 offset) const;
void write_col (int colnum, const void *data, int64 ndata, PDT type,
int64 offset);
void getKeyHelper(const std::string &name) const;
public:
/*! the list of modes in which a \a fitshandle can be opened. */
enum openmethod { CREATE, /*!< the file must not yet exist */
OPEN /*!< the file must already exist */
};
/*! \name File-level access and manipulation. */
/*! \{ */
/*! Creates an unconnected \a fitshandle. */
fitshandle ()
: status(0), fptr(0), hdutype_(INVALID), bitpix_(INVALID), nrows_(0) {}
/*! Performs all necessary cleanups. */
~fitshandle() { clean_all(); }
/*! Connects to the file \a fname. */
void open (const std::string &fname);
/*! Creates the file \a fname and connects to it. */
void create (const std::string &fname);
/*! Closes the current file. */
void close () { clean_all(); }
/*! Deletes the file with name \a name. */
static void delete_file (const std::string &name);
/*! Jumps to the HDU with the absolute number \a hdu. */
void goto_hdu (int hdu);
/*! Returns the number of HDUs in the file. */
int num_hdus () const;
/*! Asserts that the PDMTYPE of the current HDU is \a pdmtype. */
void assert_pdmtype (const std::string &pdmtype) const;
/*! Inserts a binary table described by \a cols.
The HDU has the name \a extname. */
void insert_bintab (const std::vector<fitscolumn> &cols,
const std::string &extname="xtension");
/*! Inserts an ASCII table described by \a cols. The width of the
columns is chosen automatically, in a way that avoids truncation.
The HDU has the name \a extname. */
void insert_asctab (const std::vector<fitscolumn> &cols,
const std::string &extname="xtension");
/*! Inserts a FITS image with the type given by \a type and dimensions
given by \a Axes. */
void insert_image (PDT type, const std::vector<int64> &Axes);
/*! Inserts a 2D FITS image with the type given by \a type, whose
contents are given in \a data. */
template<typename T>
void insert_image (PDT type, const arr2<T> &data);
/*! Computes the checksum for the current HDU and writes it into the
header. */
void write_checksum();
/*! \} */
/*! \name Information about the current HDU */
/*! \{ */
/*! Returns the dimensions of the current image. */
const std::vector<int64> &axes() const;
/*! Returns the name of column \a #i. */
const std::string &colname(int i) const;
/*! Returns the unit of column \a #i. */
const std::string &colunit(int i) const;
/*! Returns repetition count of column \a #i. */
int64 repcount(int i) const;
/*! Returns the Planck type for column \a #i. */
PDT coltype(int i) const;
/*! Returns the number of columns in the current table. */
int ncols() const;
/*! Returns the number of rows in the current table. */
int64 nrows() const;
/*! Returns the total number of elements (nrows*repcount)
in column \a #i. */
int64 nelems(int i) const;
/*! Returns the number of elements that should be read/written in a single
call for optimum performance. This depends on the current HDU. */
int64 efficientChunkSize(int i) const;
/*! \} */
/*! \name Keyword-handling methods */
/*! \{ */
/*! Returns a list of all user-defined keys in the current HDU
in \a keys. */
void get_all_keys (std::vector<std::string> &keys) const;
void set_key_void (const std::string &key, const void *value, PDT type,
const std::string &comment="");
/*! Updates \a key with \a value and \a comment. */
template<typename T> void set_key (const std::string &name,
const T &value, const std::string &comment="")
{ set_key_void (name, &value, planckType<T>(), comment); }
/*! Deletes \a key from the header. */
void delete_key (const std::string &name);
/*! Adds \a comment as a comment line. */
void add_comment (const std::string &comment);
void get_key_void (const std::string &key, void *value, PDT type) const;
/*! Reads the value belonging to \a key and returns it in \a value. */
template<typename T> void get_key (const std::string &name, T &value) const
{ get_key_void (name,&value,planckType<T>()); }
/*! Returms the value belonging to \a key. */
template<typename T> T get_key (const std::string &name) const
{ T tmp; get_key(name, tmp); return tmp; }
/*! Returns \a true if \a key is present, else \a false. */
bool key_present (const std::string &name) const;
/*! \} */
/*! \name Methods for table data I/O */
/*! \{ */
void read_column_raw_void
(int colnum, void *data, PDT type, int64 num, int64 offset=0) const;
/*! Copies \a num elements from column \a colnum to the memory pointed
to by \a data, starting at offset \a offset in the column. */
template<typename T> void read_column_raw
(int colnum, T *data, int64 num, int64 offset=0) const
{ read_column_raw_void (colnum, data, planckType<T>(), num, offset); }
/*! Fills \a data with elements from column \a colnum,
starting at offset \a offset in the column. */
template<typename T> void read_column
(int colnum, arr<T> &data, int64 offset=0) const
{ read_column_raw (colnum, &(data[0]), data.size(), offset); }
/*! Reads the element \a #offset from column \a colnum into \a data. */
template<typename T> void read_column
(int colnum, T &data, int64 offset=0) const
{ read_column_raw (colnum, &data, 1, offset); }
/*! Reads the whole column \a colnum into \a data (which is resized
accordingly). */
template<typename T> void read_entire_column
(int colnum, arr<T> &data) const
{
data.alloc(safe_cast<tsize>(nelems(colnum)));
read_column (colnum, data);
}
void write_column_raw_void
(int colnum, const void *data, PDT type, int64 num, int64 offset=0);
/*! Copies \a num elements from the memory pointed to by \a data to the
column \a colnum, starting at offset \a offset in the column. */
template<typename T> void write_column_raw
(int colnum, const T *data, int64 num, int64 offset=0)
{ write_column_raw_void (colnum, data, planckType<T>(), num, offset); }
/*! Copies all elements from \a data to the
column \a colnum, starting at offset \a offset in the column. */
template<typename T> void write_column
(int colnum, const arr<T> &data, int64 offset=0)
{ write_column_raw (colnum, &(data[0]), data.size(), offset); }
/*! Copies \a data to the column \a colnum, at the position \a offset. */
template<typename T> void write_column
(int colnum, const T &data, int64 offset=0)
{ write_column_raw (colnum, &data, 1, offset); }
/*! \} */
/*! \name Methods for image data I/O */
/*! \{ */
/*! Reads the current image into \a data, which is resized accordingly. */
template<typename T> void read_image (arr2<T> &data) const;
/*! Reads the current image into \a data, which is resized accordingly. */
template<typename T> void read_image (arr3<T> &data) const;
/*! Reads a partial image, whose dimensions are given by the dimensions
of \a data, into data. The starting pixel indices are given by
\a xl and \a yl. */
template<typename T> void read_subimage
(arr2<T> &data, int xl, int yl) const;
void read_subimage_void (void *data, PDT type, tsize ndata, int64 offset=0)
const;
/*! Fills \a data with values from the image, starting at the offset
\a offset in the image. The image is treated as a one-dimensional
array. */
template<typename T> void read_subimage (arr<T> &data, int64 offset=0)
const
{ read_subimage_void (&data[0],planckType<T>(),data.size(),offset); }
void write_image2D_void (const void *data, PDT type, tsize s1,
tsize s2);
/*! Writes \a data into the current image. \a data must have the same
dimensions as specified in the HDU. */
template<typename T> void write_image (const arr2<T> &data)
{
write_image2D_void (&data[0][0],planckType<T>(),data.size1(),
data.size2());
}
void write_subimage_void (const void *data, PDT type, tsize sz,
int64 offset);
/*! Copies \a data to the image, starting at the offset
\a offset in the image. The image is treated as a one-dimensional
array. */
template<typename T> void write_subimage (const arr<T> &data,
int64 offset=0)
{ write_subimage_void(&data[0],planckType<T>(),data.size(),offset); }
/*! \} */
};
/*! \} */
#endif

3848
external/healpix/cxxsupport/font_data.inc vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,60 @@
/*
* This file is part of libcxxsupport.
*
* libcxxsupport is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* libcxxsupport is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with libcxxsupport; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik
* and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
* (DLR).
*/
/*! \file geom_utils.h
* Geometric utility functions.
*
* Copyright (C) 2003, 2006 Max-Planck-Society
* \author Martin Reinecke
* \author Reinhard Hell
*/
#ifndef PLANCK_GEOM_UTILS_H
#define PLANCK_GEOM_UTILS_H
#include "cxxutils.h"
#include "vec3.h"
/*! Returns the orientation when looking from point \a loc on the unit
sphere in the direction \a dir. \a loc must be normalized. The result
ranges from -pi to pi, is 0 for North and pi/2 for West, i.e. the angle
is given in mathematically positive sense.
If \a loc is the North or South pole, the returned angle is
\a atan2(dir.y,dir.x). */
inline double orientation (const vec3 &loc, const vec3 &dir)
{
// FIXME: here is still optimization potential
if (loc.x==0 && loc.y==0)
return (loc.z>0) ? safe_atan2(dir.y,-dir.x) : safe_atan2(dir.y,dir.x);
vec3 east (-loc.y, loc.x, 0);
vec3 north = crossprod(loc,east);
return safe_atan2(-dotprod(dir,east),dotprod(dir,north));
}
/*! Returns the angle between \a v1 and \a v2 in radians. */
inline double v_angle (const vec3 &v1, const vec3 &v2)
{ return atan2 (crossprod(v1,v2).Length(), dotprod(v1,v2)); }
#endif

View file

@ -0,0 +1,15 @@
#ifndef LEVELS_FACILITIES_H
#define LEVELS_FACILITIES_H
int syn_alm_cxx_module (int argc, const char **argv);
int alm2map_cxx_module (int argc, const char **argv);
int anafast_cxx_module (int argc, const char **argv);
int calc_powspec_module (int argc, const char **argv);
int hotspots_cxx_module (int argc, const char **argv);
int map2tga_module (int argc, const char **argv);
int median_filter_cxx_module (int argc, const char **argv);
int mult_alm_module (int argc, const char **argv);
int smoothing_cxx_module (int argc, const char **argv);
int udgrade_cxx_module (int argc, const char **argv);
#endif

219
external/healpix/cxxsupport/ls_image.cc vendored Normal file
View file

@ -0,0 +1,219 @@
/*
* This file is part of libcxxsupport.
*
* libcxxsupport is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* libcxxsupport is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with libcxxsupport; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik
* and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
* (DLR).
*/
/*
* Classes for creation and output of image files
*
* Copyright (C) 2003 Max-Planck-Society
* Author: Martin Reinecke
*/
#include <fstream>
#include <sstream>
#include "ls_image.h"
#include "bstream.h"
#include "font_data.inc"
using namespace std;
const Font medium_bold_font = { 0, 128, 7, 13, medium_bold_font_data };
const Font giant_font = { 0, 128, 9, 15, giant_font_data };
void Palette::setPredefined (int num)
{
fv.clear(); cv.clear();
switch(num)
{
case 0:
add(0,Colour(0,0,0));
add(1,Colour(1,1,1));
break;
case 1:
add(0,Colour(0,0,0));
add(0.4f,Colour(0,0,0.5f));
add(0.75f,Colour(0,0.6f,1));
add(1,Colour(1,1,1));
break;
case 4:
add(0,Colour(0,0,.5f));
add(0.15f,Colour(0,0,1));
add(0.4f,Colour(0,1,1));
add(0.7f,Colour(1,1,0));
add(0.9f,Colour(1,.33f,0));
add(1,Colour(.5f,0,0));
break;
default:
planck_fail("Palette #"+dataToString(num)+" not yet supported.");
}
}
void LS_Image::write_char (int xpos, int ypos, const Colour &col, char c,
int scale)
{
planck_assert ((c>=font.offset) && (c<font.offset+font.num_chars),
"write_char: character out of range");
for (int i=0; i<font.xpix; ++i)
for (int j=0; j<font.ypix; ++j)
{
int ofs = (c-font.offset)*font.xpix*font.ypix + j*font.xpix + i;
if (font.data[ofs]!=' ')
for (int m=0; m<scale; ++m)
for (int n=0; n<scale; ++n)
put_pixel(xpos+scale*i+m,ypos+scale*j+n,col);
}
}
LS_Image::LS_Image ()
: font(medium_bold_font) {}
LS_Image::LS_Image (int xres, int yres)
: font(medium_bold_font), pixel(xres,yres,Colour(0,0,0)) {}
void LS_Image::annotate (int xpos, int ypos, const Colour &col,
const string &text, int scale)
{
for (tsize m=0; m<text.length(); ++m)
write_char(xpos+m*scale*font.xpix, ypos, col, text[m],scale);
}
void LS_Image::annotate_centered (int xpos, int ypos, const Colour &col,
const string &text, int scale)
{
xpos-=(scale*text.length()*font.xpix)/2;
ypos-=scale*font.ypix/2;
annotate (xpos,ypos,col,text,scale);
}
void LS_Image::set_font (const Font &fnt)
{ font = fnt; }
void LS_Image::write_TGA (const string &file) const
{
ofstream out(file.c_str(), ios_base::out | ios_base::binary);
planck_assert(out, "could not create file '" + file + "'");
tsize xres=pixel.size1(), yres=pixel.size2();
bostream bo(out);
const uint8 header[18] = { 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
uint8(xres%256), uint8(xres/256), uint8(yres%256), uint8(yres/256), 24, 32};
bo.put (header, 18);
for (tsize j=0; j<yres; ++j)
for (tsize i=0; i<xres; ++i)
bo << pixel[i][j].b << pixel[i][j].g << pixel[i][j].r;
}
namespace {
void write_equal_range (const arr<Colour8> &px, tsize begin, tsize end,
bostream &file)
{
chunkMaker cm (end-begin,128);
uint64 cbeg, csz;
while (cm.getNext(cbeg,csz))
{
file << uint8(csz-1+128);
file << px[begin].b << px[begin].g << px[begin].r;
}
}
void write_unequal_range (const arr<Colour8> &px, tsize begin, tsize end,
bostream &file)
{
chunkMaker cm (end-begin,128);
uint64 cbeg, csz;
while (cm.getNext(cbeg,csz))
{
file << uint8(csz-1);
for (tsize cnt=begin+cbeg; cnt< begin+cbeg+csz; ++cnt)
file << px[cnt].b << px[cnt].g << px[cnt].r;
}
}
} // unnamed namespace
void LS_Image::write_TGA_rle(const string &file) const
{
ofstream out(file.c_str(), ios_base::out | ios_base::binary);
planck_assert(out, "could not create file '" + file + "'");
tsize xres=pixel.size1(), yres=pixel.size2();
bostream bo(out);
const uint8 header[18] = { 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0,
xres%256, xres/256, yres%256, yres/256, 24, 32 };
bo.put(header,18);
for (tsize y=0; y<yres; ++y)
{
arr<Colour8> px(xres);
for (tsize x=0; x<xres; ++x) px[x] = pixel[x][y];
tsize xstart=0;
while (xstart<xres)
{
if (xstart==xres-1)
{
write_unequal_range (px,xstart,xstart+1,bo);
xstart=xres;
}
else
{
if (px[xstart+1]==px[xstart]) // range of equal pixels
{
tsize xend=xstart+2;
while ((xend<xres) && (px[xend]==px[xstart])) ++xend;
write_equal_range (px,xstart,xend,bo);
xstart=xend;
}
else
{
tsize xend=xstart+2;
while ((xend<xres) && (px[xend]!=px[xend-1])) ++xend;
write_unequal_range (px,xstart,xend,bo);
xstart=xend;
}
}
}
}
}
void LS_Image::write_PPM (const string &file) const
{
ofstream out(file.c_str(), ios_base::out | ios_base::binary);
planck_assert(out, "could not create file '" + file + "'");
tsize xres=pixel.size1(), yres=pixel.size2();
bostream bo(out);
ostringstream header;
header << "P6" << endl << xres << endl << yres << endl << 255 << endl;
string hdrdata = header.str();
bo.put(hdrdata.c_str(),hdrdata.size());
for (tsize j=0; j<yres; ++j)
for (tsize i=0; i<xres; ++i)
bo << pixel[i][j].r << pixel[i][j].g << pixel[i][j].b;
}

192
external/healpix/cxxsupport/ls_image.h vendored Normal file
View file

@ -0,0 +1,192 @@
/*
* This file is part of libcxxsupport.
*
* libcxxsupport is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* libcxxsupport is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with libcxxsupport; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik
* and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
* (DLR).
*/
/*! \file ls_image.h
* Classes for creation and output of image files
*
* Copyright (C) 2003-2010 Max-Planck-Society
* \author Martin Reinecke, David Larson
*/
#ifndef PLANCK_LS_IMAGE_H
#define PLANCK_LS_IMAGE_H
#include <string>
#include <vector>
#include <iostream>
#include <algorithm>
#include "arr.h"
#include "datatypes.h"
/*! \defgroup imagegroup Image creation */
/*! \{ */
/*! A very simple class for storing RGB colours. */
class Colour
{
public:
float r, /*!< the red component */
g, /*!< the green component */
b; /*!< the blue component */
/*! Default constructor. Does not initialize \a r, \a g and \a b. */
Colour() {}
/*! Initializes the colour with \a R, \a G and \a B. */
Colour (float R, float G, float B) : r(R), g(G), b(B) {}
/*! Multiplies all components with \a fact. */
const Colour &operator*= (float fact)
{ r*=fact; g*=fact; b*=fact; return *this; }
/*! Returns the sum colour of \a *this and \a c2. */
const Colour operator+ (const Colour &c2) const
{ return Colour(r+c2.r, g+c2.g, b+c2.b); }
/*! Returns \a *this, scaled by \a f. */
const Colour operator* (double f) const
{ return Colour(float(r*f), float(g*f), float(b*f)); }
};
/*! A class for mapping floting-point values into colours. */
class Palette
{
private:
std::vector<Colour> cv;
std::vector<float> fv;
public:
/*! Adds a new data point \a f, with the corresponding colour \a c.
The additions must be done in the order of ascending \a f. */
void add (float f, const Colour &c)
{
fv.push_back(f);
cv.push_back(c);
}
/*! Sets the palette to the predefined palette \a num. */
void setPredefined(int num);
/*! Returns the colour corresponding to the value \a f. The colour is
determined by linear interpolation between neighbouring data points. */
Colour Get_Colour (float f) const
{
if (f<=fv[0]) return cv[0];
if (f>=fv[fv.size()-1]) return cv[cv.size()-1];
int i=0;
while (f>fv[i]) ++i;
return cv[i-1]*((fv[i]-f)/(fv[i]-fv[i-1]))
+ cv[i]*((f-fv[i-1])/(fv[i]-fv[i-1]));
}
};
class Colour8
{
private:
void import (const Colour &col)
{
using namespace std;
r = uint8(max(0,min(255,int(col.r*256))));
g = uint8(max(0,min(255,int(col.g*256))));
b = uint8(max(0,min(255,int(col.b*256))));
}
public:
uint8 r,g,b;
Colour8() {}
Colour8 (uint8 R, uint8 G, uint8 B)
: r(R), g(G), b(B) {}
Colour8 (const Colour &col)
{ import (col); }
const Colour8 &operator= (const Colour &col)
{ import (col); return *this; }
bool operator== (const Colour8 &that)
{ return (r == that.r) && (g == that.g) && (b == that.b); }
bool operator!= (const Colour8 &that)
{ return (r != that.r) || (g != that.g) || (b != that.b); }
};
class Font
{
public:
int offset, num_chars, xpix, ypix;
const char *data;
};
extern const Font medium_bold_font;
extern const Font giant_font;
/*! Class for creating and storing image files. */
class LS_Image
{
private:
Font font;
arr2<Colour8> pixel;
void write_char (int xpos, int ypos, const Colour &col, char c,
int scale=1);
public:
/*! */
LS_Image ();
/*! Creates an image object with a resolution of \a xres by \a yres. */
LS_Image (int xres, int yres);
/*! */
~LS_Image () {}
/*! Fills the entire image with colour \a col. */
void fill (const Colour &col) { pixel.fill(col); }
/*! Sets the font used for annotations to \a fnt. */
void set_font (const Font &fnt);
/*! Outputs the string \a text in colour \a col.
\a xpos, \a ypos is the lower left corner;
the font is scaled by \a scale. */
void annotate (int xpos, int ypos, const Colour &col,
const std::string &text, int scale=1);
/*! Outputs the string \a text centered at position \a xpos, \a ypos
in colour \a col. The font is scaled by \a scale. */
void annotate_centered (int xpos, int ypos, const Colour &col,
const std::string &text, int scale=1);
/*! Sets the pixel \a i, \a j, to the colour \a col. */
void put_pixel (tsize i, tsize j, const Colour &col)
{
if ((i<pixel.size1()) && (j<pixel.size2()))
pixel[i][j] = col;
}
/*! Returns the colour of the pixel \a i, \a j, or black if the pixel
lies outside of the image. */
Colour8 get_pixel (tsize i, tsize j)
{
return ((i<pixel.size1()) && (j<pixel.size2())) ?
pixel[i][j] : Colour8(0, 0, 0);
}
/*! Writes the image to \a file in uncompressed TGA format. */
void write_TGA (const std::string &file) const;
/*! Writes the image to \a file in run-length encoded TGA format. */
void write_TGA_rle (const std::string &file) const;
/*! Writes the image to \a file in binary PPM format. */
void write_PPM (const std::string &file) const;
};
/*! \} */
#endif

View file

@ -0,0 +1,93 @@
/*
* This file is part of libcxxsupport.
*
* libcxxsupport is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* libcxxsupport is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with libcxxsupport; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik
* and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
* (DLR).
*/
/*! \file lsconstants.h
* Mathematical, physical and technical constants for LevelS.
*/
#ifndef PLANCK_CONSTANTS_H
#define PLANCK_CONSTANTS_H
/*! \defgroup mathconstgroup Mathematical constants */
/*! \{ */
const double pi=3.141592653589793238462643383279502884197;
const double twopi=6.283185307179586476925286766559005768394;
const double inv_twopi=1.0/twopi;
const double fourpi=12.56637061435917295385057353311801153679;
const double halfpi=1.570796326794896619231321691639751442099;
const double inv_halfpi=0.6366197723675813430755350534900574;
const double inv_sqrt4pi = 0.2820947917738781434740397257803862929220;
const double ln2 = 0.6931471805599453094172321214581766;
const double inv_ln2 = 1.4426950408889634073599246810018921;
const double ln10 = 2.3025850929940456840179914546843642;
const double onethird=1.0/3.0;
const double twothird=2.0/3.0;
const double fourthird=4.0/3.0;
const double degr2rad=pi/180.0;
const double arcmin2rad=degr2rad/60;
const double rad2degr=180.0/pi;
//! Ratio between FWHM and sigma of a Gauss curve (\f$\sqrt{8\ln2}\f$).
const double sigma2fwhm=2.3548200450309493; // sqrt(8*log(2.))
const double fwhm2sigma=1/sigma2fwhm;
/*! \} */
/*! \defgroup physconstgroup Physical constants */
/*! \{ */
const double Jansky2SI=1.0e-26;
const double SI2Jansky=1.0e+26;
//! Light speed in m/s (CODATA 2006)
const double speedOfLight=2.99792458e8;
//! Boltzmann's constant in J/K (CODATA 2006)
const double kBoltzmann=1.3806504e-23;
//! Stefan-Boltzmann constant in W/m^2/K^4 (CODATA 2006)
const double sigmaStefanBoltzmann=5.6704e-8;
//! Planck's constant in J s (CODATA 2006)
const double hPlanck=6.62606896e-34;
//! Astronomical unit in m
const double astronomicalUnit=1.49597870691e11;
//! Solar constant in W/m^2
const double solarConstant=1368.0;
//! Average CMB temperature in K (Mather et al. 1999, ApJ 512, 511)
const double tcmb = 2.725;
//! offset (in seconds) between Jan 1, 1958 and Jan 1, 1970
const double sec_58_70 = 378691200.;
/*! \} */
#endif

View file

@ -0,0 +1,89 @@
/*
* This file is part of libcxxsupport.
*
* libcxxsupport is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* libcxxsupport is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with libcxxsupport; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik
* and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
* (DLR).
*/
/*
* Copyright (C) 2005, 2006, 2007, 2009, 2010 Max-Planck-Society
* \author Martin Reinecke
*/
#ifndef PLANCK_OPENMP_SUPPORT_H
#define PLANCK_OPENMP_SUPPORT_H
#ifdef _OPENMP
#include <omp.h>
#endif
#include "cxxutils.h"
inline bool openmp_enabled()
{
#ifdef _OPENMP
return true;
#else
return false;
#endif
}
inline int openmp_max_threads ()
{
#ifdef _OPENMP
return omp_get_max_threads();
#else
return 1;
#endif
}
inline int openmp_num_threads ()
{
#ifdef _OPENMP
return omp_get_num_threads();
#else
return 1;
#endif
}
inline int openmp_thread_num ()
{
#ifdef _OPENMP
return omp_get_thread_num();
#else
return 0;
#endif
}
/*! Calculates the range of indices between \a glo and \a ghi which
must be processed by this thread and returns it in \a lo and \a hi.
The indices \a ghi and \a hi are "one past the last real index",
in analogy to the STL iterators. */
inline void openmp_calc_share (int64 glo, int64 ghi, int64 &lo, int64 &hi)
{
#ifdef _OPENMP
calcShareGeneral (glo,ghi,omp_get_num_threads(),omp_get_thread_num(),lo,hi);
#else
lo=glo; hi=ghi;
#endif
}
#endif

116
external/healpix/cxxsupport/paramfile.h vendored Normal file
View file

@ -0,0 +1,116 @@
/*
* This file is part of libcxxsupport.
*
* libcxxsupport is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* libcxxsupport is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with libcxxsupport; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik
* and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
* (DLR).
*/
/*
* Class for parsing parameter files
*
* Copyright (C) 2003, 2004, 2005, 2008, 2009, 2010 Max-Planck-Society
* Authors: Martin Reinecke, Reinhard Hell
*/
#ifndef PLANCK_PARAMFILE_H
#define PLANCK_PARAMFILE_H
#include <map>
#include <set>
#include <string>
#include <iostream>
#include "cxxutils.h"
class paramfile
{
private:
typedef std::map<std::string,std::string> params_type;
params_type params;
mutable std::set<std::string> read_params;
bool verbose;
std::string get_valstr(const std::string &key) const
{
params_type::const_iterator loc=params.find(key);
if (loc!=params.end()) return loc->second;
planck_fail ("Cannot find the key '" + key + "'.");
}
bool param_unread (const std::string &key) const
{ return (read_params.find(key)==read_params.end()); }
public:
paramfile (const std::string &filename, bool verbose_=true)
: verbose(verbose_)
{ parse_file (filename, params); }
paramfile (const params_type &par, bool verbose_=true)
: params (par), verbose(verbose_)
{}
~paramfile ()
{
if (verbose)
for (params_type::const_iterator loc=params.begin();
loc!=params.end(); ++loc)
if (param_unread(loc->first))
std::cout << "Parser warning: unused parameter '"
<< loc->first << "'" << std::endl;
}
void setVerbosity (bool verbose_)
{ verbose = verbose_; }
bool getVerbosity () const
{ return verbose; }
bool param_present(const std::string &key) const
{ return (params.find(key)!=params.end()); }
template<typename T> T find (const std::string &key) const
{
T result;
stringToData(get_valstr(key),result);
std::string output = dataToString(result);
if (planckType<T>()==PLANCK_STRING) output = "'"+output+"'";
if (verbose && param_unread(key))
std::cout << "Parser: " << key << " = " << output << std::endl;
read_params.insert(key);
return result;
}
template<typename T> T find
(const std::string &key, const T &deflt)
{
if (param_present(key)) return find<T>(key);
std::string output = dataToString(deflt);
if (planckType<T>()==PLANCK_STRING) output = "'"+output+"'";
if (verbose && param_unread(key))
std::cout << "Parser: " << key << " = " << output
<< " <default>" << std::endl;
params[key]=dataToString(deflt);
read_params.insert(key);
return deflt;
}
const params_type &getParams() const
{ return params; }
};
#endif

22
external/healpix/cxxsupport/planck.make vendored Normal file
View file

@ -0,0 +1,22 @@
PKG:=cxxsupport
SD:=$(SRCROOT)/$(PKG)
OD:=$(BLDROOT)/$(PKG)
FULL_INCLUDE+= -I$(SD)
HDR_$(PKG):=$(SD)/*.h
LIB_$(PKG):=$(LIBDIR)/libcxxsupport.a
OBJ:=cxxutils.o fitshandle.o rotmatrix.o trafos.o ls_image.o error_handling.o wigner.o
OBJ:=$(OBJ:%=$(OD)/%)
ODEP:=$(HDR_$(PKG)) $(HDR_libfftpack) $(HDR_c_utils)
$(OBJ): $(ODEP) | $(OD)_mkdir
$(LIB_$(PKG)): $(OBJ)
$(OD)/fitshandle.o: $(HDR_libcfitsio)
$(OD)/ls_image.o: $(SD)/font_data.inc
all_hdr+=$(HDR_$(PKG))
all_lib+=$(LIB_$(PKG))

154
external/healpix/cxxsupport/planck_rng.h vendored Normal file
View file

@ -0,0 +1,154 @@
/*
* This file is part of libcxxsupport.
*
* libcxxsupport is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* libcxxsupport is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with libcxxsupport; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik
* and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
* (DLR).
*/
/*! \file planck_rng.h
* This file contains the random number generator
* used by the Planck LevelS package.
* The generator is a C++ port of the xorshift generator xor128() described
* in Marsaglia, Journal of Statistical Software 2003, vol 8.
* It has a period of 2^128 - 1.
*
* Copyright (C) 2003, 2004, 2005 Max-Planck-Society
* \author Martin Reinecke
*/
#ifndef PLANCK_RNG_H
#define PLANCK_RNG_H
#include <cmath>
#include "error_handling.h"
/*! C++ port of the xorshift generator xor128() described in Marsaglia,
Journal of Statistical Software 2003, vol 8.
It has a period of 2^128 - 1. */
class planck_rng
{
private:
unsigned int x,y,z,w;
double small, gset;
bool empty;
void twiddle (unsigned int &v)
{
for (int i=0; i<9; ++i)
{
v ^= v<<13;
v ^= v>>17;
v ^= v<<5;
}
}
void init_rng ()
{
// avoid zero seeds
if (x==0) x = 123456789;
if (y==0) y = 362436069;
if (z==0) z = 521288629;
if (w==0) w = 88675123;
// shuffle the bits of the seeds
twiddle(x); twiddle(y); twiddle(z); twiddle(w);
// burn in the RNG
for (int i=0; i<16; ++i)
int_rand_uni();
}
public:
/*! Initializes the generator with 0 to 4 seed values. */
planck_rng (unsigned int x1=123456789, unsigned int y1=362436069,
unsigned int z1=521288629, unsigned int w1=88675123)
: x(x1), y(y1), z(z1), w(w1),
small(1./(1.+double(0xFFFFFFFF))), gset(0.), empty(true)
{
planck_assert (sizeof(unsigned int)==4, "wrong integer size for RNG");
init_rng();
}
/*! Re-initializes the generator with 0 to 4 seed values. */
void seed (unsigned int x1=123456789, unsigned int y1=362436069,
unsigned int z1=521288629, unsigned int w1=88675123)
{
x = x1; y = y1; z = z1; w = w1;
empty = true;
init_rng();
}
/*! Returns uniformly distributed random integer numbers from the
interval [0;0xFFFFFFFF]. */
unsigned int int_rand_uni()
{
unsigned int t = x^(x<<11);
x = y;
y = z;
z = w;
return w=(w^(w>>19))^(t^(t>>8));
}
//! Returns uniformly distributed random numbers from the interval [0;1[.
double rand_uni()
{
return small*int_rand_uni();
}
//! Returns random numbers with Gaussian distribution (mean=0, sigma=1).
/*! Uses rand_uni() internally. */
double rand_gauss()
{
using namespace std;
if (empty)
{
double v1,v2,rsq;
do
{
v1=2*rand_uni()-1.;
v2=2*rand_uni()-1.;
rsq=v1*v1+v2*v2;
}
while ((rsq>=1) || (rsq==0));
double fac=sqrt(-2*log(rsq)/rsq);
gset=v1*fac;
empty=false;
return v2*fac;
}
else
{
empty=true;
return gset;
}
}
//! Returns exponentially distributed random numbers (mean=1, nonnegative)
/*! Uses rand_uni() internally. */
double rand_exp()
{
using namespace std;
double val=rand_uni();
if (val==0.) val=1.;
return -log(val);
}
};
#endif

106
external/healpix/cxxsupport/pointing.h vendored Normal file
View file

@ -0,0 +1,106 @@
/*
* This file is part of libcxxsupport.
*
* libcxxsupport is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* libcxxsupport is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with libcxxsupport; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik
* and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
* (DLR).
*/
/*! \file pointing.h
* Class representing a direction in 3D space
*
* Copyright (C) 2003-2010 Max-Planck-Society
* \author Martin Reinecke
*/
#ifndef PLANCK_POINTING_H
#define PLANCK_POINTING_H
#include <cmath>
#include "vec3.h"
#include "cxxutils.h"
/*! \defgroup pointinggroup Pointings */
/*! \{ */
/*! Class representing a direction in 3D space or a location on the
unit sphere. All angles in radians. */
class pointing
{
public:
/*! Colatitude of the pointing (i.e. the North pole is at \a theta=0). */
double theta;
/*! Longitude of the pointing. */
double phi;
/*! Default constructor. \a theta and \a phi are not initialized. */
pointing() {}
/*! Creates a pointing with \a Theta and \a Phi. */
pointing (double Theta, double Phi) : theta(Theta), phi(Phi) {}
// FIXME: should become "explicit" some time
/*! Creates a pointing from the vector \a inp. \a inp need not be
normalized. */
pointing (const vec3 &inp)
{ from_vec3(inp); }
// FIXME: should be removed some time
/*! Returns a normalized vector pointing in the same direction. */
operator vec3() const
{ return to_vec3(); }
/*! Returns a normalized vector pointing in the same direction. */
vec3 to_vec3() const
{
double st=sin(theta);
return vec3 (st*cos(phi), st*sin(phi), cos(theta));
}
/*! Converts \a inp to \a ptg. \a inp need not be normalized. */
void from_vec3 (const vec3 &inp)
{
using namespace std;
const double twopi_=6.283185307179586476925286766559005768394;
theta = atan2(sqrt(inp.x*inp.x+inp.y*inp.y),inp.z);
phi = safe_atan2 (inp.y,inp.x);
if (phi<0.) phi += twopi_;
}
/*! Changes the angles so that \a 0<=theta<=pi and \a 0<=phi<2*pi. */
void normalize()
{
const double pi_=3.141592653589793238462643383279502884197;
const double twopi_=6.283185307179586476925286766559005768394;
theta=fmodulo(theta,twopi_);
if (theta>pi_)
{
phi+=pi_;
theta=twopi_-theta;
}
phi=fmodulo(phi,twopi_);
}
};
/*! Writes \a p to \a os.
\relates pointing */
inline std::ostream &operator<< (std::ostream &os, const pointing &p)
{
os << p.theta << ", " << p.phi << std::endl;
return os;
}
/*! \} */
#endif

177
external/healpix/cxxsupport/rotmatrix.cc vendored Normal file
View file

@ -0,0 +1,177 @@
/*
* This file is part of libcxxsupport.
*
* libcxxsupport is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* libcxxsupport is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with libcxxsupport; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik
* and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
* (DLR).
*/
/*
* Class for rotation transforms in 3D space
*
* Copyright (C) 2003 Max-Planck-Society
* Author: Martin Reinecke
*/
#include "rotmatrix.h"
#include "vec3.h"
#include "lsconstants.h"
#include <algorithm>
using namespace std;
rotmatrix::rotmatrix (const vec3 &a, const vec3 &b, const vec3 &c)
{
entry[0][0]=a.x; entry[0][1]=b.x; entry[0][2]=c.x;
entry[1][0]=a.y; entry[1][1]=b.y; entry[1][2]=c.y;
entry[2][0]=a.z; entry[2][1]=b.z; entry[2][2]=c.z;
}
void rotmatrix::SetToIdentity ()
{
entry[0][0] = entry[1][1] = entry[2][2] = 1.;
entry[0][1] = entry[1][0] = entry[0][2] =
entry[2][0] = entry[1][2] = entry[2][1] = 0.;
}
void rotmatrix::SetToZero ()
{
for (int m=0; m<3; ++m)
entry[m][0] = entry[m][1] = entry[m][2] = 0;
}
void rotmatrix::Transpose ()
{
swap(entry[0][1], entry[1][0]);
swap(entry[0][2], entry[2][0]);
swap(entry[1][2], entry[2][1]);
}
void rotmatrix::toAxisAngle (vec3 &axis, double &angle) const
{
double c2 = entry[0][0] + entry[1][1] + entry[2][2] - 1;
axis.x = entry[2][1] - entry[1][2];
axis.y = entry[0][2] - entry[2][0];
axis.z = entry[1][0] - entry[0][1];
double s2 = axis.Length();
if (s2>0)
{
angle = atan2(s2,c2);
axis *= 1/s2;
return;
}
if (c2>=2) // angle is 0
{
axis = vec3(1,0,0);
angle = 0;
return;
}
angle = pi;
int choice = 0; // assume entry[0][0] is the largest
if ((entry[1][1]>entry[0][0]) && (entry[1][1]>entry[2][2])) choice=1;
if ((entry[2][2]>entry[0][0]) && (entry[2][2]>entry[1][1])) choice=2;
if (choice==0)
{
axis.x = 0.5*sqrt(entry[0][0]-entry[1][1]-entry[2][2]+1);
double half_inv = 0.5/axis.x;
axis.y = half_inv*entry[0][1];
axis.z = half_inv*entry[0][2];
return;
}
if (choice==1)
{
axis.y = 0.5*sqrt(entry[1][1]-entry[0][0]-entry[2][2]+1);
double half_inv = 0.5/axis.y;
axis.x = half_inv*entry[0][1];
axis.z = half_inv*entry[1][2];
return;
}
axis.z = 0.5*sqrt(entry[2][2]-entry[0][0]-entry[1][1]+1);
double half_inv = 0.5/axis.z;
axis.x = half_inv*entry[0][2];
axis.y = half_inv*entry[1][2];
}
void rotmatrix::Make_CPAC_Euler_Matrix
(double alpha, double beta, double gamma)
{
double ca=cos(alpha), cb=cos(beta), cg=cos(gamma);
double sa=sin(alpha), sb=sin(beta), sg=sin(gamma);
entry[0][0]= ca*cb*cg-sa*sg; entry[0][1]=-ca*cb*sg-sa*cg; entry[0][2]= ca*sb;
entry[1][0]= sa*cb*cg+ca*sg; entry[1][1]=-sa*cb*sg+ca*cg; entry[1][2]= sa*sb;
entry[2][0]=-sb*cg; entry[2][1]= sb*sg; entry[2][2]= cb;
}
void rotmatrix::Extract_CPAC_Euler_Angles
(double &alpha, double &beta, double &gamma) const
{
double cb = entry[2][2];
double sb = sqrt(entry[0][2]*entry[0][2] + entry[1][2]*entry[1][2]);
beta=atan2(sb,cb);
if (abs(sb)<=1e-6)
{
alpha=0;
if (cb>0)
gamma=atan2(entry[1][0],entry[0][0]);
else
gamma=atan2(entry[0][1],-entry[0][0]);
}
else
{
alpha=atan2(entry[1][2],entry[0][2]);
gamma=atan2(entry[2][1],-entry[2][0]);
}
}
rotmatrix operator* (const rotmatrix &a, const rotmatrix &b)
{
rotmatrix res;
for (int i=0; i<3; ++i)
for (int j=0; j<3; ++j)
res.entry[i][j] = a.entry[i][0] * b.entry[0][j]
+ a.entry[i][1] * b.entry[1][j]
+ a.entry[i][2] * b.entry[2][j];
return res;
}
void TransposeTimes (const rotmatrix &a, const rotmatrix &b, rotmatrix &res)
{
for (int i=0; i<3; ++i)
for (int j=0; j<3; ++j)
res.entry[i][j] = a.entry[0][i] * b.entry[0][j]
+ a.entry[1][i] * b.entry[1][j]
+ a.entry[2][i] * b.entry[2][j];
}
ostream &operator<< (ostream &os, const rotmatrix &mat)
{
for (int i=0;i<3;++i)
os << mat.entry[i][0] << ' '
<< mat.entry[i][1] << ' '
<< mat.entry[i][2] << endl;
return os;
}

158
external/healpix/cxxsupport/rotmatrix.h vendored Normal file
View file

@ -0,0 +1,158 @@
/*
* This file is part of libcxxsupport.
*
* libcxxsupport is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* libcxxsupport is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with libcxxsupport; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik
* and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
* (DLR).
*/
/*! \file rotmatrix.h
* Class for rotation transforms in 3D space
*
* Copyright (C) 2003 Max-Planck-Society
* \author Martin Reinecke
*/
#ifndef PLANCK_ROTMATRIX_H
#define PLANCK_ROTMATRIX_H
#include <iostream>
#include "cxxutils.h"
#include "vec3.h"
/*! \defgroup rotmatrixgroup Rotation matrices */
/*! \{ */
/*! Class for rotation transforms in 3D space */
class rotmatrix
{
public:
double entry[3][3];
rotmatrix () {}
/*! Constructs a rotation matrix from its nine entries */
rotmatrix (double a00, double a01, double a02,
double a10, double a11, double a12,
double a20, double a21, double a22)
{
entry[0][0]=a00; entry[0][1]=a01; entry[0][2]=a02;
entry[1][0]=a10; entry[1][1]=a11; entry[1][2]=a12;
entry[2][0]=a20; entry[2][1]=a21; entry[2][2]=a22;
}
/*! Constructs a rotation matrix so that \a a is the first column,
\a b is the second column and \a c is the third column.
\note The vectors \a a, \a b and \a c must form an orthonormal system!
*/
rotmatrix (const vec3 &a, const vec3 &b, const vec3 &c);
/*! Sets the matrix to the identity matrix. */
void SetToIdentity ();
/*! Sets all matrix elements to zero. */
void SetToZero ();
/*! Transposes the matrix. */
void Transpose ();
/*! Extracts a unit-length rotation axis \a axis and a rotation angle
\a angle from the matrix. */
void toAxisAngle (vec3 &axis, double &angle) const;
/*! Constructs a matrix which causes a rotation by \a angle around
\a axis. \a axis must have unit length. */
void Make_Axis_Rotation_Transform (const vec3 &axis, double angle)
{
double sa=sin(angle), ca=cos(angle);
double ica=1-ca;
entry[0][0] = axis.x*axis.x*ica + ca;
entry[1][1] = axis.y*axis.y*ica + ca;
entry[2][2] = axis.z*axis.z*ica + ca;
double t1 = axis.x*axis.y*ica, t2 = axis.z*sa;
entry[1][0] = t1 + t2;
entry[0][1] = t1 - t2;
t1 = axis.x*axis.z*ica; t2 = axis.y*sa;
entry[2][0] = t1 - t2;
entry[0][2] = t1 + t2;
t1 = axis.y*axis.z*ica; t2 = axis.x*sa;
entry[1][2] = t1 - t2;
entry[2][1] = t1 + t2;
}
/*! Creates a rotation matrix \a A, which performs the following operations
on a vector \a v, when \a Av is calculated:
-# rotate \a v around the z-axis by \a gamma,
-# rotate \a v' around the y-axis by \a beta,
-# rotate \a v'' around the z-axis by \a alpha.
\note \a alpha, \a beta and \a gamma are given in radians,
the rotations are right handed.
\note This transformation rotates the \e vectors, not the coordinate
axes! */
void Make_CPAC_Euler_Matrix (double alpha, double beta, double gamma);
/*! Extracts the Euler angles \a alpha, \a beta and \a gamma from the
matrix. For their definition see Make_CPAC_Euler_Matrix().
\note In case of ambiguity \a alpha will be 0. */
void Extract_CPAC_Euler_Angles
(double &alpha, double &beta, double &gamma) const;
/*! Returns the vector \a vec, transformed by the matrix. */
vec3 Transform (const vec3 &vec) const
{
return vec3
(vec.x*entry[0][0] + vec.y*entry[0][1] + vec.z*entry[0][2],
vec.x*entry[1][0] + vec.y*entry[1][1] + vec.z*entry[1][2],
vec.x*entry[2][0] + vec.y*entry[2][1] + vec.z*entry[2][2]);
}
/*! Returns the vector \a vec, transformed by the matrix, in \a vec2. */
void Transform (const vec3 &vec, vec3 &vec2) const
{
vec2.x = vec.x*entry[0][0] + vec.y*entry[0][1] + vec.z*entry[0][2];
vec2.y = vec.x*entry[1][0] + vec.y*entry[1][1] + vec.z*entry[1][2];
vec2.z = vec.x*entry[2][0] + vec.y*entry[2][1] + vec.z*entry[2][2];
}
};
/*! Returns \a a * \a b.
\relates rotmatrix */
rotmatrix operator* (const rotmatrix &a, const rotmatrix &b);
/*! Returns \a a * \a b in \a res.
\relates rotmatrix */
inline void matmult (const rotmatrix &a, const rotmatrix &b, rotmatrix &res)
{
for (int i=0; i<3; ++i)
for (int j=0; j<3; ++j)
res.entry[i][j] = a.entry[i][0] * b.entry[0][j]
+ a.entry[i][1] * b.entry[1][j]
+ a.entry[i][2] * b.entry[2][j];
}
/*! Returns \a a^T * \a b in \a res.
\relates rotmatrix */
void TransposeTimes (const rotmatrix &a, const rotmatrix &b, rotmatrix &res);
/*! Writes \a mat to \a os.
\relates rotmatrix */
std::ostream &operator<< (std::ostream &os, const rotmatrix &mat);
/*! \} */
#endif

92
external/healpix/cxxsupport/safe_cast.h vendored Normal file
View file

@ -0,0 +1,92 @@
/*
* This file is part of libcxxsupport.
*
* libcxxsupport is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* libcxxsupport is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with libcxxsupport; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik
* and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
* (DLR).
*/
/*! \file safe_cast.h
* Numerical cast operator with additional checks that the value is preserved.
*
* Copyright (C) 2009 Max-Planck-Society
* Author: Martin Reinecke
*/
#ifndef PLANCK_SAFE_CAST_H
#define PLANCK_SAFE_CAST_H
#include <limits>
#include "error_handling.h"
template<typename T1, typename T2, bool s1, bool s2> struct safe_cast_helper__
{};
template<typename T1, typename T2> struct safe_cast_helper__ <T1,T2,true,true>
{
static T1 cast (const T2 &arg)
{
T1 res = T1(arg);
planck_assert(T2(res)==arg, "safe_cast: value changed during cast");
return res;
}
};
template<typename T1, typename T2> struct safe_cast_helper__ <T1,T2,false,false>
{
static T1 cast (const T2 &arg)
{
T1 res = T1(arg);
planck_assert(T2(res)==arg, "safe_cast: value changed during cast");
return res;
}
};
template<typename T1, typename T2> struct safe_cast_helper__ <T1,T2,true,false>
{
static T1 cast (const T2 &arg)
{
T1 res = T1(arg);
planck_assert((res>=0) && (T2(res)==arg),
"safe_cast: value changed during cast");
return res;
}
};
template<typename T1, typename T2> struct safe_cast_helper__ <T1,T2,false,true>
{
static T1 cast (const T2 &arg)
{
T1 res = T1(arg);
planck_assert((arg>=0) && (T2(res)==arg),
"safe_cast: value changed during cast");
return res;
}
};
/*! Tries to cast \a arg from its type to a variable of type \c T1.
If this conversion leads to a change of the actual value (e.g. due to
overflow or truncation), an exception is thrown. */
template<typename T1, typename T2> inline T1 safe_cast(const T2 &arg)
{
return safe_cast_helper__<T1,T2,std::numeric_limits<T1>::is_signed,
std::numeric_limits<T2>::is_signed>::cast(arg);
}
#endif

158
external/healpix/cxxsupport/trafos.cc vendored Normal file
View file

@ -0,0 +1,158 @@
/*
* This file is part of libcxxsupport.
*
* libcxxsupport is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* libcxxsupport is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with libcxxsupport; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik
* and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
* (DLR).
*/
/*! \file trafos.cc
* Celestial coordinate transformations.
*
* Copyright (C) 2005 Max-Planck-Society
* \author Martin Reinecke
*/
#include "trafos.h"
#include "lsconstants.h"
using namespace std;
vec3 Trafo::xcc_dp_precess (const vec3 &iv, double iepoch,
double oepoch)
{
// Z-axis rotation by OBL_LONG:
double Tm = ((oepoch+iepoch)*0.5 - 1900.) *0.01;
double gp_long = degr2rad * ((oepoch-iepoch) * (50.2564+0.0222*Tm) / 3600.);
double obl_long =
degr2rad * (180. - (173. + (57.06+54.77*Tm) / 60.)) + gp_long*0.5;
double dco = cos(obl_long), dso = sin(obl_long);
vec3 ov (iv.x*dco-iv.y*dso, iv.x*dso+iv.y*dco, iv.z);
// X-axis rotation by dE:
double dE = degr2rad * ((oepoch-iepoch) * (0.4711-0.0007*Tm) / 3600.);
double dce = cos(dE), dse = sin(dE);
double temp = ov.y*dce - ov.z*dse;
ov.z = ov.y*dse + ov.z*dce;
ov.y = temp;
// Z-axis rotation by GP_LONG - OBL_LONG:
double dL = gp_long - obl_long;
double dcl = cos(dL), dsl = sin(dL);
temp = ov.x*dcl - ov.y*dsl;
ov.y = ov.x*dsl + ov.y*dcl;
ov.x = temp;
return ov;
}
double Trafo::get_epsilon (double epoch)
{
double T = (epoch - 1900.) * 0.01;
return
degr2rad * (23.452294 - 0.0130125*T - 1.63889e-6*T*T + 5.02778e-7*T*T*T);
}
/*! Routine to convert from ecliptic coordinates to equatorial (celestial)
coordinates at the given epoch. Adapted from the COBLIB routine by Dr.
E. Wright. */
vec3 Trafo::xcc_dp_e_to_q (const vec3 &iv, double epoch)
{
double epsilon=get_epsilon(epoch);
double dc = cos(epsilon), ds = sin(epsilon);
return vec3 (iv.x, dc*iv.y-ds*iv.z, dc*iv.z+ds*iv.y);
}
vec3 Trafo::xcc_dp_q_to_e (const vec3 &iv, double epoch)
{
double epsilon=-get_epsilon(epoch);
double dc = cos(epsilon), ds = sin(epsilon);
return vec3 (iv.x, dc*iv.y-ds*iv.z, dc*iv.z+ds*iv.y);
}
/*! Routine to convert galactic coordinates to ecliptic (celestial)
coordinates at the given epoch. First the conversion to ecliptic
2000 is done, then if necessary the results are precessed. */
vec3 Trafo::xcc_dp_g_to_e (const vec3 &iv, double epoch)
{
static const rotmatrix T (-0.054882486, 0.494116468, -0.867661702,
-0.993821033, -0.110993846, -0.000346354,
-0.096476249, 0.862281440, 0.497154957);
vec3 hv=T.Transform(iv);
if (!approx(epoch,2000.))
hv=xcc_dp_precess(hv,2000.,epoch);
return hv;
}
/*! Routine to convert ecliptic (celestial) coordinates at the given
epoch to galactic coordinates. The ecliptic coordinates are first
precessed to 2000.0, then converted. */
vec3 Trafo::xcc_dp_e_to_g (const vec3 &iv, double epoch)
{
static const rotmatrix T (-0.054882486, -0.993821033, -0.096476249,
0.494116468, -0.110993846, 0.862281440,
-0.867661702, -0.000346354, 0.497154957);
vec3 hv=iv;
if (!approx(epoch,2000.))
hv=xcc_dp_precess(hv,epoch,2000.);
return T.Transform(hv);
}
/*! Function to convert between standard coordinate systems, including
precession. */
vec3 Trafo::xcc_v_convert(const vec3 &iv, double iepoch, double oepoch,
coordsys isys,coordsys osys)
{
vec3 xv;
if (isys == Ecliptic)
xv=iv;
else if (isys == Equatorial)
xv = xcc_dp_q_to_e(iv,iepoch);
else if (isys == Galactic)
xv = xcc_dp_g_to_e(iv,iepoch);
else
planck_fail("Unsupported input coordinate system");
vec3 yv = approx(iepoch,oepoch) ? xv : xcc_dp_precess(xv,iepoch,oepoch);
vec3 ov;
if (osys == Ecliptic)
ov = yv;
else if (osys == Equatorial)
ov = xcc_dp_e_to_q(yv,oepoch);
else if (osys == Galactic)
ov = xcc_dp_e_to_g(yv,oepoch);
else
planck_fail("Unsupported output coordinate system");
return ov;
}
void Trafo::coordsys2matrix (double iepoch, double oepoch,
coordsys isys, coordsys osys, rotmatrix &matrix)
{
vec3 v1p = xcc_v_convert(vec3(1,0,0),iepoch,oepoch,isys,osys),
v2p = xcc_v_convert(vec3(0,1,0),iepoch,oepoch,isys,osys),
v3p = xcc_v_convert(vec3(0,0,1),iepoch,oepoch,isys,osys);
v1p.Normalize(); v2p.Normalize(); v3p.Normalize();
matrix=rotmatrix(v1p,v2p,v3p);
}

103
external/healpix/cxxsupport/trafos.h vendored Normal file
View file

@ -0,0 +1,103 @@
/*
* This file is part of libcxxsupport.
*
* libcxxsupport is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* libcxxsupport is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with libcxxsupport; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik
* and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
* (DLR).
*/
/*! \file trafos.h
* Celestial coordinate transformations.
*
* Copyright (C) 2005 Max-Planck-Society
* \author Martin Reinecke
*/
#ifndef PLANCK_TRAFOS_H
#define PLANCK_TRAFOS_H
#include "vec3.h"
#include "pointing.h"
#include "rotmatrix.h"
#include "cxxutils.h"
#include "geom_utils.h"
enum coordsys { Ecliptic, Equatorial, Galactic };
/*! Class for celestial coordinate transformations. */
class Trafo
{
private:
rotmatrix mat;
static vec3 xcc_dp_precess (const vec3 &iv, double iepoch, double oepoch);
static double get_epsilon (double epoch);
static vec3 xcc_dp_e_to_q (const vec3 &iv, double epoch);
static vec3 xcc_dp_q_to_e (const vec3 &iv, double epoch);
static vec3 xcc_dp_g_to_e (const vec3 &iv, double epoch);
static vec3 xcc_dp_e_to_g (const vec3 &iv, double epoch);
static vec3 xcc_v_convert(const vec3 &iv, double iepoch, double oepoch,
coordsys isys,coordsys osys);
static void coordsys2matrix (double iepoch, double oepoch, coordsys isys,
coordsys osys, rotmatrix &matrix);
public:
/*! Creates a \a Trafo for transformation from \a iepoch and \a isys
to \a oepoch and \a osys. */
Trafo (double iepoch, double oepoch, coordsys isys, coordsys osys)
{ coordsys2matrix (iepoch, oepoch, isys, osys, mat); }
/*! Transforms the vector \a vec and returns the result. */
vec3 operator() (const vec3 &vec) const
{ return mat.Transform(vec); }
/*! Transforms the pointing \a ptg and returns the result. */
pointing operator() (const pointing &ptg) const
{ return pointing(operator()(vec3(ptg))); }
/*! Transforms the pointing \a ptg and returns it in \a newptg.
On exit, \a delta_psi holds the change in orientation. */
void rotatefull (const pointing &ptg, pointing &newptg,
double &delta_psi) const
{
const double halfpi_=1.570796326794896619231321691639751442099;
vec3 vec (ptg);
vec3 east (-vec.y,vec.x,0.);
vec3 newvec = operator()(vec);
vec3 neweast = operator()(east);
delta_psi = orientation(newvec,neweast)+halfpi_;
newptg = newvec;
}
/*! Transforms the vector \a vec and returns it in \a newvec.
On exit, \a delta_psi holds the change in orientation. */
void rotatefull (const vec3 &vec, vec3 &newvec, double &delta_psi) const
{
const double halfpi_=1.570796326794896619231321691639751442099;
vec3 east (-vec.y,vec.x,0.);
newvec = operator()(vec);
vec3 neweast = operator()(east);
delta_psi = orientation(newvec,neweast)+halfpi_;
}
/*! Returns the internally used rotation matrix. */
const rotmatrix &Matrix() const
{ return mat; }
};
#endif

149
external/healpix/cxxsupport/vec3.h vendored Normal file
View file

@ -0,0 +1,149 @@
/*
* This file is part of libcxxsupport.
*
* libcxxsupport is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* libcxxsupport is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with libcxxsupport; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik
* and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
* (DLR).
*/
/*! \file vec3.h
* Class representing 3D cartesian vectors
*
* Copyright (C) 2003, 2006 Max-Planck-Society
* \author Martin Reinecke
*/
#ifndef PLANCK_VEC3_H
#define PLANCK_VEC3_H
#include <cmath>
#include <iostream>
#include "datatypes.h"
/*! \defgroup vec3group 3D vectors */
/*! \{ */
/*! Class representing a 3D cartesian vector. */
template<typename T>class vec3_t
{
public:
T x, /*!< x-coordinate */
y, /*!< y-coordinate */
z; /*!< z-coordinate */
/*! Default constructor. Does not initialize \a x, \a y, and \a z. */
vec3_t () {}
/*! Creates a vector with the coordinates \a xc, \a yc, and \a zc. */
vec3_t (T xc, T yc, T zc)
: x(xc), y(yc), z(zc) {}
template<typename T2> explicit vec3_t (const vec3_t<T2> &orig)
: x(orig.x), y(orig.y), z(orig.z) {}
/*! Sets the vector components to \a xc, \a yc, and \a zc. */
void Set (T xc, T yc, T zc)
{ x=xc; y=yc; z=zc; }
/*! Creates a unit vector from a z coordinate and an azimuthal angle. */
void set_z_phi (T z_, T phi)
{
using namespace std;
T sintheta = sqrt((T(1)-z_)*(T(1)+z_));
x = sintheta*cos(phi);
y = sintheta*sin(phi);
z = z_;
}
/*! Normalizes the vector to length 1. */
void Normalize ()
{
using namespace std;
T l = T(1)/sqrt (x*x + y*y + z*z);
x*=l; y*=l; z*=l;
}
vec3_t Norm() const
{
vec3_t res(*this);
res.Normalize();
return res;
}
/*! Returns the length of the vector. */
T Length () const
{ return sqrt (x*x + y*y + z*z); }
/*! Returns the squared length of the vector. */
T SquaredLength () const
{ return (x*x + y*y + z*z); }
/*! Returns the vector with the signs of all coordinates flipped. */
const vec3_t operator- () const
{ return vec3_t (-x, -y, -z); }
/*! Flips the signs of all coordinates. */
void Flip ()
{ x=-x; y=-y; z=-z; }
/*! Returns (\a *this + \a vec). */
const vec3_t operator+ (const vec3_t &vec) const
{ return vec3_t (x+vec.x, y+vec.y, z+vec.z); }
/*! Adds \a vec to \a *this. */
vec3_t &operator+= (const vec3_t &vec)
{ x+=vec.x; y+=vec.y; z+=vec.z; return *this; }
/*! Returns (\a *this - \a vec). */
const vec3_t operator- (const vec3_t &vec) const
{ return vec3_t (x-vec.x, y-vec.y, z-vec.z); }
/*! Subtracts \a vec from \a *this. */
vec3_t &operator-= (const vec3_t &vec)
{ x-=vec.x; y-=vec.y; z-=vec.z; return *this; }
/*! Returns the vector scaled by \a fact. */
const vec3_t operator* (T fact) const
{ return vec3_t (x*fact, y*fact, z*fact); }
/*! Returns the vector scaled by \a 1/fact. */
const vec3_t operator/ (T fact) const
{ T xfact = T(1)/fact; return vec3_t (x*xfact, y*xfact, z*xfact); }
/*! Scales the vector by \a fact. */
vec3_t &operator*= (T fact)
{ x*=fact; y*=fact; z*=fact; return *this; }
};
/*! Returns the dot product of \a v1 and \a v2.
\relates vec3_t */
template<typename T> inline T dotprod(const vec3_t<T> &v1, const vec3_t<T> &v2)
{ return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z; }
/*! Returns the cross product of \a a and \a b.
\relates vec3_t */
template<typename T> inline vec3_t<T> crossprod
(const vec3_t<T> &a, const vec3_t<T> &b)
{ return vec3_t<T>(a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x); }
/*! Writes \a v to \a os.
\relates vec3_t */
template<typename T> inline std::ostream &operator<<
(std::ostream &os, const vec3_t<T> &v)
{
os << v.x << ", " << v.y << ", " << v.z << std::endl;
return os;
}
/*! Specialisation of vec3_t for 64-bit floating point components */
typedef vec3_t<float64> vec3;
/*! Specialisation of vec3_t for 32-bit floating point components */
typedef vec3_t<float32> vec3f;
/*! \} */
#endif

583
external/healpix/cxxsupport/wigner.cc vendored Normal file
View file

@ -0,0 +1,583 @@
/*
* This file is part of libcxxsupport.
*
* libcxxsupport is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* libcxxsupport is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with libcxxsupport; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik
* and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
* (DLR).
*/
/*! \file wigner.cc
* Several C++ classes for calculating Wigner matrices
*
* Copyright (C) 2009,2010 Max-Planck-Society
* \author Martin Reinecke and others (see individual classes)
*/
#include "wigner.h"
#include "lsconstants.h"
using namespace std;
void wigner_d_halfpi_risbo_scalar::do_line0 (double *l1, int j)
{
double xj = pq/j;
for (int i=n; i>=1; --i)
l1[i] = xj*sqt[j]*(sqt[j-i]*l1[i] - sqt[i]*l1[i-1]);
l1[0] = pq*l1[0];
}
void wigner_d_halfpi_risbo_scalar::do_line (const double *l1, double *l2,
int j, int k)
{
double xj = pq/j;
double t1 = xj*sqt[j-k];
double t2 = xj*sqt[k];
for (int i=n; i>=1; --i)
l2[i] = t1 * (sqt[j-i]*l2[i] - sqt[i]*l2[i-1])
+t2 * (sqt[j-i]*l1[i] + sqt[i]*l1[i-1]);
l2[0] = sqt[j] * (t2*l1[0]+t1*l2[0]);
}
wigner_d_halfpi_risbo_scalar::wigner_d_halfpi_risbo_scalar(int lmax)
: pq(.5*sqrt(2.)), sqt(2*lmax+1), d(lmax+2,lmax+2), n(-1)
{ for (tsize m=0; m<sqt.size(); ++m) sqt[m] = sqrt(double(m)); }
const arr2<double> &wigner_d_halfpi_risbo_scalar::recurse ()
{
++n;
if (n==0)
d[0][0] = 1;
else if (n==1)
{
d[0][0] = .5; d[0][1] =-pq;
d[1][0] = pq; d[1][1] = 0.;
}
else
{
//padding
int flip = 1;
for (int i=0; i<n; ++i)
{
d[i][n]=flip*d[i][n-2];
d[n][i]=flip*d[n-2][i];
flip=-flip;
}
d[n][n]=flip*d[n-2][n];
do_line (d[n-1],d[n],2*n-1,n);
for (int k=n; k>=2; --k)
{
do_line (d[k-2],d[k-1],2*n-1,k-1);
do_line (d[k-1],d[k],2*n,k);
}
do_line0 (d[0],2*n-1);
do_line (d[0],d[1],2*n,1);
do_line0 (d[0],2*n);
}
return d;
}
void wigner_d_risbo_scalar::do_line0 (double *l1, int j)
{
double xj = 1./j;
l1[j] = -p*l1[j-1];
for (int i=j-1; i>=1; --i)
l1[i] = xj*sqt[j]*(q*sqt[j-i]*l1[i] - p*sqt[i]*l1[i-1]);
l1[0] = q*l1[0];
}
void wigner_d_risbo_scalar::do_line (const double *l1, double *l2, int j, int k)
{
double xj = 1./j;
double t1 = xj*sqt[j-k]*q, t2 = xj*sqt[j-k]*p;
double t3 = xj*sqt[k]*p, t4 = xj*sqt[k]*q;
l2[j] = sqt[j] * (t4*l1[j-1]-t2*l2[j-1]);
for (int i=j-1; i>=1; --i)
l2[i] = t1*sqt[j-i]*l2[i] - t2*sqt[i]*l2[i-1]
+t3*sqt[j-i]*l1[i] + t4*sqt[i]*l1[i-1];
l2[0] = sqt[j] * (t3*l1[0]+t1*l2[0]);
}
wigner_d_risbo_scalar::wigner_d_risbo_scalar(int lmax, double ang)
: p(sin(ang/2)), q(cos(ang/2)), sqt(2*lmax+1),
d(lmax+1,2*lmax+1), n(-1)
{ for (tsize m=0; m<sqt.size(); ++m) sqt[m] = sqrt(double(m)); }
const arr2<double> &wigner_d_risbo_scalar::recurse ()
{
++n;
if (n==0)
d[0][0] = 1;
else if (n==1)
{
d[0][0] = q*q; d[0][1] = -p*q*sqt[2]; d[0][2] = p*p;
d[1][0] = -d[0][1]; d[1][1] = q*q-p*p; d[1][2] = d[0][1];
}
else
{
// padding
int sign = (n&1)? -1 : 1;
for (int i=0; i<=2*n-2; ++i)
{
d[n][i] = sign*d[n-2][2*n-2-i];
sign=-sign;
}
do_line (d[n-1],d[n],2*n-1,n);
for (int k=n; k>=2; --k)
{
do_line (d[k-2],d[k-1],2*n-1,k-1);
do_line (d[k-1],d[k],2*n,k);
}
do_line0 (d[0],2*n-1);
do_line (d[0],d[1],2*n,1);
do_line0 (d[0],2*n);
}
return d;
}
wigner_d_halfpi_risbo_openmp::wigner_d_halfpi_risbo_openmp(int lmax)
: pq(.5*sqrt(2.)), sqt(2*lmax+1), d(lmax+2,lmax+2),
dd(lmax+2,lmax+2), n(-1)
{ for (tsize m=0; m<sqt.size(); ++m) sqt[m] = sqrt(double(m)); }
const arr2<double> &wigner_d_halfpi_risbo_openmp::recurse ()
{
++n;
if (n==0)
d[0][0] = 1;
else if (n==1)
{
d.fast_alloc(3,3);
d[0][0] = .5; d[0][1] =-pq;
d[1][0] = pq; d[1][1] = 0.;
}
else
{
//padding
int flip = 1;
for (int i=0; i<n; ++i)
{
d[i][n]=flip*d[i][n-2];
d[n][i]=flip*d[n-2][i];
flip=-flip;
}
d[n][n]=flip*d[n-2][n];
for (int j=2*n-1; j<=2*n; ++j)
{
dd.fast_alloc(n+2,n+2);
double tmpx1 = pq/j;
dd[0][0] = pq*d[0][0];
for (int i=1;i<=n; ++i)
dd[0][i] = tmpx1*sqt[j]*(sqt[j-i]*d[0][i] - sqt[i]*d[0][i-1]);
#pragma omp parallel
{
int k;
#pragma omp for schedule(static)
for (k=1; k<=n; ++k)
{
double stmp1=sqt[j-k]*tmpx1;
double stmp2=sqt[k]*tmpx1;
double save1 = stmp1*d[k][0], save2 = stmp2*d[k-1][0];
dd[k][0] = sqt[j]*(save1+save2);
for (int i=1; i<=n; ++i)
{
dd[k][i] = sqt[i]*(save2-save1);
save1 = stmp1*d[k][i];
save2 = stmp2*d[k-1][i];
dd[k][i] += sqt[j-i]*(save1+save2);
}
}
}
dd.swap(d);
}
}
return d;
}
wigner_d_risbo_openmp::wigner_d_risbo_openmp(int lmax, double ang)
: p(sin(ang/2)), q(cos(ang/2)), sqt(2*lmax+1),
d(lmax+1,2*lmax+1), dd(lmax+1,2*lmax+1), n(-1)
{ for (tsize m=0; m<sqt.size(); ++m) sqt[m] = sqrt(double(m)); }
const arr2<double> &wigner_d_risbo_openmp::recurse ()
{
++n;
if (n==0)
d[0][0] = 1;
else if (n==1)
{
d[0][0] = q*q; d[0][1] = -p*q*sqt[2]; d[0][2] = p*p;
d[1][0] = -d[0][1]; d[1][1] = q*q-p*p; d[1][2] = d[0][1];
}
else
{
// padding
int sign = (n&1)? -1 : 1;
for (int i=0; i<=2*n-2; ++i)
{
d[n][i] = sign*d[n-2][2*n-2-i];
sign=-sign;
}
for (int j=2*n-1; j<=2*n; ++j)
{
double xj = 1./j;
dd[0][0] = q*d[0][0];
for (int i=1;i<j; ++i)
dd[0][i] = xj*sqt[j]*(q*sqt[j-i]*d[0][i] - p*sqt[i]*d[0][i-1]);
dd[0][j] = -p*d[0][j-1];
#pragma omp parallel
{
int k;
#pragma omp for schedule(static)
for (k=1; k<=n; ++k)
{
double t1 = xj*sqt[j-k]*q, t2 = xj*sqt[j-k]*p;
double t3 = xj*sqt[k ]*p, t4 = xj*sqt[k ]*q;
dd[k][0] = xj*sqt[j]*(q*sqt[j-k]*d[k][0] + p*sqt[k]*d[k-1][0]);
for (int i=1; i<j; ++i)
dd[k][i] = t1*sqt[j-i]*d[k ][i] - t2*sqt[i]*d[k ][i-1]
+ t3*sqt[j-i]*d[k-1][i] + t4*sqt[i]*d[k-1][i-1];
dd[k][j] = -t2*sqt[j]*d[k][j-1] + t4*sqt[j]*d[k-1][j-1];
}
}
dd.swap(d);
}
}
return d;
}
wignergen::wignergen (int lmax_, const arr<double> &thetas, double epsilon)
: eps(epsilon), lmax(lmax_),
logsum(2*lmax+1), lc05(thetas.size()), ls05(thetas.size()),
flm1(2*lmax+1), flm2(2*lmax+1),
cf(maxscale+1-minscale), costh(thetas.size()), xl(lmax+1),
thetaflip(thetas.size()),
m1(-1234567890), m2(-1234567890), am1(-1234567890), am2(-1234567890),
mlo(-1234567890), mhi(-1234567890),
fx(lmax+2), result(lmax+1)
#ifdef PLANCK_HAVE_SSE2
, result2(lmax+1)
#endif
{
planck_assert(lmax>0,"lmax too small");
logsum[0] = 0.;
for (tsize m=1; m<logsum.size(); ++m)
logsum[m] = logsum[m-1]+log(static_cast<long double>(m));
for (tsize lm=0; lm<flm1.size(); ++lm)
{
flm1[lm] = sqrt(1./(lm+1.));
flm2[lm] = sqrt(lm/(lm+1.));
}
for (tsize i=0; i<cf.size(); ++i)
cf[i] = ldexp(1.,(int(i)+minscale)*large_exponent2);
fsmall = ldexp(1.,-large_exponent2);
fbig = ldexp(1.,large_exponent2);
for (tsize i=0; i<thetas.size(); ++i)
{
double theta=fmodulo(thetas[i],twopi);
if (theta>pi) theta-=twopi;
thetaflip[i]=(theta<0);
theta=abs(theta); // now theta is in (0; pi)
// tiny adjustments to make sure cos and sin (theta/2) are positive
if (theta==0.) theta=1e-16;
if (abs_approx(theta,pi,1e-15)) theta=pi-1e-15;
costh[i]=cos(theta);
lc05[i]=log(cos(0.5L*theta));
ls05[i]=log(sin(0.5L*theta));
}
xl[0]=0;
for (tsize l=1; l<xl.size(); ++l) xl[l]=1./l;
for (tsize l=0; l<fx.size(); ++l)
fx[l][0]=fx[l][1]=fx[l][2]=0.;
}
void wignergen::prepare (int m1_, int m2_)
{
if ((m1_==m1) && (m2_==m2)) return;
int mlo_=abs(m1_), mhi_=abs(m2_);
if (mhi_<mlo_) swap(mhi_,mlo_);
bool ms_similar = ((mhi==mhi_) && (mlo==mlo_));
bool flip_m_sign = ((m1*m2)!=(m1_*m2_));
m1=m1_; m2=m2_;
mlo=am1=abs(m1); mhi=am2=abs(m2);
if (mhi<mlo) swap(mhi,mlo);
if (ms_similar)
{
if (flip_m_sign)
for (int l=mhi; l<lmax; ++l)
fx[l+1][1]=-fx[l+1][1];
}
else
{
for (int l=mhi; l<lmax; ++l)
{
double t = flm1[l+m1]*flm1[l-m1]*flm1[l+m2]*flm1[l-m2];
double lt = 2*l+1;
double l1 = l+1;
fx[l+1][0]=l1*lt*t;
fx[l+1][1]=m1*m2*xl[l]*xl[l+1];
t = flm2[l+m1]*flm2[l-m1]*flm2[l+m2]*flm2[l-m2];
fx[l+1][2]=t*l1*xl[l];
}
}
prefactor = 0.5L*(logsum[2*mhi]-logsum[mhi+mlo]-logsum[mhi-mlo]);
preMinus = false;
if (mhi==am1)
{
cosPow = mhi-m2; sinPow = mhi+m2;
if (m1>=0)
{ swap(cosPow, sinPow); preMinus=((mhi-m2)&1); }
}
else
{
cosPow = mhi+m1; sinPow = mhi-m1;
if (m2<0)
{ swap(cosPow, sinPow); preMinus=((mhi+m1)&1); }
}
}
const arr<double> &wignergen::calc (int nth, int &firstl)
{
int l=mhi;
const dbl3 *fy = &fx[0];
const double cth = costh[nth];
double *res = &result[0];
long double logval = prefactor + lc05[nth]*cosPow + ls05[nth]*sinPow;
logval *= inv_ln2;
int scale = int (logval/large_exponent2)-minscale;
double rec1 = 0.;
double rec2 = double(exp(ln2*(logval-(scale+minscale)*large_exponent2)));
if (preMinus ^ (thetaflip[nth] && ((am1+am2)&1))) rec2 = -rec2;
while(scale<0) // iterate until we reach the realm of IEEE numbers
{
if (++l>lmax) break;
rec1 = (cth - fy[l][1])*fy[l][0]*rec2 - fy[l][2]*rec1;
if (++l>lmax) break;
rec2 = (cth - fy[l][1])*fy[l][0]*rec1 - fy[l][2]*rec2;
while (abs(rec2)>fbig)
{
rec1 *= fsmall;
rec2 *= fsmall;
++scale;
}
}
if (scale<0) { firstl=lmax+1; return result; }
rec1 *= cf[scale];
rec2 *= cf[scale];
for (;l<lmax-1;l+=2) // iterate until we cross the eps threshold
{
if (abs(rec2)>eps) break;
rec1 = (cth - fy[l+1][1])*fy[l+1][0]*rec2 - fy[l+1][2]*rec1;
if (abs(rec1)>eps) { swap(rec1,rec2); ++l; break; }
rec2 = (cth - fy[l+2][1])*fy[l+2][0]*rec1 - fy[l+2][2]*rec2;
}
if ((abs(rec2)<=eps) && (++l<=lmax))
{
rec1 = (cth - fy[l][1])*fy[l][0]*rec2 - fy[l][2]*rec1;
swap (rec1,rec2);
}
firstl = l;
if (l>lmax) return result;
res[l]=rec2;
for (;l<lmax-1;l+=2)
{
res[l+1] = rec1 = (cth - fy[l+1][1])*fy[l+1][0]*rec2 - fy[l+1][2]*rec1;
res[l+2] = rec2 = (cth - fy[l+2][1])*fy[l+2][0]*rec1 - fy[l+2][2]*rec2;
}
while (true)
{
if (++l>lmax) break;
res[l] = rec1 = (cth - fy[l][1])*fy[l][0]*rec2 - fy[l][2]*rec1;
if (++l>lmax) break;
res[l] = rec2 = (cth - fy[l][1])*fy[l][0]*rec1 - fy[l][2]*rec2;
}
return result;
}
#ifdef PLANCK_HAVE_SSE2
#define RENORMALIZE \
do \
{ \
double rec1a, rec1b, rec2a, rec2b, cfa, cfb; \
read_v2df (rec1, &rec1a, &rec1b); read_v2df (rec2, &rec2a, &rec2b); \
read_v2df (corfac, &cfa, &cfb); \
while (abs(rec2a)>fbig) \
{ \
rec1a*=fsmall; rec2a*=fsmall; ++scale1; \
cfa = (scale1<0) ? 0. : cf[scale1]; \
} \
while (abs(rec2b)>fbig) \
{ \
rec1b*=fsmall; rec2b*=fsmall; ++scale2; \
cfb = (scale2<0) ? 0. : cf[scale2]; \
} \
rec1=build_v2df(rec1a,rec1b); rec2=build_v2df(rec2a,rec2b); \
corfac=build_v2df(cfa,cfb); \
} \
while(0)
#define GETPRE(prea,preb,lv) \
prea=_mm_mul_pd(_mm_sub_pd(cth,_mm_set1_pd(fy[lv][1])),_mm_set1_pd(fy[lv][0])); \
preb=_mm_set1_pd(fy[lv][2]);
#define NEXTSTEP(prea,preb,prec,pred,reca,recb,lv) \
{ \
prec = _mm_set1_pd(fy[lv][1]); \
preb = _mm_mul_pd(preb,reca); \
prea = _mm_mul_pd(prea,recb); \
v2df t0 = _mm_set1_pd(fy[lv][0]); \
prec = _mm_sub_pd(cth,prec); \
pred = _mm_set1_pd(fy[lv][2]); \
reca = _mm_sub_pd(prea,preb); \
prec = _mm_mul_pd(prec,t0); \
}
const arr_align<v2df,16> &wignergen::calc (int nth1, int nth2, int &firstl)
{
int l=mhi;
const dbl3 *fy = &fx[0];
const v2df cth = build_v2df(costh[nth1],costh[nth2]);
v2df *res = &result2[0];
long double logval1 = prefactor + lc05[nth1]*cosPow + ls05[nth1]*sinPow,
logval2 = prefactor + lc05[nth2]*cosPow + ls05[nth2]*sinPow;
logval1 *= inv_ln2;
logval2 *= inv_ln2;
int scale1 = int (logval1/large_exponent2)-minscale,
scale2 = int (logval2/large_exponent2)-minscale;
v2df rec1 = _mm_setzero_pd();
double tr1 = double(exp(ln2*(logval1-(scale1+minscale)*large_exponent2))),
tr2 = double(exp(ln2*(logval2-(scale2+minscale)*large_exponent2)));
if (preMinus ^ (thetaflip[nth1] && ((am1+am2)&1))) tr1 = -tr1;
if (preMinus ^ (thetaflip[nth2] && ((am1+am2)&1))) tr2 = -tr2;
v2df rec2 = build_v2df(tr1,tr2);
v2df corfac = build_v2df ( (scale1<0) ? 0. : cf[scale1],
(scale2<0) ? 0. : cf[scale2]);
v2df eps2=build_v2df(eps,eps);
v2df fbig2=build_v2df(fbig,fbig);
v2df pre0,pre1,pre2,pre3;
GETPRE(pre0,pre1,l+1)
if ((scale1<0) && (scale2<0))
{
while (true)
{
if (++l>lmax) break;
NEXTSTEP(pre0,pre1,pre2,pre3,rec1,rec2,l+1)
if (++l>lmax) break;
NEXTSTEP(pre2,pre3,pre0,pre1,rec2,rec1,l+1)
if (v2df_any_gt(rec2,fbig2))
{
RENORMALIZE;
if ((scale1>=0) || (scale2>=0)) break;
}
}
}
if (l<=lmax)
{
GETPRE(pre0,pre1,l+1)
while (true)
{
v2df t1;
res[l]=t1=_mm_mul_pd(rec2,corfac);
if (v2df_any_gt(t1,eps2))
break;
if (++l>lmax) break;
NEXTSTEP(pre0,pre1,pre2,pre3,rec1,rec2,l+1)
res[l]=t1=_mm_mul_pd(rec1,corfac);
if (v2df_any_gt(t1,eps2))
{ swap(rec1,rec2); break; }
if (++l>lmax) break;
NEXTSTEP(pre2,pre3,pre0,pre1,rec2,rec1,l+1)
if (v2df_any_gt(rec2,fbig2))
RENORMALIZE;
}
}
firstl=l;
if (l>lmax) return result2;
GETPRE(pre0,pre1,l+1)
while (true)
{
v2df t1;
res[l]=t1=_mm_mul_pd(rec2,corfac);
if (v2df_all_ge(t1,eps2))
break;
if (++l>lmax) break;
NEXTSTEP(pre0,pre1,pre2,pre3,rec1,rec2,l+1)
res[l]=t1=_mm_mul_pd(rec1,corfac);
if (v2df_all_ge(t1,eps2))
{ swap(rec1,rec2); break; }
if (++l>lmax) break;
NEXTSTEP(pre2,pre3,pre0,pre1,rec2,rec1,l+1)
if (v2df_any_gt(rec2,fbig2))
RENORMALIZE;
}
if (l>lmax) return result2;
rec1 = _mm_mul_pd (rec1,corfac);
rec2 = _mm_mul_pd (rec2,corfac);
GETPRE(pre0,pre1,l+1)
for (;l<lmax-1;l+=2)
{
res[l] = rec2;
NEXTSTEP(pre0,pre1,pre2,pre3,rec1,rec2,l+2)
res[l+1] = rec1;
NEXTSTEP(pre2,pre3,pre0,pre1,rec2,rec1,l+3)
}
res[l] = rec2;
if (++l<=lmax)
{
NEXTSTEP(pre0,pre1,pre2,pre3,rec1,rec2,l+1)
res[l] = rec1;
}
return result2;
}
#endif /* PLANCK_HAVE_SSE2 */

169
external/healpix/cxxsupport/wigner.h vendored Normal file
View file

@ -0,0 +1,169 @@
/*
* This file is part of libcxxsupport.
*
* libcxxsupport is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* libcxxsupport is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with libcxxsupport; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik
* and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
* (DLR).
*/
/*! \file wigner.h
* Several C++ classes for calculating Wigner matrices
*
* Copyright (C) 2009,2010 Max-Planck-Society
* \author Martin Reinecke and others (see individual classes)
*/
#ifndef PLANCK_WIGNER_H
#define PLANCK_WIGNER_H
#include <cmath>
#include "arr.h"
#include "sse_utils.h"
/*! Class for calculation of the Wigner matrix at pi/2, using Risbo recursion
in a way that cannot easily be parallelised, but is fairly efficient on
scalar machines. */
class wigner_d_halfpi_risbo_scalar
{
private:
double pq;
arr<double> sqt;
arr2<double> d;
int n;
void do_line0 (double *l1, int j);
void do_line (const double *l1, double *l2, int j, int k);
public:
wigner_d_halfpi_risbo_scalar(int lmax);
const arr2<double> &recurse ();
};
/*! Class for calculation of the Wigner matrix at arbitrary angles, using Risbo
recursion in a way that cannot easily be parallelised, but is fairly
efficient on scalar machines. */
class wigner_d_risbo_scalar
{
private:
double p,q;
arr<double> sqt;
arr2<double> d;
int n;
void do_line0 (double *l1, int j);
void do_line (const double *l1, double *l2, int j, int k);
public:
wigner_d_risbo_scalar(int lmax, double ang);
const arr2<double> &recurse ();
};
/*! Class for calculation of the Wigner matrix at pi/2, using Risbo recursion
in a way that can be OpenMP-parallelised. This approach uses more memory
and is slightly slower than wigner_d_halfpi_risbo_scalar. */
class wigner_d_halfpi_risbo_openmp
{
private:
double pq;
arr<double> sqt;
arr2<double> d,dd;
int n;
public:
wigner_d_halfpi_risbo_openmp(int lmax);
const arr2<double> &recurse ();
};
/*! Class for calculation of the Wigner matrix at arbitrary angles, using Risbo
recursion in a way that can be OpenMP-parallelised. This approach uses more
memory and is slightly slower than wigner_d_risbo_scalar. */
class wigner_d_risbo_openmp
{
private:
double p,q;
arr<double> sqt;
arr2<double> d, dd;
int n;
public:
wigner_d_risbo_openmp(int lmax, double ang);
const arr2<double> &recurse ();
};
/*! Class for calculation of the Wigner matrix elements by l-recursion.
For details, see Prezeau & Reinecke 2010, http://arxiv.org/pdf/1002.1050 */
class wignergen
{
private:
typedef double dbl3[3];
// members set in the constructor and kept fixed afterwards
double fsmall, fbig, eps;
int lmax;
arr<long double> logsum, lc05, ls05;
arr<double> flm1, flm2, cf, costh, xl;
arr<bool> thetaflip;
// members depending on m and m'
int m1, m2, am1, am2, mlo, mhi, cosPow, sinPow;
long double prefactor;
arr<dbl3> fx;
bool preMinus;
// members depending on theta
arr<double> result;
#ifdef PLANCK_HAVE_SSE2
arr_align<v2df,16> result2;
#endif
enum { large_exponent2=90, minscale=-4, maxscale=14 };
public:
/*! Constructs an object that can compute Wigner matrix elements up
to a maximum \a l value of \a lmax_, at the colatitudes provided
in \a thetas. The generator will be allowed to regard values with
absolute magnitudes smaller than \a epsilon as zero; a typical value
is 1e-30. */
wignergen (int lmax_, const arr<double> &thetas, double epsilon);
/*! Prepares the object to produce Wigner matrix elements with \a m=m1_
and \a m'=m2_ in subsequent calls to calc(). This operation is not cheap
so it is recommended to use calc() for many different colatitudes after
every call to prepare(), if possible. */
void prepare (int m1_, int m2_);
/*! Computes the Wigner matrix elements for the values of \a m and \a m'
set by the preceding call to prepare(), for all \a l up to \a lmax
(set in the constructor), and for the \a nth colatitude passed to the
constructor. On return, \a firstl contains the index of the first
matrix element larger than \a epsilon; all values with smaller indices
in the result array are undefined. */
const arr<double> &calc (int nth, int &firstl);
#ifdef PLANCK_HAVE_SSE2
const arr_align<v2df,16> &calc (int nth1, int nth2, int &firstl);
#endif
};
#endif

208
external/healpix/cxxsupport/xcomplex.h vendored Normal file
View file

@ -0,0 +1,208 @@
/*
* This file is part of libcxxsupport.
*
* libcxxsupport is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* libcxxsupport is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with libcxxsupport; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik
* and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
* (DLR).
*/
/*! \file xcomplex.h
* Class for representing complex numbers, strongly inspired by C++'s
* std::complex
*
* Copyright (C) 2003-2010 Max-Planck-Society
* \author Martin Reinecke
*/
#ifndef PLANCK_XCOMPLEX_H
#define PLANCK_XCOMPLEX_H
#include <iostream>
#include <complex>
/*! \defgroup complexgroup Complex number support */
/*! \{ */
/*! A class for representing complex numbers.
This template is intended as an (under-encapsulated) replacement for
the (over-encapsulated) std::complex<>. The goal is to include the
whole functionality of std::complex<>, with some additional methods
that allow higher performance.
The (known and intentional) differences between xcomplex<> and
std::complex<> are:
- the default constructor of xcomplex<> does nothing, in contrast to
std::complex<>, which initialises its members to zero.
- xcomplex<> implements the methods real() and imag() according
to defect report DR387
*/
template<typename T> class xcomplex
{
public:
T re, /*!< real part */
im; /*!< imaginary part */
/*! Default constructor. \a re and \a im are not initialised. */
xcomplex () {}
/*! Creates the complex number (\a re_, \a im_). */
xcomplex (const T &re_, const T &im_)
: re(re_), im(im_) {}
/*! Creates the complex number (\a re_, 0). */
xcomplex (const T &re_)
: re(re_), im(0) {}
/*! Creates an xcomplex from a std::complex of identical precision. */
xcomplex (const std::complex<T> &orig)
: re(orig.real()), im(orig.imag()) {}
/*! Creates a complex number as a copy of \a orig. */
template<typename U> explicit xcomplex (const xcomplex<U> &orig)
: re(T(orig.re)), im(T(orig.im)) {}
/*! Conversion operator to std::complex<T> */
operator std::complex<T> () const
{ return std::complex<T>(re,im); }
/*! Returns the real part as lvalue. */
T &real() { return re; }
/*! Returns the real part. */
const T &real() const { return re; }
/*! Returns the imaginary part as lvalue. */
T &imag() { return im; }
/*! Returns the imaginary part. */
const T &imag() const { return im; }
/*! Sets the number to (\a re_, \a im_). */
void Set (const T &re_, const T &im_)
{ re = re_; im = im_; }
/*! Sets the number to \a orig. */
xcomplex &operator= (const xcomplex &orig)
{ re=orig.re; im=orig.im; return *this; }
/*! Sets the number to \a orig. */
xcomplex &operator= (const std::complex<T> &orig)
{ re=orig.real(); im=orig.imag(); return *this; }
/*! Sets the number to (\a orig, 0). */
xcomplex &operator= (const T &orig)
{ re=orig; im=0; return *this; }
/*! Adds \a b to \a *this. */
xcomplex &operator+= (const xcomplex &b)
{ re+=b.re; im+=b.im; return *this; }
/*! Subtracts \a b from \a *this. */
xcomplex &operator-= (const xcomplex &b)
{ re-=b.re; im-=b.im; return *this; }
/*! Multiplies \a *this by \a b. */
xcomplex &operator*= (const xcomplex &b)
{
T tmp=re;
re=tmp*b.re-im*b.im; im=tmp*b.im+im*b.re;
return *this;
}
/*! Divides \a *this by \a b. */
xcomplex &operator/= (const xcomplex &b)
{
std::complex<T> tmp=*this;
std::complex<T> tmp2=b;
tmp /= tmp2;
*this=tmp;
return *this;
}
/*! Multiplies \a *this by \a fact. */
xcomplex &operator*= (const T &fact)
{ re*=fact; im*=fact; return *this; }
/*! Divides \a *this by \a div. */
xcomplex &operator/= (const T &div)
{ re/=div; im/=div; return *this; }
/*! Returns \a *this * \a fact. */
xcomplex operator* (const T &fact) const
{ return xcomplex (re*fact,im*fact); }
/*! Returns \a *this * \a b. */
xcomplex operator* (const xcomplex &b) const
{ return xcomplex (re*b.re-im*b.im, re*b.im+im*b.re); }
/*! Returns \a *this / \a b. */
xcomplex operator/ (const xcomplex &b) const
{ return xcomplex(std::complex<T>(*this)/std::complex<T>(b)); }
/*! Returns \a *this / \a div. */
xcomplex operator/ (const T &div) const
{ return xcomplex (re/div,im/div); }
/*! Returns \a *this + \a b. */
xcomplex operator+ (const xcomplex &b) const
{ return xcomplex (re+b.re, im+b.im); }
/*! Returns \a *this - \a b. */
xcomplex operator- (const xcomplex &b) const
{ return xcomplex (re-b.re, im-b.im); }
/*! Returns \a -(*this) */
xcomplex operator- () const
{ return xcomplex (-re,-im); }
/*! Flips the signs of both components. */
void Negate()
{ re=-re; im=-im; }
/*! Flips the signs of the imaginary component. */
void Conjugate()
{ im=-im; }
/*! Multiplies the number by exp(i*\a angle) */
void Rotate(T angle)
{
T ca=cos(angle), sa=sin(angle);
T tmp=re;
re=tmp*ca-im*sa; im=tmp*sa+im*ca;
}
/*! Returns the complex conjugate of \a *this. */
xcomplex conj() const
{ return xcomplex (re,-im); }
/*! Returns the norm of \a *this. */
T norm() const
{ return re*re + im*im; }
};
/*! Returns the complex conjugate of \a num.
\relates xcomplex */
template <typename T> inline xcomplex<T> conj (const xcomplex<T> &num)
{ return xcomplex<T> (num.re, -num.im); }
/*! Returns the norm of \a num.
\relates xcomplex */
template <typename T> inline T norm (const xcomplex<T> &num)
{ return num.re*num.re + num.im*num.im; }
/*! Returns the absolute value of \a num.
\relates xcomplex */
template <typename T> inline T abs (const xcomplex<T> &num)
{
using namespace std;
return abs(complex<T>(num));
}
/*! Returns \a f1*f2.
\relates xcomplex */
template <typename T> inline xcomplex<T> operator*
(const T &f1, const xcomplex<T> &f2)
{ return xcomplex<T> (f1*f2.re, f1*f2.im); }
/*! Returns \a f1/f2.
\relates xcomplex */
template <typename T> inline xcomplex<T> operator/
(const T &f1, const xcomplex<T> &f2)
{ return xcomplex<T>(f1)/f2; }
/*! Writes \a val to \a os.
\relates xcomplex */
template<typename T>
inline std::ostream &operator<< (std::ostream &os, const xcomplex<T> &val)
{ os << "(" << val.re << "," << val.im << ")"; return os; }
/*! \} */
#endif