diff --git a/external/healpix/COPYING b/external/healpix/COPYING new file mode 100644 index 0000000..3912109 --- /dev/null +++ b/external/healpix/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program 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. + + This program 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 this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/external/healpix/Healpix_cxx/Healpix_cxx.dox b/external/healpix/Healpix_cxx/Healpix_cxx.dox new file mode 100644 index 0000000..1b4a1ac --- /dev/null +++ b/external/healpix/Healpix_cxx/Healpix_cxx.dox @@ -0,0 +1,133 @@ +/*! \mainpage HEALPix C++ documentation +
    +
  • \ref components "Programming interface" +
  • \ref facilities "Facilities" +
+ */ + +/*! \page components Code components + + Classes: + - Healpix_Base contains all functionality related to the HEALPix + pixelisation which does not require actual map data. + - Healpix_Base2 is analogous to Healpix_Base, but allows for much + higher resolutions. + - Healpix_Map is derived from Healpix_Base and implements + additional functionality like change of the ordering scheme, up- and + degrading and interpolation. + - Alm is used to store spherical harmonic coefficients. + - PowSpec is used to store \f$C_l\f$ coefficients. + + Conversions between different data types: + - \ref alm_healpix_group "HEALPix maps <-> a_lm". + - \ref alm_ps_group "power spectra <-> a_lm". + + FITS I/O: + - for \ref healpix_map_fitsio_group "HEALPix Maps" + - for \ref alm_fitsio_group "spherical harmonic coefficients" + - for \ref powspec_fitsio_group "power spectra" +*/ + +/*! \page facilities HEALPix C++ facilities + + \section syn_alm_cxx + This program reads a set of \f$C_l\f$ from disk and converts it to + a set of \f$a_{lm}\f$. + + \verbinclude syn_alm_cxx.par.txt + + \section alm2map_cxx + This program reads a set of \f$a_{lm}\f$ from disk and converts them to + a HEALPix map. + + \verbinclude alm2map_cxx.par.txt + + \section anafast_cxx + This program performs harmonic analysis of a HEALPix map up to a + user-specified maximum spherical harmonic order \f$l_{\mbox{max}}\f$. + The integrals are computed on the whole sphere. + Scalar, or scalar and tensor, spherical harmonic coefficients are evaluated + from the map(s) if the input provides, respectively, only the temperature, + or temperature and polarisation maps. + The total operation count scales as \f${\cal {O}}(N_{\mbox{pix}}^{3/2})\f$ + with a prefactor depending on \f$l_{\mbox{max}}\f$. + + Anafast_cxx reads a file containing the map(s) and produces a file + containing the temperature power spectrum \f$C^T_l\f$ and, if requested, + also the polarisation power spectra \f$C^E_l\f$, \f$C^B_l\f$ and + \f$C^{T\times E}_l\f$. The \f$a_{lm}\f$ coefficients computed during the + execution also can be written to a file if requested. + + Anafast_cxx executes an approximate, discrete point-set quadrature on + a sphere sampled at the HEALPix pixel centers. + Spherical harmonic transforms are computed using recurrence relations for + Legendre polynomials on co-latitude (\f$\vartheta\f$) and Fast Fourier + transforms on longitude (\f$\varphi\f$). + + Anafast permits two execution options which allow a significant + improvement of accuracy of the approximate quadrature performed by + this facility: + + - An improved analysis using the provided ring weights, which correct the + quadrature on latitude, and/or + - An iterative scheme using in succession several backward and forward + harmonic transforms of the maps. + + \verbinclude anafast_cxx.par.txt + + \section map2tga + This program reads in a HEALPix sky map in FITS format and generates an + image in TGA format. map2tga allows the selection of the projection + scheme (Mollweide or Gnomonic for small patches of the sky), color + table, color bar inclusion, linear or log scaling, maximum and + minimum range for the plot and plot-title. The facility provides + a command-line interface, but can also read a parameter file. + + \verbinclude map2tga.par.txt + + \section rotalm_cxx + Performs a coordinate transformation on a set of \f$a_{lm}\f$. + + \verbatim +Usage: rotalm_cxx +Transform 1: Equatorial (2000) -> Galactic (2000) + 2: Galactic (2000) -> Equatorial (2000) + 3: Equatorial (2000) -> Ecliptic (2000) + 4: Ecliptic (2000) -> Equatorial (2000) + 5: Ecliptic (2000) -> Galactic (2000) + 6: Galactic (2000) -> Ecliptic (2000) + 7: Equatorial (1950) -> Galactic (1950) + 8: Galactic (1950) -> Equatorial (1950) + 9: Equatorial (1950) -> Ecliptic (1950) + 10: Ecliptic (1950) -> Equatorial (1950) + 11: Ecliptic (1950) -> Galactic (1950) + 12: Galactic (1950) -> Ecliptic (1950) + \endverbatim + + \section mult_alm + This program reads a set of (unpolarised or polarised) \f$a_{lm}\f$, + removes pixel window functions and/or Gaussian beams, applies different + pixel window functions or Gaussian beams, and outputs the result. + + \verbinclude mult_alm.par.txt + + \section smoothing_cxx + This program reads a (unpolarised or polarised) HEALPix map, converts it + to \f$a_{lm}\f$, performs a smoothing operation with a Gaussian beam, + converts the \f$a_{lm}\f$ back to a map and outputs the result. + + \verbinclude smoothing_cxx.par.txt + + \section calc_powspec + This program reads one or two sets of \f$a_{lm}\f$, extracts the + (unpolarised or polarised) power spectrum or the unpolarised cross power + spectrum, and outputs the result. + + \verbatim Usage: calc_powspec [] \endverbatim + + \section median_filter_cxx + This program inputs a HEALPix map, runs a median filter with the desired + radius on it and saves the result to another file. + + \verbatim Usage: median_filter_cxx \endverbatim +*/ diff --git a/external/healpix/Healpix_cxx/alm.h b/external/healpix/Healpix_cxx/alm.h new file mode 100644 index 0000000..5af845b --- /dev/null +++ b/external/healpix/Healpix_cxx/alm.h @@ -0,0 +1,177 @@ +/* + * This file is part of Healpix_cxx. + * + * Healpix_cxx 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. + * + * Healpix_cxx 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 Healpix_cxx; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * For more information about HEALPix, see http://healpix.jpl.nasa.gov + */ + +/* + * Healpix_cxx is being developed at the Max-Planck-Institut fuer Astrophysik + * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt + * (DLR). + */ + +/*! \file alm.h + * Class for storing spherical harmonic coefficients. + * + * Copyright (C) 2003 - 2009 Max-Planck-Society + * \author Martin Reinecke + */ + +#ifndef PLANCK_ALM_H +#define PLANCK_ALM_H + +#include "arr.h" + +/*! Base class for calculating the storage layout of spherical harmonic + coefficients. */ +class Alm_Base + { + protected: + int lmax, mmax, tval; + + public: + /*! Returns the total number of coefficients for maximum quantum numbers + \a l and \a m. */ + static tsize Num_Alms (int l, int m) + { + planck_assert(m<=l,"mmax must not be larger than lmax"); + return ((m+1)*(m+2))/2 + (m+1)*(l-m); + } + /*! Constructs an Alm_Base object with given \a lmax and \a mmax. */ + Alm_Base (int lmax_=0, int mmax_=0) + : lmax(lmax_), mmax(mmax_), tval(2*lmax+1) {} + + /*! Changes the object's maximum quantum numbers to \a lmax and \a mmax. */ + void Set (int lmax_, int mmax_) + { + lmax=lmax_; + mmax=mmax_; + tval=2*lmax+1; + } + + /*! Returns the maximum \a l */ + int Lmax() const { return lmax; } + /*! Returns the maximum \a m */ + int Mmax() const { return mmax; } + + /*! Returns an array index for a given m, from which the index of a_lm + can be obtained by adding l. */ + int index_l0 (int m) const + { return ((m*(tval-m))>>1); } + + /*! Returns the array index of the specified coefficient. */ + int index (int l, int m) const + { return index_l0(m) + l; } + + /*! Returns \a true, if both objects have the same \a lmax and \a mmax, + else \a false. */ + bool conformable (const Alm_Base &other) const + { return ((lmax==other.lmax) && (mmax==other.mmax)); } + + /*! Swaps the contents of two Alm_Base objects. */ + void swap (Alm_Base &other) + { + std::swap(lmax, other.lmax); + std::swap(mmax, other.mmax); + std::swap(tval, other.tval); + } + }; + +/*! Class for storing spherical harmonic coefficients. */ +template class Alm: public Alm_Base + { + private: + arr alm; + + public: + /*! Constructs an Alm object with given \a lmax and \a mmax. */ + Alm (int lmax_=0, int mmax_=0) + : Alm_Base(lmax_,mmax_), alm (Num_Alms(lmax,mmax)) {} + + /*! Deletes the old coefficients and allocates storage according to + \a lmax and \a mmax. */ + void Set (int lmax_, int mmax_) + { + Alm_Base::Set(lmax_, mmax_); + alm.alloc(Num_Alms(lmax,mmax)); + } + + /*! Deallocates the old coefficients and uses the content of \a data + for storage. \a data is deallocated during the call. */ + void Set (arr &data, int lmax_, int mmax_) + { + planck_assert (Num_Alms(lmax_,mmax_)==data.size(),"wrong array size"); + Alm_Base::Set(lmax_, mmax_); + alm.transfer(data); + } + + /*! Sets all coefficients to zero. */ + void SetToZero () + { alm.fill (0); } + + /*! Multiplies all coefficients by \a factor. */ + template void Scale (const T2 &factor) + { for (tsize m=0; m void ScaleL (const arr &factor) + { + planck_assert(factor.size()>tsize(lmax), + "alm.ScaleL: factor array too short"); + for (int m=0; m<=mmax; ++m) + for (int l=m; l<=lmax; ++l) + operator()(l,m)*=factor[l]; + } + /*! Adds \a num to a_00. */ + template void Add (const T2 &num) + { alm[0]+=num; } + + /*! Returns a reference to the specified coefficient. */ + T &operator() (int l, int m) + { return alm[index(l,m)]; } + /*! Returns a constant reference to the specified coefficient. */ + const T &operator() (int l, int m) const + { return alm[index(l,m)]; } + + /*! Returns a pointer for a given m, from which the address of a_lm + can be obtained by adding l. */ + T *mstart (int m) + { return &alm[index_l0(m)]; } + /*! Returns a pointer for a given m, from which the address of a_lm + can be obtained by adding l. */ + const T *mstart (int m) const + { return &alm[index_l0(m)]; } + + /*! Returns a constant reference to the a_lm data. */ + const arr &Alms () const { return alm; } + + /*! Swaps the contents of two Alm objects. */ + void swap (Alm &other) + { + Alm_Base::swap(other); + alm.swap(other.alm); + } + + /*! Adds all coefficients from \a other to the own coefficients. */ + void Add (const Alm &other) + { + planck_assert (conformable(other), "A_lm are not conformable"); + for (tsize m=0; m void alm2map_cxx (paramfile ¶ms) + { + int nlmax = params.template find("nlmax"); + int nmmax = params.template find("nmmax",nlmax); + planck_assert(nmmax<=nlmax,"nmmax must not be larger than nlmax"); + string infile = params.template find("infile"); + string outfile = params.template find("outfile"); + int nside = params.template find("nside"); + double fwhm = arcmin2rad*params.template find("fwhm_arcmin",0); + + arr temp, pol; + get_pixwin (params,nlmax,nside,temp,pol); + + bool deriv = params.template find("derivatives",false); + if (deriv) + { + Alm > alm; + read_Alm_from_fits(infile,alm,nlmax,nmmax,2); + if (fwhm>0) smoothWithGauss (alm, fwhm); + Healpix_Map map(nside,RING,SET_NSIDE), + mapdth(nside,RING,SET_NSIDE), + mapdph(nside,RING,SET_NSIDE); + alm.ScaleL(temp); + + double offset = alm(0,0).real()/sqrt(fourpi); + alm(0,0) = 0; + alm2map_der1(alm,map,mapdth,mapdph); + map.Add(T(offset)); + write_Healpix_map_to_fits (outfile,map,mapdth,mapdph,planckType()); + return; + } + + bool polarisation = params.template find("polarisation"); + if (!polarisation) + { + Alm > alm; + read_Alm_from_fits(infile,alm,nlmax,nmmax,2); + if (fwhm>0) smoothWithGauss (alm, fwhm); + Healpix_Map map(nside,RING,SET_NSIDE); + alm.ScaleL(temp); + + double offset = alm(0,0).real()/sqrt(fourpi); + alm(0,0) = 0; + alm2map(alm,map); + map.Add(T(offset)); + write_Healpix_map_to_fits (outfile,map,planckType()); + } + else + { + Alm > almT, almG, almC; + read_Alm_from_fits(infile,almT,almG,almC,nlmax,nmmax,2); + if (fwhm>0) smoothWithGauss (almT, almG, almC, fwhm); + Healpix_Map mapT(nside,RING,SET_NSIDE), mapQ(nside,RING,SET_NSIDE), + mapU(nside,RING,SET_NSIDE); + almT.ScaleL(temp); + almG.ScaleL(pol); almC.ScaleL(pol); + + double offset = almT(0,0).real()/sqrt(fourpi); + almT(0,0) = 0; + alm2map_pol(almT,almG,almC,mapT,mapQ,mapU); + mapT.Add(T(offset)); + write_Healpix_map_to_fits (outfile,mapT,mapQ,mapU,planckType()); + } + } + +} // unnamed namespace + +int alm2map_cxx_module (int argc, const char **argv) + { + module_startup ("alm2map_cxx", argc, argv, 2, ""); + paramfile params (argv[1]); + + bool dp = params.find ("double_precision",false); + dp ? alm2map_cxx(params) : alm2map_cxx(params); + return 0; + } diff --git a/external/healpix/Healpix_cxx/alm_fitsio.cc b/external/healpix/Healpix_cxx/alm_fitsio.cc new file mode 100644 index 0000000..f52c1eb --- /dev/null +++ b/external/healpix/Healpix_cxx/alm_fitsio.cc @@ -0,0 +1,250 @@ +/* + * This file is part of Healpix_cxx. + * + * Healpix_cxx 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. + * + * Healpix_cxx 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 Healpix_cxx; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * For more information about HEALPix, see http://healpix.jpl.nasa.gov + */ + +/* + * Healpix_cxx is being developed at the Max-Planck-Institut fuer Astrophysik + * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt + * (DLR). + */ + +/* + * Copyright (C) 2003-2010 Max-Planck-Society + * Author: Martin Reinecke + */ + +#include +#include "alm_fitsio.h" +#include "alm.h" +#include "fitshandle.h" +#include "xcomplex.h" +#include "safe_cast.h" + +using namespace std; + +void get_almsize(fitshandle &inp, int &lmax, int &mmax) + { + if (inp.key_present("MAX-LPOL") && inp.key_present("MAX-MPOL")) + { + inp.get_key ("MAX-LPOL",lmax); + inp.get_key ("MAX-MPOL",mmax); + return; + } + + int n_alms = safe_cast(inp.nelems(1)); + arr index; + lmax=mmax=-1; + chunkMaker cm(n_alms,inp.efficientChunkSize(1)); + uint64 offset,ppix; + while(cm.getNext(offset,ppix)) + { + index.alloc(ppix); + inp.read_column(1,index,offset); + + for (tsize i=0; ilmax) lmax=l; + if (m>mmax) mmax=m; + } + } + } + +void get_almsize(const string &filename, int &lmax, int &mmax, int hdunum) + { + fitshandle inp; + inp.open (filename); + inp.goto_hdu(hdunum); + get_almsize (inp, lmax, mmax); + } + +void get_almsize_pol(const string &filename, int &lmax, int &mmax) + { + int tlmax, tmmax; + fitshandle inp; + inp.open (filename); + lmax=mmax=0; + for (int hdu=2; hdu<=4; ++hdu) + { + inp.goto_hdu(hdu); + get_almsize (inp,tlmax,tmmax); + if (tlmax>lmax) lmax=tlmax; + if (tmmax>mmax) mmax=tmmax; + } + } + +template void read_Alm_from_fits + (fitshandle &inp, Alm >&alms, int lmax, int mmax) + { + int n_alms = safe_cast(inp.nelems(1)); + arr index; + arr re, im; + + alms.Set(lmax, mmax); + alms.SetToZero(); + int max_index = lmax*lmax + lmax + mmax + 1; + chunkMaker cm(n_alms,inp.efficientChunkSize(1)); + uint64 offset,ppix; + while(cm.getNext(offset,ppix)) + { + index.alloc(ppix); + re.alloc(ppix); im.alloc(ppix); + inp.read_column(1,index,offset); + inp.read_column(2,re,offset); + inp.read_column(3,im,offset); + + for (tsize i=0; imax_index) return; + + int l = isqrt(index[i]-1); + int m = index[i] - l*l - l - 1; + planck_assert(m>=0,"negative m encountered"); + planck_assert(l>=m, "wrong l,m combination"); + if ((l<=lmax) && (m<=mmax)) + alms(l,m).Set (re[i], im[i]); + } + } + } + +template void read_Alm_from_fits (fitshandle &inp, + Alm > &alms, int lmax, int mmax); +template void read_Alm_from_fits (fitshandle &inp, + Alm > &alms, int lmax, int mmax); + + +template void read_Alm_from_fits + (const string &filename, Alm >&alms, int lmax, int mmax, + int hdunum) + { + fitshandle inp; + inp.open (filename); + inp.goto_hdu(hdunum); + read_Alm_from_fits(inp,alms,lmax,mmax); + } + +template void read_Alm_from_fits (const string &filename, + Alm > &alms, int lmax, int mmax, int hdunum); +template void read_Alm_from_fits (const string &filename, + Alm > &alms, int lmax, int mmax, int hdunum); + + +template void write_Alm_to_fits + (fitshandle &out, const Alm > &alms, int lmax, int mmax, + PDT datatype) + { + vector cols; + cols.push_back (fitscolumn("index","l*l+l+m+1",1,PLANCK_INT32)); + cols.push_back (fitscolumn("real","unknown",1,datatype)); + cols.push_back (fitscolumn("imag","unknown",1,datatype)); + out.insert_bintab(cols); + arr index; + arr re, im; + + int lm=alms.Lmax(), mm=alms.Mmax(); + int n_alms = ((mmax+1)*(mmax+2))/2 + (mmax+1)*(lmax-mmax); + + int l=0, m=0; + chunkMaker cm(n_alms,out.efficientChunkSize(1)); + uint64 offset,ppix; + while(cm.getNext(offset,ppix)) + { + index.alloc(ppix); + re.alloc(ppix); im.alloc(ppix); + for (tsize i=0; il) || (m>mmax)) { ++l; m=0; } + } + out.write_column(1,index,offset); + out.write_column(2,re,offset); + out.write_column(3,im,offset); + } + out.set_key("MAX-LPOL",lmax,"highest l in the table"); + out.set_key("MAX-MPOL",mmax,"highest m in the table"); + } + +template void write_Alm_to_fits + (fitshandle &out, const Alm > &alms, int lmax, + int mmax, PDT datatype); +template void write_Alm_to_fits + (fitshandle &out, const Alm > &alms, int lmax, + int mmax, PDT datatype); + + +template void write_compressed_Alm_to_fits + (fitshandle &out, const Alm > &alms, int lmax, int mmax, + PDT datatype) + { + vector cols; + cols.push_back (fitscolumn("index","l*l+l+m+1",1,PLANCK_INT32)); + cols.push_back (fitscolumn("real","unknown",1,datatype)); + cols.push_back (fitscolumn("imag","unknown",1,datatype)); + out.insert_bintab(cols); + arr index; + arr re, im; + + int n_alms = 0; + for (int m=0; m<=mmax; ++m) + for (int l=m; l<=lmax; ++l) + if (alms(l,m).norm()>0) ++n_alms; + + int l=0, m=0; + int real_lmax=0, real_mmax=0; + chunkMaker cm(n_alms,out.efficientChunkSize(1)); + uint64 offset,ppix; + while(cm.getNext(offset,ppix)) + { + index.alloc(ppix); + re.alloc(ppix); im.alloc(ppix); + for (tsize i=0; il) || (m>mmax)) { ++l; m=0; } + } + index[i] = l*l + l + m + 1; + re[i] = alms(l,m).re; + im[i] = alms(l,m).im; + if (l>real_lmax) real_lmax=l; + if (m>real_mmax) real_mmax=m; + ++m; + if ((m>l) || (m>mmax)) { ++l; m=0; } + } + out.write_column(1,index,offset); + out.write_column(2,re,offset); + out.write_column(3,im,offset); + } + out.set_key("MAX-LPOL",real_lmax,"highest l in the table"); + out.set_key("MAX-MPOL",real_mmax,"highest m in the table"); + } + +template void write_compressed_Alm_to_fits + (fitshandle &out, const Alm > &alms, int lmax, + int mmax, PDT datatype); +template void write_compressed_Alm_to_fits + (fitshandle &out, const Alm > &alms, int lmax, + int mmax, PDT datatype); diff --git a/external/healpix/Healpix_cxx/alm_fitsio.h b/external/healpix/Healpix_cxx/alm_fitsio.h new file mode 100644 index 0000000..7961175 --- /dev/null +++ b/external/healpix/Healpix_cxx/alm_fitsio.h @@ -0,0 +1,123 @@ +/* + * This file is part of Healpix_cxx. + * + * Healpix_cxx 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. + * + * Healpix_cxx 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 Healpix_cxx; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * For more information about HEALPix, see http://healpix.jpl.nasa.gov + */ + +/* + * Healpix_cxx is being developed at the Max-Planck-Institut fuer Astrophysik + * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt + * (DLR). + */ + +/*! \file alm_fitsio.h + * FITS I/O for spherical harmonic coefficients + * + * Copyright (C) 2003-2010 Max-Planck-Society + * \author Martin Reinecke + */ + +#ifndef PLANCK_ALM_FITSIO_H +#define PLANCK_ALM_FITSIO_H + +#include +#include "xcomplex.h" +#include "datatypes.h" +#include "fitshandle.h" + +template class Alm; + +/*! \defgroup alm_fitsio_group FITS-based I/O of a_lm */ +/*! \{ */ + +/*! Returns the maximum \a l and \a m multipole moments found in the FITS HDU + pointed to be \a inp in \a lmax and \a mmax. */ +void get_almsize(fitshandle &inp, int &lmax, int &mmax); +/*! Returns the maximum \a l and \a m multipole moments found in the HDU + \a hdunum of file \a filename in \a lmax and \a mmax. */ +void get_almsize(const std::string &filename, int &lmax, int &mmax, + int hdunum=2); +/*! Returns the maximum \a l and \a m multipole moments found in the HDUs + 2, 3 and 4 of file \a filename in \a lmax and \a mmax. */ +void get_almsize_pol(const std::string &filename, int &lmax, int &mmax); + +/*! Reads the a_lm of the FITS binary table pointed to by \a inp into + \a alms. \a alms is reallocated with the parameters \a lmax and \a mmax. + Values not present in the FITS table are set to zero; values outside + the requested (l,m) range are ignored. */ +template void read_Alm_from_fits + (fitshandle &inp, Alm > &alms, int lmax, int mmax); +/*! Opens the FITS file \a filename, jumps to the HDU \a hdunum, then reads + the a_lm from the FITS binary table there into \a alms. \a alms is + reallocated with the parameters \a lmax and \a mmax. + Values not present in the FITS table are set to zero; values outside + the requested \a (l,m) range are ignored. */ +template void read_Alm_from_fits + (const std::string &filename, Alm > &alms, + int lmax, int mmax, int hdunum=2); + +template inline void read_Alm_from_fits + (const std::string &filename, Alm > &almT, + Alm > &almG, Alm > &almC, + int lmax, int mmax, int firsthdu=2) + { + read_Alm_from_fits (filename, almT, lmax, mmax, firsthdu); + read_Alm_from_fits (filename, almG, lmax, mmax, firsthdu+1); + read_Alm_from_fits (filename, almC, lmax, mmax, firsthdu+2); + } + +/*! Inserts a new binary table into \a out, which contains three columns + of type PLANCK_INT32, \a datatype and \a datatype, respectively. + The data in \a alms is written into this table; values outside + the requested (\a lmax, \a mmax) range are omitted. */ +template void write_Alm_to_fits + (fitshandle &out, const Alm > &alms, + int lmax, int mmax, PDT datatype); + +template inline void write_Alm_to_fits + (const std::string &outfile, const Alm > &alms, + int lmax, int mmax, PDT datatype) + { + fitshandle out; + out.create(outfile); + write_Alm_to_fits (out, alms, lmax, mmax, datatype); + } + +template inline void write_Alm_to_fits + (const std::string &outfile, const Alm > &almT, + const Alm > &almG, const Alm > &almC, + int lmax, int mmax, PDT datatype) + { + fitshandle out; + out.create(outfile); + write_Alm_to_fits (out, almT, lmax, mmax, datatype); + write_Alm_to_fits (out, almG, lmax, mmax, datatype); + write_Alm_to_fits (out, almC, lmax, mmax, datatype); + } + +/*! Inserts a new binary table into \a out, which contains three columns + of type PLANCK_INT32, \a datatype and \a datatype, respectively. + The data in \a alms is written into this table; values outside + the requested (\a lmax, \a mmax) range are omitted. Values with an absolute + magnitude of zero are not written. */ +template void write_compressed_Alm_to_fits + (fitshandle &out, const Alm > &alms, + int lmax, int mmax, PDT datatype); + +/*! \} */ + +#endif diff --git a/external/healpix/Healpix_cxx/alm_healpix_tools.cc b/external/healpix/Healpix_cxx/alm_healpix_tools.cc new file mode 100644 index 0000000..2b15c33 --- /dev/null +++ b/external/healpix/Healpix_cxx/alm_healpix_tools.cc @@ -0,0 +1,428 @@ +/* + * This file is part of Healpix_cxx. + * + * Healpix_cxx 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. + * + * Healpix_cxx 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 Healpix_cxx; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * For more information about HEALPix, see http://healpix.jpl.nasa.gov + */ + +/* + * Healpix_cxx is being developed at the Max-Planck-Institut fuer Astrophysik + * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt + * (DLR). + */ + +/* + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Max-Planck-Society + * Author: Martin Reinecke + */ + +#include "alm_healpix_tools.h" +#include "alm.h" +#include "healpix_map.h" +#include "xcomplex.h" +#include "psht_cxx.h" + +using namespace std; + +template void map2alm (const Healpix_Map &map, + Alm > &alm, const arr &weight, bool add_alm) + { + planck_assert (map.Scheme()==RING, "map2alm: map must be in RING scheme"); + planck_assert (int(weight.size())>=2*map.Nside(), + "map2alm: weight array has too few entries"); + + psht_joblist joblist; + joblist.set_weighted_Healpix_geometry (map.Nside(),&weight[0]); + joblist.set_triangular_alm_info (alm.Lmax(), alm.Mmax()); + joblist.add_map2alm(&map[0], &alm(0,0), add_alm); + joblist.execute(); + } + +template void map2alm (const Healpix_Map &map, + Alm > &alm, const arr &weight, + bool add_alm); +template void map2alm (const Healpix_Map &map, + Alm > &alm, const arr &weight, + bool add_alm); + +template void map2alm_iter (const Healpix_Map &map, + Alm > &alm, int num_iter, const arr &weight) + { + map2alm(map,alm,weight); + for (int iter=1; iter<=num_iter; ++iter) + { + Healpix_Map map2(map.Nside(),map.Scheme(),SET_NSIDE); + alm2map(alm,map2); + for (int m=0; m &map, + Alm > &alm, int num_iter, + const arr &weight); +template void map2alm_iter (const Healpix_Map &map, + Alm > &alm, int num_iter, + const arr &weight); + +template void map2alm_iter2 (const Healpix_Map &map, + Alm > &alm, double err_abs, double err_rel) + { + double x_err_abs=1./err_abs, x_err_rel=1./err_rel; + arr wgt(2*map.Nside()); + wgt.fill(1); + Healpix_Map map2(map); + alm.SetToZero(); + while(true) + { + map2alm(map2,alm,wgt,true); + alm2map(alm,map2); + double errmeasure=0; + for (int m=0; m &map, + Alm > &alm, double err_abs, double err_rel); + + +template void map2alm_spin + (const Healpix_Map &map1, const Healpix_Map &map2, + Alm > &alm1, Alm > &alm2, + int spin, const arr &weight, bool add_alm) + { + planck_assert (map1.Scheme()==RING, + "map2alm_spin: maps must be in RING scheme"); + planck_assert (map1.conformable(map2), + "map2alm_spin: maps are not conformable"); + planck_assert (alm1.conformable(alm1), + "map2alm_spin: a_lm are not conformable"); + planck_assert (int(weight.size())>=2*map1.Nside(), + "map2alm_spin: weight array has too few entries"); + + psht_joblist joblist; + joblist.set_weighted_Healpix_geometry (map1.Nside(),&weight[0]); + joblist.set_triangular_alm_info (alm1.Lmax(), alm1.Mmax()); + joblist.add_map2alm_spin(&map1[0], &map2[0], &alm1(0,0), &alm2(0,0), + spin, add_alm); + joblist.execute(); + } + +template void map2alm_spin + (const Healpix_Map &map1, const Healpix_Map &map2, + Alm > &alm1, Alm > &alm2, + int spin, const arr &weight, bool add_alm); +template void map2alm_spin + (const Healpix_Map &map1, const Healpix_Map &map2, + Alm > &alm1, Alm > &alm2, + int spin, const arr &weight, bool add_alm); + +template void map2alm_spin_iter2 + (const Healpix_Map &map1, const Healpix_Map &map2, + Alm > &alm1, Alm > &alm2, + int spin, double err_abs, double err_rel) + { + arr wgt(2*map1.Nside()); + wgt.fill(1); + Healpix_Map map1b(map1), map2b(map2); + alm1.SetToZero(); alm2.SetToZero(); + while(true) + { + map2alm_spin(map1b,map2b,alm1,alm2,spin,wgt,true); + alm2map_spin(alm1,alm2,map1b,map2b,spin); + double errmeasure=0; + for (int m=0; m &map1, const Healpix_Map &map2, + Alm > &alm1, Alm > &alm2, + int spin, double err_abs, double err_rel); + +template void map2alm_pol + (const Healpix_Map &mapT, + const Healpix_Map &mapQ, + const Healpix_Map &mapU, + Alm > &almT, + Alm > &almG, + Alm > &almC, + const arr &weight, + bool add_alm) + { + planck_assert (mapT.Scheme()==RING, + "map2alm_pol: maps must be in RING scheme"); + planck_assert (mapT.conformable(mapQ) && mapT.conformable(mapU), + "map2alm_pol: maps are not conformable"); + planck_assert (almT.conformable(almG) && almT.conformable(almC), + "map2alm_pol: a_lm are not conformable"); + planck_assert (int(weight.size())>=2*mapT.Nside(), + "map2alm_pol: weight array has too few entries"); + + psht_joblist joblist; + joblist.set_weighted_Healpix_geometry (mapT.Nside(),&weight[0]); + joblist.set_triangular_alm_info (almT.Lmax(), almT.Mmax()); + joblist.add_map2alm_pol(&mapT[0], &mapQ[0], &mapU[0], &almT(0,0), + &almG(0,0), &almC(0,0), add_alm); + joblist.execute(); + } + +template void map2alm_pol + (const Healpix_Map &mapT, + const Healpix_Map &mapQ, + const Healpix_Map &mapU, + Alm > &almT, + Alm > &almG, + Alm > &almC, + const arr &weight, + bool add_alm); +template void map2alm_pol + (const Healpix_Map &mapT, + const Healpix_Map &mapQ, + const Healpix_Map &mapU, + Alm > &almT, + Alm > &almG, + Alm > &almC, + const arr &weight, + bool add_alm); + + +template void map2alm_pol_iter + (const Healpix_Map &mapT, + const Healpix_Map &mapQ, + const Healpix_Map &mapU, + Alm > &almT, + Alm > &almG, + Alm > &almC, + int num_iter, + const arr &weight) + { + map2alm_pol(mapT,mapQ,mapU,almT,almG,almC,weight); + for (int iter=1; iter<=num_iter; ++iter) + { + Healpix_Map mapT2(mapT.Nside(),mapT.Scheme(),SET_NSIDE), + mapQ2(mapT.Nside(),mapT.Scheme(),SET_NSIDE), + mapU2(mapT.Nside(),mapT.Scheme(),SET_NSIDE); + + alm2map_pol(almT,almG,almC,mapT2,mapQ2,mapU2); + for (int m=0; m &mapT, + const Healpix_Map &mapQ, + const Healpix_Map &mapU, + Alm > &almT, + Alm > &almG, + Alm > &almC, + int num_iter, + const arr &weight); +template void map2alm_pol_iter + (const Healpix_Map &mapT, + const Healpix_Map &mapQ, + const Healpix_Map &mapU, + Alm > &almT, + Alm > &almG, + Alm > &almC, + int num_iter, + const arr &weight); + +template void map2alm_pol_iter2 + (const Healpix_Map &mapT, + const Healpix_Map &mapQ, + const Healpix_Map &mapU, + Alm > &almT, + Alm > &almG, + Alm > &almC, + double err_abs, double err_rel) + { + arr wgt(2*mapT.Nside()); + wgt.fill(1); + Healpix_Map mapT2(mapT), mapQ2(mapQ), mapU2(mapU); + almT.SetToZero(); almG.SetToZero(); almC.SetToZero(); + while(true) + { + map2alm_pol(mapT2,mapQ2,mapU2,almT,almG,almC,wgt,true); + alm2map_pol(almT,almG,almC,mapT2,mapQ2,mapU2); + double errmeasure=0; + for (int m=0; m &mapT, + const Healpix_Map &mapQ, + const Healpix_Map &mapU, + Alm > &almT, + Alm > &almG, + Alm > &almC, + double err_abs, double err_rel); + + +template void alm2map (const Alm > &alm, + Healpix_Map &map) + { + planck_assert (map.Scheme()==RING, "alm2map: map must be in RING scheme"); + + psht_joblist joblist; + joblist.set_Healpix_geometry (map.Nside()); + joblist.set_triangular_alm_info (alm.Lmax(), alm.Mmax()); + joblist.add_alm2map(&alm(0,0), &map[0], false); + joblist.execute(); + } + +template void alm2map (const Alm > &alm, + Healpix_Map &map); +template void alm2map (const Alm > &alm, + Healpix_Map &map); + +template void alm2map_spin + (const Alm > &alm1, const Alm > &alm2, + Healpix_Map &map1, Healpix_Map &map2, int spin) + { + planck_assert (map1.Scheme()==RING, + "alm2map_spin: maps must be in RING scheme"); + planck_assert (map1.conformable(map2), + "alm2map_spin: maps are not conformable"); + planck_assert (alm1.conformable(alm2), + "alm2map_spin: a_lm are not conformable"); + + psht_joblist joblist; + joblist.set_Healpix_geometry (map1.Nside()); + joblist.set_triangular_alm_info (alm1.Lmax(), alm1.Mmax()); + joblist.add_alm2map_spin(&alm1(0,0), &alm2(0,0), &map1[0], &map2[0], + spin, false); + joblist.execute(); + } + +template void alm2map_spin + (const Alm > &alm1, const Alm > &alm2, + Healpix_Map &map, Healpix_Map &map2, int spin); +template void alm2map_spin + (const Alm > &alm1, const Alm > &alm2, + Healpix_Map &map, Healpix_Map &map2, int spin); + + +template void alm2map_pol + (const Alm > &almT, + const Alm > &almG, + const Alm > &almC, + Healpix_Map &mapT, + Healpix_Map &mapQ, + Healpix_Map &mapU) + { + planck_assert (mapT.Scheme()==RING, + "alm2map_pol: maps must be in RING scheme"); + planck_assert (mapT.conformable(mapQ) && mapT.conformable(mapU), + "alm2map_pol: maps are not conformable"); + planck_assert (almT.conformable(almG) && almT.conformable(almC), + "alm2map_pol: a_lm are not conformable"); + + psht_joblist joblist; + joblist.set_Healpix_geometry (mapT.Nside()); + joblist.set_triangular_alm_info (almT.Lmax(), almT.Mmax()); + joblist.add_alm2map_pol(&almT(0,0), &almG(0,0), &almC(0,0), &mapT[0], + &mapQ[0], &mapU[0], false); + joblist.execute(); + } + +template void alm2map_pol (const Alm > &almT, + const Alm > &almG, + const Alm > &almC, + Healpix_Map &mapT, + Healpix_Map &mapQ, + Healpix_Map &mapU); + +template void alm2map_pol (const Alm > &almT, + const Alm > &almG, + const Alm > &almC, + Healpix_Map &mapT, + Healpix_Map &mapQ, + Healpix_Map &mapU); + + +template void alm2map_der1 + (const Alm > &alm, + Healpix_Map &map, + Healpix_Map &mapdth, + Healpix_Map &mapdph) + { + planck_assert (map.Scheme()==RING, + "alm2map_der1: maps must be in RING scheme"); + planck_assert (map.conformable(mapdth) && map.conformable(mapdph), + "alm2map_der1: maps are not conformable"); + + psht_joblist joblist; + joblist.set_Healpix_geometry (map.Nside()); + joblist.set_triangular_alm_info (alm.Lmax(), alm.Mmax()); + joblist.add_alm2map(&alm(0,0), &map[0], false); + joblist.add_alm2map_der1(&alm(0,0), &mapdth[0], &mapdph[0], false); + joblist.execute(); + } + +template void alm2map_der1 (const Alm > &alm, + Healpix_Map &map, + Healpix_Map &map_dth, + Healpix_Map &map_dph); + +template void alm2map_der1 (const Alm > &alm, + Healpix_Map &map, + Healpix_Map &map_dth, + Healpix_Map &map_dph); diff --git a/external/healpix/Healpix_cxx/alm_healpix_tools.h b/external/healpix/Healpix_cxx/alm_healpix_tools.h new file mode 100644 index 0000000..8d12920 --- /dev/null +++ b/external/healpix/Healpix_cxx/alm_healpix_tools.h @@ -0,0 +1,201 @@ +/* + * This file is part of Healpix_cxx. + * + * Healpix_cxx 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. + * + * Healpix_cxx 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 Healpix_cxx; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * For more information about HEALPix, see http://healpix.jpl.nasa.gov + */ + +/* + * Healpix_cxx is being developed at the Max-Planck-Institut fuer Astrophysik + * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt + * (DLR). + */ + +/*! \file alm_healpix_tools.h + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Max-Planck-Society + * \author Martin Reinecke + */ + +#ifndef HEALPIX_ALM_HEALPIX_TOOLS_H +#define HEALPIX_ALM_HEALPIX_TOOLS_H + +#include "xcomplex.h" +#include "arr.h" + +template class Alm; +template class Healpix_Map; + +/*! \defgroup alm_healpix_group Conversions between a_lm and HEALPix maps */ +/*! \{ */ + +/*! Converts a Healpix map to a set of a_lms. + \param map the input map, which must have RING ordering + \param alm the output a_lms. l_max and m_max of the conversion are + determined from this object. + \param weight array containing the weights for the individual rings of + the map. It must have at least 2*\a map.Nside() entries. + \param add_alm If this is \a true, then the computed a_lm are added + to the values already residing in \a alm. */ +template void map2alm (const Healpix_Map &map, + Alm > &alm, const arr &weight, + bool add_alm=false); + +/*! Converts a Healpix map to a set of a_lms, using an iterative scheme + which is more accurate than plain map2alm(). + \param map the input map, which must have RING ordering. + \param alm the output a_lms. l_max and m_max of the conversion are + determined from this object. + \param num_iter the number of iterations (0 is identical to map2alm()). + \param weight array containing the weights for the individual rings of + the map. It must have at least 2*\a map.Nside() entries. */ +template void map2alm_iter (const Healpix_Map &map, + Alm > &alm, int num_iter, const arr &weight); + +template inline void map2alm_iter (const Healpix_Map &map, + Alm > &alm, int num_iter) + { + arr wgt(2*map.Nside()); + wgt.fill(1); + map2alm_iter(map,alm,num_iter,wgt); + } + +template void map2alm_iter2 (const Healpix_Map &map, + Alm > &alm, double err_abs, double err_rel); + +template void map2alm_spin + (const Healpix_Map &map1, const Healpix_Map &map2, + Alm > &alm1, Alm > &alm2, + int spin, const arr &weight, bool add_alm); + +template void map2alm_spin_iter2 + (const Healpix_Map &map1, const Healpix_Map &map2, + Alm > &alm1, Alm > &alm2, + int spin, double err_abs, double err_rel); + +/*! Converts Healpix maps containing the I, Q and U Stokes parameters + to sets of a_lms. + \param mapT the I-Stokes parameter input map + \param mapQ the Q-Stokes parameter input map + \param mapU the U-Stokes parameter input map + \note All maps must have the same nside, and must be in RING scheme. + \param almT the output temperature a_lms + \param almG the output gradient a_lms + \param almC the output curl a_lms + \note all a_lm sets must have the the same lmax and mmax. + \param weight ring weights for the maps. + \param add_alm If this is \a true, then the computed a_lm are added + to the values already residing in \a alm. + \note The weight array must have at least 2*\a mapT.Nside() entries. */ +template void map2alm_pol + (const Healpix_Map &mapT, + const Healpix_Map &mapQ, + const Healpix_Map &mapU, + Alm > &almT, + Alm > &almG, + Alm > &almC, + const arr &weight, + bool add_alm=false); +/*! Converts Healpix maps containing the I, Q and U Stokes parameters + to sets of a_lms, using an iterative scheme which is more accurate than + plain map2alm_pol(). + \param mapT the I-Stokes parameter input map + \param mapQ the Q-Stokes parameter input map + \param mapU the U-Stokes parameter input map + \note All maps must have the same nside, and must be in RING scheme. + \param almT the output temperature a_lms + \param almG the output gradient a_lms + \param almC the output curl a_lms + \note all a_lm sets must have the the same lmax and mmax. + \param num_iter the number of iterations (0 is identical to map2alm_pol()). + \param weight ring weights for the maps. + \note The weight array must have at least 2*\a mapT.Nside() entries. */ +template void map2alm_pol_iter + (const Healpix_Map &mapT, + const Healpix_Map &mapQ, + const Healpix_Map &mapU, + Alm > &almT, + Alm > &almG, + Alm > &almC, + int num_iter, + const arr &weight); + +template inline void map2alm_pol_iter + (const Healpix_Map &mapT, + const Healpix_Map &mapQ, + const Healpix_Map &mapU, + Alm > &almT, + Alm > &almG, + Alm > &almC, + int num_iter) + { + arr wgt(2*mapT.Nside()); + wgt.fill(1); + map2alm_pol_iter(mapT,mapQ,mapU,almT,almG,almC,num_iter,wgt); + } + +template void map2alm_pol_iter2 + (const Healpix_Map &mapT, + const Healpix_Map &mapQ, + const Healpix_Map &mapU, + Alm > &almT, + Alm > &almG, + Alm > &almC, + double err_abs, double err_rel); + +/*! Converts a a set of a_lm to a HEALPix map. + \param alm the input a_lms. l_max and m_max of the conversion are + determined from this object. + \param map the output map, which must have RING ordering. */ +template void alm2map (const Alm > &alm, + Healpix_Map &map); + +template void alm2map_spin + (const Alm > &alm1, const Alm > &alm2, + Healpix_Map &map1, Healpix_Map &map2, int spin); + +/*! Converts a a set of polarised a_lm to a HEALPix map. + \param almT the input temperature a_lms + \param almG the input gradient a_lms + \param almC the input curl a_lms + \param mapT the I-Stokes parameter output map + \param mapQ the Q-Stokes parameter output map + \param mapU the U-Stokes parameter output map */ +template void alm2map_pol + (const Alm > &almT, + const Alm > &almG, + const Alm > &almC, + Healpix_Map &mapT, + Healpix_Map &mapQ, + Healpix_Map &mapU); + +/*! Converts a a set of a_lm to a HEALPix map and its first derivatives. + \param alm the input a_lms. l_max and m_max of the conversion are + determined from this object. + \param map the output map, which must have RING ordering. + \param mapdth an output map containing \f$d (\mbox{map})/d\vartheta\f$, + which must have RING ordering. + \param mapdph an output map containing + \f$(\sin\vartheta)^{-1}d(\mbox{map})/d\varphi\f$, + which must have RING ordering. */ +template void alm2map_der1 + (const Alm > &alm, + Healpix_Map &map, + Healpix_Map &mapdth, + Healpix_Map &mapdph); + +/*! \} */ + +#endif diff --git a/external/healpix/Healpix_cxx/alm_powspec_tools.cc b/external/healpix/Healpix_cxx/alm_powspec_tools.cc new file mode 100644 index 0000000..cae6ce3 --- /dev/null +++ b/external/healpix/Healpix_cxx/alm_powspec_tools.cc @@ -0,0 +1,450 @@ +/* + * This file is part of Healpix_cxx. + * + * Healpix_cxx 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. + * + * Healpix_cxx 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 Healpix_cxx; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * For more information about HEALPix, see http://healpix.jpl.nasa.gov + */ + +/* + * Healpix_cxx is being developed at the Max-Planck-Institut fuer Astrophysik + * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt + * (DLR). + */ + +/* + * Copyright (C) 2003-2011 Max-Planck-Society + * Author: Martin Reinecke + */ + +#include "alm_powspec_tools.h" +#include "alm.h" +#include "planck_rng.h" +#include "powspec.h" +#include "xcomplex.h" +#include "rotmatrix.h" +#include "openmp_support.h" +#include "wigner.h" +#include "lsconstants.h" + +using namespace std; +template void create_alm + (const PowSpec &powspec, Alm > &alm, planck_rng &rng) + { + int lmax = alm.Lmax(); + int mmax = alm.Mmax(); + const double hsqrt2 = 1/sqrt(2.); + + for (int l=0; l<=lmax; ++l) + { + double rms_tt = sqrt(powspec.tt(l)); + double zeta1_r = rng.rand_gauss(); + alm(l,0) = T(zeta1_r * rms_tt); + for (int m=1; m<=min(l,mmax); ++m) + { + zeta1_r = rng.rand_gauss()*hsqrt2; + double zeta1_i = rng.rand_gauss()*hsqrt2; + alm(l,m).Set (T(zeta1_r*rms_tt), T(zeta1_i*rms_tt)); + } + } + } + +template void create_alm (const PowSpec &powspec, + Alm > &alm, planck_rng &rng); +template void create_alm (const PowSpec &powspec, + Alm > &alm, planck_rng &rng); + + +template void create_alm_pol + (const PowSpec &powspec, + Alm > &almT, + Alm > &almG, + Alm > &almC, + planck_rng &rng) + { + int lmax = almT.Lmax(); + int mmax = almT.Mmax(); + const double hsqrt2 = 1/sqrt(2.); + + for (int l=0; l<=lmax; ++l) + { + double rms_tt=0, rms_g1=0; + if (powspec.tt(l) != 0) + { + rms_tt = sqrt(powspec.tt(l)); + rms_g1 = powspec.tg(l)/rms_tt; + } + + double zeta1_r = rng.rand_gauss(); + almT(l,0) = T(zeta1_r * rms_tt); + almG(l,0) = T(zeta1_r * rms_g1); + for (int m=1; m<=min(l,mmax); ++m) + { + zeta1_r = rng.rand_gauss()*hsqrt2; + double zeta1_i = rng.rand_gauss()*hsqrt2; + almT(l,m).Set (T(zeta1_r*rms_tt), T(zeta1_i*rms_tt)); + almG(l,m).Set (T(zeta1_r*rms_g1), T(zeta1_i*rms_g1)); + } + } + + for (int l=0; l<=lmax; ++l) + { + double rms_g2 = 0; + double rms_cc = 0; + if (powspec.tt(l) != 0) + { + rms_g2 = powspec.gg(l) - (powspec.tg(l)/powspec.tt(l))*powspec.tg(l); + if (rms_g2 <= 0) + { + planck_assert (abs(rms_g2) <= 1e-8*abs(powspec.gg(l)), + "Inconsistent TT, GG and TG spectra at l="+dataToString(l)); + rms_g2 = 0; + } + rms_g2 = sqrt(rms_g2); + rms_cc = sqrt(powspec.cc(l)); + } + almG(l,0) += T(rng.rand_gauss()*rms_g2); + almC(l,0) = T(rng.rand_gauss()*rms_cc); + + for (int m=1; m<=min(l,mmax); ++m) + { + double zeta2_r = rng.rand_gauss()*hsqrt2; + double zeta2_i = rng.rand_gauss()*hsqrt2; + double zeta3_r = rng.rand_gauss()*hsqrt2; + double zeta3_i = rng.rand_gauss()*hsqrt2; + + almG(l,m) += xcomplex (T(zeta2_r*rms_g2),T(zeta2_i*rms_g2)); + almC(l,m).Set (T(zeta3_r*rms_cc),T(zeta3_i*rms_cc)); + } + } + } + +template void create_alm_pol + (const PowSpec &powspec, + Alm > &almT, + Alm > &almG, + Alm > &almC, + planck_rng &rng); +template void create_alm_pol + (const PowSpec &powspec, + Alm > &almT, + Alm > &almG, + Alm > &almC, + planck_rng &rng); + + +template void extract_crosspowspec + (const Alm > &alm1, + const Alm > &alm2,PowSpec &powspec) + { + planck_assert (alm1.conformable(alm2), "a_lm are not conformable"); + arr tt(alm1.Lmax()+1); + for (int l=0; l<=alm1.Lmax(); ++l) + { + tt[l] = alm1(l,0).re*alm2(l,0).re; + int limit = min(l,alm1.Mmax()); + for (int m=1; m<=limit; ++m) + tt[l] += 2 * (alm1(l,m).re*alm2(l,m).re + alm1(l,m).im*alm2(l,m).im); + tt[l] /= (2*l+1); + } + powspec.Set(tt); + } + +template void extract_crosspowspec + (const Alm > &alm1, + const Alm > &alm2, PowSpec &powspec); +template void extract_crosspowspec + (const Alm > &alm1, + const Alm > &alm2, PowSpec &powspec); + + +template void extract_powspec + (const Alm > &alm, PowSpec &powspec) + { extract_crosspowspec (alm,alm,powspec); } + +template void extract_powspec + (const Alm > &alm, PowSpec &powspec); +template void extract_powspec + (const Alm > &alm, PowSpec &powspec); + +namespace { + +template void extract_crosspowspec + (const Alm > &almT1, + const Alm > &almG1, + const Alm > &almC1, + const Alm > &almT2, + const Alm > &almG2, + const Alm > &almC2, + PowSpec &powspec) + { + planck_assert (almT1.conformable(almG1) && almT1.conformable(almC1) && + almT1.conformable(almT2) && almT1.conformable(almG2) && + almT1.conformable(almC2), "a_lm are not conformable"); + + int lmax = almT1.Lmax(); + arr tt(lmax+1), gg(lmax+1), cc(lmax+1), tg(lmax+1), + tc(lmax+1), gc(lmax+1); + for (int l=0; l<=lmax; ++l) + { + tt[l] = almT1(l,0).re*almT2(l,0).re; + gg[l] = almG1(l,0).re*almG2(l,0).re; + cc[l] = almC1(l,0).re*almC2(l,0).re; + tg[l] = almT1(l,0).re*almG2(l,0).re; + tc[l] = almT1(l,0).re*almC2(l,0).re; + gc[l] = almG1(l,0).re*almC2(l,0).re; + int limit = min(l,almT1.Mmax()); + for (int m=1; m<=limit; ++m) + { + tt[l] += 2 * (almT1(l,m).re*almT2(l,m).re + almT1(l,m).im*almT2(l,m).im); + gg[l] += 2 * (almG1(l,m).re*almG2(l,m).re + almG1(l,m).im*almG2(l,m).im); + cc[l] += 2 * (almC1(l,m).re*almC2(l,m).re + almC1(l,m).im*almC2(l,m).im); + tg[l] += 2 * (almT1(l,m).re*almG2(l,m).re + almT1(l,m).im*almG2(l,m).im); + tc[l] += 2 * (almT1(l,m).re*almC2(l,m).re + almT1(l,m).im*almC2(l,m).im); + gc[l] += 2 * (almG1(l,m).re*almC2(l,m).re + almG1(l,m).im*almC2(l,m).im); + } + tt[l] /= (2*l+1); + gg[l] /= (2*l+1); + cc[l] /= (2*l+1); + tg[l] /= (2*l+1); + tc[l] /= (2*l+1); + gc[l] /= (2*l+1); + } + powspec.Set(tt,gg,cc,tg,tc,gc); + } + +} // unnamed namespace + +template void extract_powspec + (const Alm > &almT, + const Alm > &almG, + const Alm > &almC, + PowSpec &powspec) + { extract_crosspowspec(almT,almG,almC,almT,almG,almC,powspec); } + +template void extract_powspec + (const Alm > &almT, + const Alm > &almG, + const Alm > &almC, + PowSpec &powspec); +template void extract_powspec + (const Alm > &almT, + const Alm > &almG, + const Alm > &almC, + PowSpec &powspec); + + +template void smoothWithGauss + (Alm > &alm, double fwhm) + { + int fct = (fwhm>=0) ? 1 : -1; + double sigma = fwhm*fwhm2sigma; + arr gb(alm.Lmax()+1); + for (int l=0; l<=alm.Lmax(); ++l) + gb[l] = exp(-.5*fct*l*(l+1)*sigma*sigma); + alm.ScaleL(gb); + } + +template void smoothWithGauss + (Alm > &alm, double fwhm); +template void smoothWithGauss + (Alm > &alm, double fwhm); + + +template void smoothWithGauss + (Alm > &almT, + Alm > &almG, + Alm > &almC, + double fwhm) + { + int fct = (fwhm>=0) ? 1 : -1; + double sigma = fwhm*fwhm2sigma; + double fact_pol = exp(2*fct*sigma*sigma); + arr gb(almT.Lmax()+1); + for (int l=0; l<=almT.Lmax(); ++l) + gb[l] = exp(-.5*fct*l*(l+1)*sigma*sigma); + almT.ScaleL(gb); + for (int l=0; l<=almT.Lmax(); ++l) + gb[l] *= fact_pol; + almG.ScaleL(gb); almC.ScaleL(gb); + } + +template void smoothWithGauss + (Alm > &almT, + Alm > &almG, + Alm > &almC, + double fwhm); +template void smoothWithGauss + (Alm > &almT, + Alm > &almG, + Alm > &almC, + double fwhm); + +template void rotate_alm (Alm > &alm, + double psi, double theta, double phi) + { + planck_assert (alm.Lmax()==alm.Mmax(), + "rotate_alm: lmax must be equal to mmax"); + int lmax=alm.Lmax(); + arr > exppsi(lmax+1), expphi(lmax+1); + for (int m=0; m<=lmax; ++m) + { + exppsi[m].Set (cos(psi*m),-sin(psi*m)); + expphi[m].Set (cos(phi*m),-sin(phi*m)); + } + + wigner_d_risbo_openmp rec(lmax,theta); + + arr > almtmp(lmax+1); + + for (int l=0; l<=lmax; ++l) + { + const arr2 &d(rec.recurse()); + + for (int m=0; m<=l; ++m) + almtmp[m] = xcomplex(alm(l,0))*d[l][l+m]; + +#pragma omp parallel +{ + int64 lo,hi; + openmp_calc_share(0,l+1,lo,hi); + + bool flip = true; + for (int mm=1; mm<=l; ++mm) + { + xcomplex t1 = xcomplex(alm(l,mm))*exppsi[mm]; + bool flip2 = ((mm+lo)&1) ? true : false; + for (int m=lo; m(almtmp[m]*expphi[m]); + } + } + +template void rotate_alm (Alm > &alm, + double psi, double theta, double phi); +template void rotate_alm (Alm > &alm, + double psi, double theta, double phi); + +template void rotate_alm (Alm > &almT, + Alm > &almG, Alm > &almC, + double psi, double theta, double phi) + { + planck_assert (almT.Lmax()==almT.Mmax(), + "rotate_alm: lmax must be equal to mmax"); + planck_assert (almG.conformable(almT) && almC.conformable(almT), + "rotate_alm: a_lm are not conformable"); + int lmax=almT.Lmax(); + arr > exppsi(lmax+1), expphi(lmax+1); + for (int m=0; m<=lmax; ++m) + { + exppsi[m].Set (cos(psi*m),-sin(psi*m)); + expphi[m].Set (cos(phi*m),-sin(phi*m)); + } + + wigner_d_risbo_openmp rec(lmax,theta); + + arr > almtmpT(lmax+1), almtmpG(lmax+1), almtmpC(lmax+1); + + for (int l=0; l<=lmax; ++l) + { + const arr2 &d(rec.recurse()); + + for (int m=0; m<=l; ++m) + { + almtmpT[m] = xcomplex(almT(l,0))*d[l][m+l]; + almtmpG[m] = xcomplex(almG(l,0))*d[l][m+l]; + almtmpC[m] = xcomplex(almC(l,0))*d[l][m+l]; + } + +#pragma omp parallel +{ + int64 lo,hi; + openmp_calc_share(0,l+1,lo,hi); + + bool flip = true; + for (int mm=1; mm<=l; ++mm) + { + xcomplex t1T = xcomplex(almT(l,mm))*exppsi[mm]; + xcomplex t1G = xcomplex(almG(l,mm))*exppsi[mm]; + xcomplex t1C = xcomplex(almC(l,mm))*exppsi[mm]; + bool flip2 = ((mm+lo)&1) ? true : false; + for (int m=lo; m(almtmpT[m]*expphi[m]); + almG(l,m) = xcomplex(almtmpG[m]*expphi[m]); + almC(l,m) = xcomplex(almtmpC[m]*expphi[m]); + } + } + } + +template void rotate_alm (Alm > &almT, + Alm > &almG, Alm > &almC, + double psi, double theta, double phi); +template void rotate_alm (Alm > &almT, + Alm > &almG, Alm > &almC, + double psi, double theta, double phi); + + +template void rotate_alm (Alm > &alm, + const rotmatrix &mat) + { + double a1, a2, a3; + mat.Extract_CPAC_Euler_Angles (a1, a2, a3); + rotate_alm (alm, a3, a2, a1); + } + +template void rotate_alm (Alm > &alm, const rotmatrix &mat); +template void rotate_alm (Alm > &alm, const rotmatrix &mat); + +template void rotate_alm (Alm > &almT, + Alm > &almG, Alm > &almC, + const rotmatrix &mat) + { + double a1, a2, a3; + mat.Extract_CPAC_Euler_Angles (a1, a2, a3); + rotate_alm (almT, almG, almC, a3, a2, a1); + } + +template void rotate_alm (Alm > &almT, + Alm > &almG, Alm > &almC, + const rotmatrix &mat); +template void rotate_alm (Alm > &almT, + Alm > &almG, Alm > &almC, + const rotmatrix &mat); diff --git a/external/healpix/Healpix_cxx/alm_powspec_tools.h b/external/healpix/Healpix_cxx/alm_powspec_tools.h new file mode 100644 index 0000000..260b68a --- /dev/null +++ b/external/healpix/Healpix_cxx/alm_powspec_tools.h @@ -0,0 +1,125 @@ +/* + * This file is part of Healpix_cxx. + * + * Healpix_cxx 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. + * + * Healpix_cxx 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 Healpix_cxx; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * For more information about HEALPix, see http://healpix.jpl.nasa.gov + */ + +/* + * Healpix_cxx is being developed at the Max-Planck-Institut fuer Astrophysik + * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt + * (DLR). + */ + +/*! \file alm_powspec_tools.h + * Copyright (C) 2003, 2004, 2005 Max-Planck-Society + * \author Martin Reinecke + */ + +#ifndef PLANCK_ALM_POWSPEC_TOOLS_H +#define PLANCK_ALM_POWSPEC_TOOLS_H + +#include "xcomplex.h" + +template class Alm; +class PowSpec; +class planck_rng; +class rotmatrix; + +/*! \defgroup alm_ps_group Conversions between a_lm and power spectra */ +/*! \{ */ + +/*! Creates a Gaussian realisation of the input power spectrum \a powspec, + using the random number generator \a rng, and returns the result + in \a alm. */ +template void create_alm (const PowSpec &powspec, + Alm > &alm, planck_rng &rng); + +/*! Creates a Gaussian realisation of the polarised input power spectrum + \a powspec, using the random number generator \a rng, and returns the + result in \a almT, \a almG and \a almC. */ +template void create_alm_pol + (const PowSpec &powspec, + Alm > &almT, + Alm > &almG, + Alm > &almC, + planck_rng &rng); + +/*! Returns the unpolarised power spectrum of \a alm in \a powspec. */ +template void extract_powspec + (const Alm > &alm, PowSpec &powspec); +/*! Returns the cross power spectrum of \a alm1 and \a alm2 in \a powspec. */ +template void extract_crosspowspec + (const Alm > &alm1, + const Alm > &alm2, PowSpec &powspec); +/*! Returns the polarised power spectrum of \a almT, \a almG and \a almC + in \a powspec. */ +template void extract_powspec + (const Alm > &almT, + const Alm > &almG, + const Alm > &almC, + PowSpec &powspec); + +/*! \} */ + +/*! Applies a convolution with a Gaussian beam with an FWHM of + \a fwhm (in radian) to \a alm. + \note If \a fwhm<0, a deconvolution with \a -fwhm is performed. + \relates Alm */ +template void smoothWithGauss + (Alm > &alm, double fwhm); +/*! Applies a convolution with a Gaussian beam with an FWHM of + \a fwhm (in radian) to \a almT, \a almG and \a almC. + \note If \a fwhm<0, a deconvolution with \a -fwhm is performed. + \relates Alm */ +template void smoothWithGauss + (Alm > &almT, + Alm > &almG, + Alm > &almC, + double fwhm); + +/*! Rotates \a alm through the Euler angles \a psi, \a theta and \a phi. + The Euler angle convention is right handed, rotations are active. + - \a psi is the first rotation about the z-axis (vertical) + - then \a theta about the ORIGINAL (unrotated) y-axis + - then \a phi about the ORIGINAL (unrotated) z-axis (vertical) + \relates Alm */ +template void rotate_alm (Alm > &alm, + double psi, double theta, double phi); + +/*! Rotates \a almT, \a almG and \a almC through the Euler angles + \a psi, \a theta and \a phi. + The Euler angle convention is right handed, rotations are active. + - \a psi is the first rotation about the z-axis (vertical) + - then \a theta about the ORIGINAL (unrotated) y-axis + - then \a phi about the ORIGINAL (unrotated) z-axis (vertical) + \relates Alm */ +template void rotate_alm (Alm > &almT, + Alm > &almG, Alm > &almC, + double psi, double theta, double phi); + +/*! Rotates \a alm through the rotation matrix \a mat. + \relates Alm */ +template void rotate_alm (Alm > &alm, + const rotmatrix &mat); + +/*! Rotates \a almT, \a almG and \a almC through the rotation matrix \a mat. + \relates Alm */ +template void rotate_alm (Alm > &almT, + Alm > &almG, Alm > &almC, + const rotmatrix &mat); + +#endif diff --git a/external/healpix/Healpix_cxx/anafast_cxx.cc b/external/healpix/Healpix_cxx/anafast_cxx.cc new file mode 100644 index 0000000..eddb097 --- /dev/null +++ b/external/healpix/Healpix_cxx/anafast_cxx.cc @@ -0,0 +1,9 @@ +#include "levels_facilities.h" +#include "error_handling.h" + +int main (int argc, const char **argv) + { + PLANCK_DIAGNOSIS_BEGIN + anafast_cxx_module (argc, argv); + PLANCK_DIAGNOSIS_END + } diff --git a/external/healpix/Healpix_cxx/anafast_cxx.par.txt b/external/healpix/Healpix_cxx/anafast_cxx.par.txt new file mode 100644 index 0000000..03defa5 --- /dev/null +++ b/external/healpix/Healpix_cxx/anafast_cxx.par.txt @@ -0,0 +1,41 @@ +Parameters read by anafast_cxx: + +nlmax (integer): + maximum order of l + +nmmax (integer): + maximum order of m (must not be larger than nlmax, default=nlmax) + +infile (string): + input file containing the Healpix map + +outfile (string, default=""): + output file name for power spectrum; if empty, no spectrum is written + +outfile_alms (string, default=""): + output file name for the a_lm; if empty, no a_lm are written + +polarisation (bool): + if false, only the intensity a_lm are generated, + if true, a_lm for T, G and C component are generated + +weighted (bool, default=false): + if true, weighted quadrature is used + +if (weighted) + healpix_data (string): + directory containing the Healpix data files +endif + +iter_order (integer, default=0) + number of iterations for the analysis (0: standard analysis) + +double_precision (bool, default=false): + if false, maps and a_lm are read/written in single precision, + otherwise in double precision. + +if (polarisation==true && outfile!="") + full_powerspectrum (bool, default=false): + if true, write a 6-column power spectrum; + if false, write a 4-column power spectrum. +endif diff --git a/external/healpix/Healpix_cxx/anafast_cxx_module.cc b/external/healpix/Healpix_cxx/anafast_cxx_module.cc new file mode 100644 index 0000000..cf45d23 --- /dev/null +++ b/external/healpix/Healpix_cxx/anafast_cxx_module.cc @@ -0,0 +1,129 @@ +/* + * This file is part of Healpix_cxx. + * + * Healpix_cxx 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. + * + * Healpix_cxx 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 Healpix_cxx; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * For more information about HEALPix, see http://healpix.jpl.nasa.gov + */ + +/* + * Healpix_cxx is being developed at the Max-Planck-Institut fuer Astrophysik + * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt + * (DLR). + */ + +/* + * Copyright (C) 2003-2010 Max-Planck-Society + * Author: Martin Reinecke + */ + +#include "xcomplex.h" +#include "cxxutils.h" +#include "paramfile.h" +#include "healpix_data_io.h" +#include "alm.h" +#include "alm_fitsio.h" +#include "healpix_map.h" +#include "healpix_map_fitsio.h" +#include "powspec.h" +#include "powspec_fitsio.h" +#include "alm_healpix_tools.h" +#include "alm_powspec_tools.h" +#include "fitshandle.h" +#include "levels_facilities.h" +#include "lsconstants.h" + +using namespace std; + +namespace { + +template void anafast_cxx (paramfile ¶ms) + { + int nlmax = params.template find("nlmax"); + int nmmax = params.template find("nmmax",nlmax); + string infile = params.template find("infile"); + string outfile = params.template find("outfile",""); + string outfile_alms = params.template find("outfile_alms",""); + planck_assert ((outfile!="") || (outfile_alms!=""), + "no output specified, nothing done"); + bool polarisation = params.template find("polarisation"); + int num_iter = params.template find("iter_order",0); + + if (!polarisation) + { + Healpix_Map map; + read_Healpix_map_from_fits(infile,map,1,2); + arr weight; + get_ring_weights (params,map.Nside(),weight); + + Alm > alm(nlmax,nmmax); + double avg=map.average(); + map.Add(T(-avg)); + if (map.Scheme()==NEST) map.swap_scheme(); + map2alm_iter(map,alm,num_iter,weight); + + alm(0,0) += T(avg*sqrt(fourpi)); + + if (outfile!="") + { + PowSpec powspec; + extract_powspec (alm,powspec); + write_powspec_to_fits (outfile,powspec,1); + } + if (outfile_alms!="") + write_Alm_to_fits(outfile_alms,alm,nlmax,nmmax,planckType()); + } + else + { + Healpix_Map mapT, mapQ, mapU; + read_Healpix_map_from_fits(infile,mapT,mapQ,mapU,2); + arr weight; + get_ring_weights (params,mapT.Nside(),weight); + + Alm > almT(nlmax,nmmax), almG(nlmax,nmmax), almC(nlmax,nmmax); + double avg=mapT.average(); + mapT.Add(T(-avg)); + if (mapT.Scheme()==NEST) mapT.swap_scheme(); + if (mapQ.Scheme()==NEST) mapQ.swap_scheme(); + if (mapU.Scheme()==NEST) mapU.swap_scheme(); + map2alm_pol_iter + (mapT,mapQ,mapU,almT,almG,almC,num_iter,weight); + + almT(0,0) += T(avg*sqrt(fourpi)); + + if (outfile!="") + { + PowSpec powspec; + extract_powspec (almT,almG,almC,powspec); + params.template find("full_powerspectrum",false) ? + write_powspec_to_fits (outfile,powspec,6) : + write_powspec_to_fits (outfile,powspec,4); + } + if (outfile_alms!="") + write_Alm_to_fits (outfile_alms,almT,almG,almC,nlmax,nmmax,planckType()); + } + } + +} // unamed namespace + +int anafast_cxx_module (int argc, const char **argv) + { + module_startup ("anafast_cxx", argc, argv, 2, ""); + paramfile params (argv[1]); + + bool dp = params.find ("double_precision",false); + dp ? anafast_cxx(params) : anafast_cxx(params); + return 0; + } diff --git a/external/healpix/Healpix_cxx/calc_powspec.cc b/external/healpix/Healpix_cxx/calc_powspec.cc new file mode 100644 index 0000000..54c3409 --- /dev/null +++ b/external/healpix/Healpix_cxx/calc_powspec.cc @@ -0,0 +1,9 @@ +#include "levels_facilities.h" +#include "error_handling.h" + +int main (int argc, const char **argv) + { + PLANCK_DIAGNOSIS_BEGIN + calc_powspec_module (argc, argv); + PLANCK_DIAGNOSIS_END + } diff --git a/external/healpix/Healpix_cxx/calc_powspec_module.cc b/external/healpix/Healpix_cxx/calc_powspec_module.cc new file mode 100644 index 0000000..ba5b8bb --- /dev/null +++ b/external/healpix/Healpix_cxx/calc_powspec_module.cc @@ -0,0 +1,73 @@ +/* + * This file is part of Healpix_cxx. + * + * Healpix_cxx 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. + * + * Healpix_cxx 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 Healpix_cxx; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * For more information about HEALPix, see http://healpix.jpl.nasa.gov + */ + +/* + * Healpix_cxx 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 + */ + +#include "fitshandle.h" +#include "alm.h" +#include "alm_fitsio.h" +#include "powspec.h" +#include "powspec_fitsio.h" +#include "alm_powspec_tools.h" +#include "levels_facilities.h" + +using namespace std; + +int calc_powspec_module (int argc, const char **argv) + { + announce ("calc_powspec"); + planck_assert (argc==3||argc==4, + "usage: calc_powspec [] "); + + if (argc==3) + { + int lmax,mmax; + get_almsize(argv[1],lmax,mmax,2); + Alm > alm; + read_Alm_from_fits (argv[1],alm,lmax,mmax,2); + PowSpec powspec; + extract_powspec (alm,powspec); + write_powspec_to_fits (argv[2],powspec,1); + } + else + { + int lmax,mmax; + get_almsize(argv[1],lmax,mmax,2); + Alm > alm1; + read_Alm_from_fits (argv[1],alm1,lmax,mmax,2); + get_almsize(argv[2],lmax,mmax,2); + Alm > alm2; + read_Alm_from_fits (argv[2],alm2,lmax,mmax,2); + PowSpec powspec; + extract_crosspowspec (alm1,alm2,powspec); + write_powspec_to_fits (argv[3],powspec,1); + } + + return 0; + } diff --git a/external/healpix/Healpix_cxx/healpix_base.cc b/external/healpix/Healpix_cxx/healpix_base.cc new file mode 100644 index 0000000..a93ad46 --- /dev/null +++ b/external/healpix/Healpix_cxx/healpix_base.cc @@ -0,0 +1,798 @@ +/* + * This file is part of Healpix_cxx. + * + * Healpix_cxx 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. + * + * Healpix_cxx 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 Healpix_cxx; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * For more information about HEALPix, see http://healpix.jpl.nasa.gov + */ + +/* + * Healpix_cxx is being developed at the Max-Planck-Institut fuer Astrophysik + * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt + * (DLR). + */ + +/* + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Max-Planck-Society + * Author: Martin Reinecke + */ + +#include "healpix_base.h" +#include "cxxutils.h" +#include "pointing.h" +#include "arr.h" +#include "geom_utils.h" +#include "lsconstants.h" + +using namespace std; + +short Healpix_Base::ctab[]; +short Healpix_Base::utab[]; + +const nside_dummy SET_NSIDE=nside_dummy(); + +Healpix_Ordering_Scheme string2HealpixScheme (const string &inp) + { + string tmp=trim(inp); + if (equal_nocase(tmp,"RING")) return RING; + if (equal_nocase(tmp,"NESTED")) return NEST; + planck_fail ("bad Healpix ordering scheme '"+tmp+ + "': expected 'RING' or 'NESTED'"); + } + +Healpix_Base::Tablefiller::Tablefiller() + { + for (int m=0; m<0x100; ++m) + { + ctab[m] = short( + (m&0x1 ) | ((m&0x2 ) << 7) | ((m&0x4 ) >> 1) | ((m&0x8 ) << 6) + | ((m&0x10) >> 2) | ((m&0x20) << 5) | ((m&0x40) >> 3) | ((m&0x80) << 4)); + utab[m] = short( + (m&0x1 ) | ((m&0x2 ) << 1) | ((m&0x4 ) << 2) | ((m&0x8 ) << 3) + | ((m&0x10) << 4) | ((m&0x20) << 5) | ((m&0x40) << 6) | ((m&0x80) << 7)); + } + } + +Healpix_Base::Tablefiller Healpix_Base::Filler; + +const int Healpix_Base::jrll[] = { 2,2,2,2,3,3,3,3,4,4,4,4 }; +const int Healpix_Base::jpll[] = { 1,3,5,7,0,2,4,6,1,3,5,7 }; + +int Healpix_Base::npix2nside (int npix) + { + int res=isqrt(npix/12); + planck_assert (npix==res*res*12, "npix2nside: invalid argument"); + return res; + } + +int Healpix_Base::ring_above (double z) const + { + double az=abs(z); + if (az>twothird) // polar caps + { + int iring = int(nside_*sqrt(3*(1-az))); + return (z>0) ? iring : 4*nside_-iring-1; + } + else // ----- equatorial region --------- + return int(nside_*(2-1.5*z)); + } + +void Healpix_Base::in_ring(int iz, double phi0, double dphi, + vector &listir) const + { + int nr, ir, ipix1; + double shift=0.5; + + if (iz(3*nside_)) // south pole + { + ir = 4*nside_ - iz; + nr = ir*4; + ipix1 = npix_ - 2*ir*(ir+1); // lowest pixel number in the ring + } + else // equatorial region + { + ir = iz - nside_ + 1; // within {1, 2*nside + 1} + nr = nside_*4; + if ((ir&1)==0) shift = 0; + ipix1 = ncap_ + (ir-1)*nr; // lowest pixel number in the ring + } + + int ipix2 = ipix1 + nr - 1; // highest pixel number in the ring + + // ----------- constructs the pixel list -------------- + if (dphi > (pi-1e-7)) + for (int i=ipix1; i<=ipix2; ++i) listir.push_back(i); + else + { + int ip_lo = ifloor(nr*inv_twopi*(phi0-dphi) - shift)+1; + int ip_hi = ifloor(nr*inv_twopi*(phi0+dphi) - shift); + int pixnum = ip_lo+ipix1; + if (pixnumipix2) pixnum -= nr; + listir.push_back(pixnum); + } + } + } + +void Healpix_Base::nest2xyf (int pix, int &ix, int &iy, int &face_num) const + { + face_num = pix>>(2*order_); + pix &= (npface_-1); + int raw = (pix&0x5555) | ((pix&0x55550000)>>15); + ix = ctab[raw&0xff] | (ctab[raw>>8]<<4); + pix >>= 1; + raw = (pix&0x5555) | ((pix&0x55550000)>>15); + iy = ctab[raw&0xff] | (ctab[raw>>8]<<4); + } + +int Healpix_Base::xyf2nest (int ix, int iy, int face_num) const + { + return (face_num<<(2*order_)) + + (utab[ix&0xff] | (utab[ix>>8]<<16) + | (utab[iy&0xff]<<1) | (utab[iy>>8]<<17)); + } + +void Healpix_Base::ring2xyf (int pix, int &ix, int &iy, int &face_num) const + { + int iring, iphi, kshift, nr; + + int nl2 = 2*nside_; + + if (pix=(2*iring)) + { + face_num=2; + tmp-=2*iring; + } + if (tmp>=iring) ++face_num; + } + else if (pix<(npix_-ncap_)) // Equatorial region + { + int ip = pix - ncap_; + if (order_>=0) + { + iring = (ip>>(order_+2)) + nside_; // counted from North pole + iphi = (ip&(4*nside_-1)) + 1; + } + else + { + iring = (ip/(4*nside_)) + nside_; // counted from North pole + iphi = (ip%(4*nside_)) + 1; + } + kshift = (iring+nside_)&1; + nr = nside_; + unsigned int ire = iring-nside_+1; + unsigned int irm = nl2+2-ire; + int ifm, ifp; + if (order_>=0) + { + ifm = (iphi - ire/2 + nside_ -1) >> order_; + ifp = (iphi - irm/2 + nside_ -1) >> order_; + } + else + { + ifm = (iphi - ire/2 + nside_ -1) / nside_; + ifp = (iphi - irm/2 + nside_ -1) / nside_; + } + if (ifp == ifm) // faces 4 to 7 + face_num = (ifp==4) ? 4 : ifp+4; + else if (ifp=(2*nr)) + { + face_num=10; + tmp-=2*nr; + } + if (tmp>=nr) ++face_num; + } + + int irt = iring - (jrll[face_num]*nside_) + 1; + int ipt = 2*iphi- jpll[face_num]*nr - kshift -1; + if (ipt>=nl2) ipt-=8*nside_; + + ix = (ipt-irt) >>1; + iy =(-(ipt+irt))>>1; + } + +int Healpix_Base::xyf2ring (int ix, int iy, int face_num) const + { + int nl4 = 4*nside_; + int jr = (jrll[face_num]*nside_) - ix - iy - 1; + + int nr, kshift, n_before; + if (jr 3*nside_) + { + nr = nl4-jr; + n_before = npix_ - 2*(nr+1)*nr; + kshift = 0; + } + else + { + nr = nside_; + n_before = ncap_ + (jr-nside_)*nl4; + kshift = (jr-nside_)&1; + } + + int jp = (jpll[face_num]*nr + ix - iy + 1 + kshift) / 2; + if (jp>nl4) + jp-=nl4; + else + if (jp<1) jp+=nl4; + + return n_before + jp - 1; + } + +double Healpix_Base::ring2z (int ring) const + { + if (ring=0, "nest2ring: need hierarchical map"); + int ix, iy, face_num; + nest2xyf (pix, ix, iy, face_num); + return xyf2ring (ix, iy, face_num); + } + +int Healpix_Base::ring2nest (int pix) const + { + planck_assert(order_>=0, "ring2nest: need hierarchical map"); + int ix, iy, face_num; + ring2xyf (pix, ix, iy, face_num); + return xyf2nest (ix, iy, face_num); + } + +int Healpix_Base::nest2peano (int pix) const + { + static const uint8 subpix[8][4] = { + { 0, 1, 3, 2 }, { 3, 0, 2, 1 }, { 2, 3, 1, 0 }, { 1, 2, 0, 3 }, + { 0, 3, 1, 2 }, { 1, 0, 2, 3 }, { 2, 1, 3, 0 }, { 3, 2, 0, 1 } }; + static const uint8 subpath[8][4] = { + { 4, 0, 6, 0 }, { 7, 5, 1, 1 }, { 2, 4, 2, 6 }, { 3, 3, 7, 5 }, + { 0, 2, 4, 4 }, { 5, 1, 5, 3 }, { 6, 6, 0, 2 }, { 1, 7, 3, 7 } }; + static const uint8 face2path[12] = { + 2, 5, 2, 5, 3, 6, 3, 6, 2, 3, 2, 3 }; + static const uint8 face2peanoface[12] = { + 0, 5, 6, 11, 10, 1, 4, 7, 2, 3, 8, 9 }; + + int face = pix>>(2*order_); + uint8 path = face2path[face]; + int result = 0; + + for (int shift=2*order_-2; shift>=0; shift-=2) + { + uint8 spix = uint8((pix>>shift) & 0x3); + result <<= 2; + result |= subpix[path][spix]; + path=subpath[path][spix]; + } + + return result + (int(face2peanoface[face])<<(2*order_)); + } + +int Healpix_Base::peano2nest (int pix) const + { + static const uint8 subpix[8][4] = { + { 0, 1, 3, 2 }, { 1, 3, 2, 0 }, { 3, 2, 0, 1 }, { 2, 0, 1, 3 }, + { 0, 2, 3, 1 }, { 1, 0, 2, 3 }, { 3, 1, 0, 2 }, { 2, 3, 1, 0 } }; + static const uint8 subpath[8][4] = { + { 4, 0, 0, 6 }, { 5, 1, 1, 7 }, { 6, 2, 2, 4 }, { 7, 3, 3, 5 }, + { 0, 4, 4, 2 }, { 1, 5, 5, 3 }, { 2, 6, 6, 0 }, { 3, 7, 7, 1 } }; + static const uint8 face2path[12] = { + 2, 6, 2, 3, 3, 5, 2, 6, 2, 3, 3, 5 }; + static const uint8 peanoface2face[12] = { + 0, 5, 8, 9, 6, 1, 2, 7, 10, 11, 4, 3 }; + + int face = pix>>(2*order_); + uint8 path = face2path[face]; + int result = 0; + + for (int shift=2*order_-2; shift>=0; shift-=2) + { + uint8 spix = uint8((pix>>shift) & 0x3); + result <<= 2; + result |= subpix[path][spix]; + path=subpath[path][spix]; + } + + return result + (int(peanoface2face[face])<<(2*order_)); + } + +int Healpix_Base::ang2pix_z_phi (double z, double phi) const + { + double za = abs(z); + double tt = fmodulo(phi,twopi) * inv_halfpi; // in [0,4) + + if (scheme_==RING) + { + if (za<=twothird) // Equatorial region + { + double temp1 = nside_*(0.5+tt); + double temp2 = nside_*z*0.75; + int jp = int(temp1-temp2); // index of ascending edge line + int jm = int(temp1+temp2); // index of descending edge line + + // ring number counted from z=2/3 + int ir = nside_ + 1 + jp - jm; // in {1,2n+1} + int kshift = 1-(ir&1); // kshift=1 if ir even, 0 otherwise + + int ip = (jp+jm-nside_+kshift+1)/2; // in {0,4n-1} + ip = imodulo(ip,4*nside_); + + return ncap_ + (ir-1)*4*nside_ + ip; + } + else // North & South polar caps + { + double tp = tt-int(tt); + double tmp = nside_*sqrt(3*(1-za)); + + int jp = int(tp*tmp); // increasing edge line index + int jm = int((1.0-tp)*tmp); // decreasing edge line index + + int ir = jp+jm+1; // ring number counted from the closest pole + int ip = int(tt*ir); // in {0,4*ir-1} + ip = imodulo(ip,4*ir); + + if (z>0) + return 2*ir*(ir-1) + ip; + else + return npix_ - 2*ir*(ir+1) + ip; + } + } + else // scheme_ == NEST + { + int face_num, ix, iy; + + if (za<=twothird) // Equatorial region + { + double temp1 = nside_*(0.5+tt); + double temp2 = nside_*(z*0.75); + int jp = int(temp1-temp2); // index of ascending edge line + int jm = int(temp1+temp2); // index of descending edge line + int ifp = jp >> order_; // in {0,4} + int ifm = jm >> order_; + if (ifp == ifm) // faces 4 to 7 + face_num = (ifp==4) ? 4: ifp+4; + else if (ifp < ifm) // (half-)faces 0 to 3 + face_num = ifp; + else // (half-)faces 8 to 11 + face_num = ifm + 8; + + ix = jm & (nside_-1); + iy = nside_ - (jp & (nside_-1)) - 1; + } + else // polar region, za > 2/3 + { + int ntt = int(tt); + if (ntt>=4) ntt=3; + double tp = tt-ntt; + double tmp = nside_*sqrt(3*(1-za)); + + int jp = int(tp*tmp); // increasing edge line index + int jm = int((1.0-tp)*tmp); // decreasing edge line index + if (jp>=nside_) jp = nside_-1; // for points too close to the boundary + if (jm>=nside_) jm = nside_-1; + if (z >= 0) + { + face_num = ntt; // in {0,3} + ix = nside_ - jm - 1; + iy = nside_ - jp - 1; + } + else + { + face_num = ntt + 8; // in {8,11} + ix = jp; + iy = jm; + } + } + + return xyf2nest(ix,iy,face_num); + } + } + +void Healpix_Base::pix2ang_z_phi (int pix, double &z, double &phi) const + { + if (scheme_==RING) + { + if (pix 3*nside_) + { + nr = nl4-jr; + z = nr*nr*fact2_ - 1; + kshift = 0; + } + else + { + nr = nside_; + z = (2*nside_-jr)*fact1_; + kshift = (jr-nside_)&1; + } + + int jp = (jpll[face_num]*nr + ix -iy + 1 + kshift) / 2; + if (jp>nl4) jp-=nl4; + if (jp<1) jp+=nl4; + + phi = (jp-(kshift+1)*0.5)*(halfpi/nr); + } + } + +void Healpix_Base::query_disc (const pointing &ptg, double radius, + vector& listpix) const + { + listpix.clear(); + + double dth1 = fact2_; + double dth2 = fact1_; + double cosang = cos(radius); + + double z0 = cos(ptg.theta); + double xa = 1./sqrt((1-z0)*(1+z0)); + + double rlat1 = ptg.theta - radius; + double zmax = cos(rlat1); + int irmin = ring_above (zmax)+1; + + if (rlat1<=0) // north pole in the disc + for (int m=1; m=0, "error in query_disc()"); + double dphi=atan2(sqrt(ysq),x); + in_ring (iz, ptg.phi, dphi, listpix); + } + + if (rlat2>=pi) // south pole in the disc + for (int m=irmax+1; m<(4*nside_); ++m) // rings completely in the disc + in_ring (m, 0, pi, listpix); + + if (scheme_==NEST) + for (tsize m=0; m2*nside_) ? 4*nside_-ring : ring; + if (northring < nside_) + { + double tmp = northring*northring*fact2_; + costheta = 1 - tmp; + sintheta = sqrt(tmp*(2-tmp)); + ringpix = 4*northring; + shifted = true; + startpix = 2*northring*(northring-1); + } + else + { + costheta = (2*nside_-northring)*fact1_; + sintheta = sqrt((1+costheta)*(1-costheta)); + ringpix = 4*nside_; + shifted = ((northring-nside_) & 1) == 0; + startpix = ncap_ + (northring-nside_)*ringpix; + } + if (northring != ring) // southern hemisphere + { + costheta = -costheta; + startpix = npix_ - startpix - ringpix; + } + } + +void Healpix_Base::query_disc_inclusive (const pointing &dir, double radius, + vector &listpix) const + { query_disc (dir,radius+1.362*pi/(4*nside_),listpix); } + +void Healpix_Base::neighbors (int pix, fix_arr &result) const + { + static const int xoffset[] = { -1,-1, 0, 1, 1, 1, 0,-1 }; + static const int yoffset[] = { 0, 1, 1, 1, 0,-1,-1,-1 }; + static const int facearray[][12] = + { { 8, 9,10,11,-1,-1,-1,-1,10,11, 8, 9 }, // S + { 5, 6, 7, 4, 8, 9,10,11, 9,10,11, 8 }, // SE + { -1,-1,-1,-1, 5, 6, 7, 4,-1,-1,-1,-1 }, // E + { 4, 5, 6, 7,11, 8, 9,10,11, 8, 9,10 }, // SW + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }, // center + { 1, 2, 3, 0, 0, 1, 2, 3, 5, 6, 7, 4 }, // NE + { -1,-1,-1,-1, 7, 4, 5, 6,-1,-1,-1,-1 }, // W + { 3, 0, 1, 2, 3, 0, 1, 2, 4, 5, 6, 7 }, // NW + { 2, 3, 0, 1,-1,-1,-1,-1, 0, 1, 2, 3 } }; // N + static const int swaparray[][12] = + { { 0,0,0,0,0,0,0,0,3,3,3,3 }, // S + { 0,0,0,0,0,0,0,0,6,6,6,6 }, // SE + { 0,0,0,0,0,0,0,0,0,0,0,0 }, // E + { 0,0,0,0,0,0,0,0,5,5,5,5 }, // SW + { 0,0,0,0,0,0,0,0,0,0,0,0 }, // center + { 5,5,5,5,0,0,0,0,0,0,0,0 }, // NE + { 0,0,0,0,0,0,0,0,0,0,0,0 }, // W + { 6,6,6,6,0,0,0,0,0,0,0,0 }, // NW + { 3,3,3,3,0,0,0,0,0,0,0,0 } }; // N + + int ix, iy, face_num; + (scheme_==RING) ? + ring2xyf(pix,ix,iy,face_num) : nest2xyf(pix,ix,iy,face_num); + + const int nsm1 = nside_-1; + if ((ix>0)&&(ix0)&&(iy=nside_) + { x-=nside_; nbnum+=1; } + if (y<0) + { y+=nside_; nbnum-=3; } + else if (y>=nside_) + { y-=nside_; nbnum+=3; } + + int f = facearray[nbnum][face_num]; + if (f>=0) + { + if (swaparray[nbnum][face_num]&1) x=nside_-x-1; + if (swaparray[nbnum][face_num]&2) y=nside_-y-1; + if (swaparray[nbnum][face_num]&4) std::swap(x,y); + result[i] = (scheme_==RING) ? xyf2ring(x,y,f) : xyf2nest(x,y,f); + } + else + result[i] = -1; + } + } + } + +void Healpix_Base::get_ring_info2 (int ring, int &startpix, int &ringpix, + double &theta, bool &shifted) const + { + int northring = (ring>2*nside_) ? 4*nside_-ring : ring; + if (northring < nside_) + { + double tmp = northring*northring*fact2_; + double costheta = 1 - tmp; + double sintheta = sqrt(tmp*(2-tmp)); + theta = atan2(sintheta,costheta); + ringpix = 4*northring; + shifted = true; + startpix = 2*northring*(northring-1); + } + else + { + theta = acos((2*nside_-northring)*fact1_); + ringpix = 4*nside_; + shifted = ((northring-nside_) & 1) == 0; + startpix = ncap_ + (northring-nside_)*ringpix; + } + if (northring != ring) // southern hemisphere + { + theta = pi-theta; + startpix = npix_ - startpix - ringpix; + } + } + +void Healpix_Base::get_interpol (const pointing &ptg, fix_arr &pix, + fix_arr &wgt) const + { + double z = cos (ptg.theta); + int ir1 = ring_above(z); + int ir2 = ir1+1; + double theta1, theta2, w1, tmp, dphi; + int sp,nr; + bool shift; + int i1,i2; + if (ir1>0) + { + get_ring_info2 (ir1, sp, nr, theta1, shift); + dphi = twopi/nr; + tmp = (ptg.phi/dphi - .5*shift); + i1 = (tmp<0) ? int(tmp)-1 : int(tmp); + w1 = (ptg.phi-(i1+.5*shift)*dphi)/dphi; + i2 = i1+1; + if (i1<0) i1 +=nr; + if (i2>=nr) i2 -=nr; + pix[0] = sp+i1; pix[1] = sp+i2; + wgt[0] = 1-w1; wgt[1] = w1; + } + if (ir2<(4*nside_)) + { + get_ring_info2 (ir2, sp, nr, theta2, shift); + dphi = twopi/nr; + tmp = (ptg.phi/dphi - .5*shift); + i1 = (tmp<0) ? int(tmp)-1 : int(tmp); + w1 = (ptg.phi-(i1+.5*shift)*dphi)/dphi; + i2 = i1+1; + if (i1<0) i1 +=nr; + if (i2>=nr) i2 -=nr; + pix[2] = sp+i1; pix[3] = sp+i2; + wgt[2] = 1-w1; wgt[3] = w1; + } + + if (ir1==0) + { + double wtheta = ptg.theta/theta2; + wgt[2] *= wtheta; wgt[3] *= wtheta; + double fac = (1-wtheta)*0.25; + wgt[0] = fac; wgt[1] = fac; wgt[2] += fac; wgt[3] +=fac; + pix[0] = (pix[2]+2)%4; + pix[1] = (pix[3]+2)%4; + } + else if (ir2==4*nside_) + { + double wtheta = (ptg.theta-theta1)/(pi-theta1); + wgt[0] *= (1-wtheta); wgt[1] *= (1-wtheta); + double fac = wtheta*0.25; + wgt[0] += fac; wgt[1] += fac; wgt[2] = fac; wgt[3] =fac; + pix[2] = ((pix[0]+2)&3)+npix_-4; + pix[3] = ((pix[1]+2)&3)+npix_-4; + } + else + { + double wtheta = (ptg.theta-theta1)/(theta2-theta1); + wgt[0] *= (1-wtheta); wgt[1] *= (1-wtheta); + wgt[2] *= wtheta; wgt[3] *= wtheta; + } + + if (scheme_==NEST) + for (tsize m=0; m +#include "cxxutils.h" +#include "pointing.h" +#include "arr.h" + +/*! The two possible ordering schemes of a HEALPix map. */ +enum Healpix_Ordering_Scheme { RING, /*!< RING scheme */ + NEST /*!< NESTED scheme */ + }; + +Healpix_Ordering_Scheme string2HealpixScheme (const std::string &inp); + +class nside_dummy {}; +extern const nside_dummy SET_NSIDE; + +/*! Functionality related to the HEALPix pixelisation. */ +class Healpix_Base + { + protected: + enum { order_max=13 }; + + class Tablefiller + { + public: + Tablefiller(); + }; + static Tablefiller Filler; + friend class Tablefiller; + + static short ctab[0x100], utab[0x100]; + + static const int jrll[]; + static const int jpll[]; + + /*! The order of the map; -1 for nonhierarchical map. */ + int order_; + /*! The N_side parameter of the map; 0 if not allocated. */ + int nside_; + int npface_, ncap_, npix_; + double fact1_, fact2_; + /*! The map's ordering scheme. */ + Healpix_Ordering_Scheme scheme_; + + inline int ring_above (double z) const; + void in_ring (int iz, double phi0, double dphi, + std::vector &listir) const; + + int xyf2nest(int ix, int iy, int face_num) const; + void nest2xyf(int pix, int &ix, int &iy, int &face_num) const; + int xyf2ring(int ix, int iy, int face_num) const; + void ring2xyf(int pix, int &ix, int &iy, int &face_num) const; + + typedef int (Healpix_Base::*swapfunc)(int pix) const; + typedef void (Healpix_Base::*pix2xyf) + (int pix, int &x, int &y, int &f) const; + typedef int (Healpix_Base::*xyf2pix) (int x, int y, int f) const; + + public: + /*! Calculates the map order from its \a N_side parameter. + Returns -1 if \a nside is not a power of 2. + \param nside the \a N_side parameter */ + static int nside2order (int nside) + { + planck_assert (nside>0, "invalid value for Nside"); + if ((nside)&(nside-1)) return -1; + return ilog2(nside); + } + /*! Calculates the \a N_side parameter from the number of pixels. + \param npix the number of pixels */ + static int npix2nside (int npix); + /*! Constructs an unallocated object. */ + Healpix_Base () + : order_(-1), nside_(0), npface_(0), ncap_(0), npix_(0), + fact1_(0), fact2_(0), scheme_(RING) {} + /*! Constructs an object with a given \a order and the ordering + scheme \a scheme. */ + Healpix_Base (int order, Healpix_Ordering_Scheme scheme) + { Set (order, scheme); } + /*! Constructs an object with a given \a nside and the ordering + scheme \a scheme. The \a nside_dummy parameter must be set to + SET_NSIDE. */ + Healpix_Base (int nside, Healpix_Ordering_Scheme scheme, const nside_dummy) + { SetNside (nside, scheme); } + + /* Adjusts the object to \a order and \a scheme. */ + void Set (int order, Healpix_Ordering_Scheme scheme) + { + planck_assert ((order>=0)&&(order<=order_max), "bad order"); + order_ = order; + nside_ = 1<=0), + "SetNside: nside must be power of 2 for nested maps"); + nside_ = nside; + npface_ = nside_*nside_; + ncap_ = (npface_-nside_)<<1; + npix_ = 12*npface_; + fact2_ = 4./npix_; + fact1_ = (nside_<<1)*fact2_; + scheme_ = scheme; + } + + /*! Returns the z-coordinate of the ring \a ring. This also works + for the (not really existing) rings 0 and 4*nside. */ + double ring2z (int ring) const; + /*! Returns the number of the ring in which \a pix lies. */ + int pix2ring (int pix) const; + + /*! Translates a pixel number from NEST to RING. */ + int nest2ring (int pix) const; + /*! Translates a pixel number from RING to NEST. */ + int ring2nest (int pix) const; + /*! Translates a pixel number from NEST to its Peano index. */ + int nest2peano (int pix) const; + /*! Translates a pixel number from its Peano index to NEST. */ + int peano2nest (int pix) const; + + int ang2pix_z_phi (double z, double phi) const; + + /*! Returns the number of the pixel which contains the angular coordinates + \a ang. */ + int ang2pix (const pointing &ang) const + { return ang2pix_z_phi (cos(ang.theta), ang.phi); } + /*! Returns the number of the pixel which contains the vector \a vec + (\a vec is normalized if necessary). */ + int vec2pix (const vec3 &vec) const + { return ang2pix_z_phi (vec.z/vec.Length(), safe_atan2(vec.y,vec.x)); } + + void pix2ang_z_phi (int pix, double &z, double &phi) const; + + /*! Returns the angular coordinates of the center of the pixel with + number \a pix. */ + pointing pix2ang (int pix) const + { + double z, phi; + pix2ang_z_phi (pix,z,phi); + return pointing(acos(z),phi); + } + /*! Returns the vector to the center of the pixel with number \a pix. */ + vec3 pix2vec (int pix) const + { + double z, phi; + pix2ang_z_phi (pix,z,phi); + vec3 res; + res.set_z_phi (z, phi); + return res; + } + + /*! Returns the numbers of all pixels whose centers lie within \a radius + of \a dir in \a listpix. + \param dir the angular coordinates of the disc center + \param radius the radius (in radians) of the disc + \param listpix a vector containing the numbers of all pixels within + the disc + \note This method is more efficient in the RING scheme. */ + void query_disc (const pointing &dir, double radius, + std::vector &listpix) const; + /*! Returns the numbers of all pixels that lie at least partially within + \a radius of \a dir in \a listpix. It may also return a few pixels + which do not lie in the disk at all. + \param dir the angular coordinates of the disc center + \param radius the radius (in radians) of the disc + \param listpix a vector containing the numbers of all pixels within + the disc + \note This method works in both RING and NEST schemes, but is + considerably faster in the RING scheme. */ + void query_disc_inclusive (const pointing &dir, double radius, + std::vector &listpix) const; + + /*! Returns useful information about a given ring of the map. + \param ring the ring number (the number of the first ring is 1) + \param startpix the number of the first pixel in the ring + \param ringpix the number of pixels in the ring + \param costheta the cosine of the colatitude of the ring + \param sintheta the sine of the colatitude of the ring + \param shifted if \a true, the center of the first pixel is not at + \a phi=0 */ + void get_ring_info (int ring, int &startpix, int &ringpix, + double &costheta, double &sintheta, bool &shifted) const; + /*! Returns useful information about a given ring of the map. + \param ring the ring number (the number of the first ring is 1) + \param startpix the number of the first pixel in the ring + \param ringpix the number of pixels in the ring + \param theta the colatitude (in radians) of the ring + \param shifted if \a true, the center of the first pixel is not at + \a phi=0 */ + void get_ring_info2 (int ring, int &startpix, int &ringpix, + double &theta, bool &shifted) const; + + /*! Returns the neighboring pixels of \a pix in \a result. + On exit, \a result contains (in this order) + the pixel numbers of the SW, W, NW, N, NE, E, SE and S neighbor + of \a pix. If a neighbor does not exist (this can only be the case + for the W, N, E and S neighbors), its entry is set to -1. + + \note This method works in both RING and NEST schemes, but is + considerably faster in the NEST scheme. */ + void neighbors (int pix, fix_arr &result) const; + /*! Returns interpolation information for the direction \a ptg. + The surrounding pixels are returned in \a pix, their corresponding + weights in \a wgt. + \note This method works in both RING and NEST schemes, but is + considerably faster in the RING scheme. */ + void get_interpol (const pointing &ptg, fix_arr &pix, + fix_arr &wgt) const; + + /*! Returns the order parameter of the object. */ + int Order() const { return order_; } + /*! Returns the \a N_side parameter of the object. */ + int Nside() const { return nside_; } + /*! Returns the number of pixels of the object. */ + int Npix() const { return npix_; } + /*! Returns the ordering scheme of the object. */ + Healpix_Ordering_Scheme Scheme() const { return scheme_; } + + /*! Returns \a true, if both objects have the same nside and scheme, + else \a false. */ + bool conformable (const Healpix_Base &other) const + { return ((nside_==other.nside_) && (scheme_==other.scheme_)); } + + /*! Swaps the contents of two Healpix_Base objects. */ + void swap (Healpix_Base &other) + { + std::swap(order_,other.order_); + std::swap(nside_,other.nside_); + std::swap(npface_,other.npface_); + std::swap(ncap_,other.ncap_); + std::swap(npix_,other.npix_); + std::swap(fact1_,other.fact1_); + std::swap(fact2_,other.fact2_); + std::swap(scheme_,other.scheme_); + } + + /*! Returns the maximum angular distance (in radian) between any pixel + center and its corners. */ + double max_pixrad() const; + }; + +#endif diff --git a/external/healpix/Healpix_cxx/healpix_base2.cc b/external/healpix/Healpix_cxx/healpix_base2.cc new file mode 100644 index 0000000..8794991 --- /dev/null +++ b/external/healpix/Healpix_cxx/healpix_base2.cc @@ -0,0 +1,707 @@ +/* + * This file is part of Healpix_cxx. + * + * Healpix_cxx 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. + * + * Healpix_cxx 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 Healpix_cxx; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * For more information about HEALPix, see http://healpix.jpl.nasa.gov + */ + +/* + * Healpix_cxx is being developed at the Max-Planck-Institut fuer Astrophysik + * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt + * (DLR). + */ + +/* + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Max-Planck-Society + * Author: Martin Reinecke + */ + +#include "healpix_base2.h" +#include "cxxutils.h" +#include "pointing.h" +#include "arr.h" +#include "geom_utils.h" +#include "lsconstants.h" + +using namespace std; + +short Healpix_Base2::ctab[]; +short Healpix_Base2::utab[]; + +Healpix_Base2::Tablefiller::Tablefiller() + { + for (int m=0; m<0x100; ++m) + { + ctab[m] = short( + (m&0x1 ) | ((m&0x2 ) << 7) | ((m&0x4 ) >> 1) | ((m&0x8 ) << 6) + | ((m&0x10) >> 2) | ((m&0x20) << 5) | ((m&0x40) >> 3) | ((m&0x80) << 4)); + utab[m] = short( + (m&0x1 ) | ((m&0x2 ) << 1) | ((m&0x4 ) << 2) | ((m&0x8 ) << 3) + | ((m&0x10) << 4) | ((m&0x20) << 5) | ((m&0x40) << 6) | ((m&0x80) << 7)); + } + } + +Healpix_Base2::Tablefiller Healpix_Base2::Filler; + +const int Healpix_Base2::jrll[] = { 2,2,2,2,3,3,3,3,4,4,4,4 }; +const int Healpix_Base2::jpll[] = { 1,3,5,7,0,2,4,6,1,3,5,7 }; + +int64 Healpix_Base2::npix2nside (int64 npix) + { + int64 res=isqrt(npix/12); + planck_assert (npix==res*res*12, "npix2nside: invalid argument"); + return res; + } + +int64 Healpix_Base2::ring_above (double z) const + { + double az=abs(z); + if (az>twothird) // polar caps + { + int64 iring = int64(nside_*sqrt(3*(1-az))); + return (z>0) ? iring : 4*nside_-iring-1; + } + else // ----- equatorial region --------- + return int64(nside_*(2-1.5*z)); + } + +void Healpix_Base2::nest2xyf (int64 pix, int &ix, int &iy, int &face_num) + const + { + face_num = int(pix>>(2*order_)); + pix &= (npface_-1); + int32 raw = ((pix&0x555500000000ull)>>16) + | ((pix&0x5555000000000000ull)>>31) + | (pix&0x5555) + | ((pix&0x55550000)>>15); + ix = ctab[raw&0xff] + | (ctab[(raw>>8)&0xff]<<4) + | (ctab[(raw>>16)&0xff]<<16) + | (ctab[(raw>>24)&0xff]<<20); + pix >>= 1; + raw = ((pix&0x555500000000ull)>>16) + | ((pix&0x5555000000000000ull)>>31) + | (pix&0x5555) + | ((pix&0x55550000)>>15); + iy = ctab[raw&0xff] + | (ctab[(raw>>8)&0xff]<<4) + | (ctab[(raw>>16)&0xff]<<16) + | (ctab[(raw>>24)&0xff]<<20); + } + +int64 Healpix_Base2::xyf2nest (int ix, int iy, int face_num) const + { + return (int64(face_num)<<(2*order_)) + + ( (int64(utab[ ix &0xff])) + | (int64(utab[(ix>> 8)&0xff])<<16) + | (int64(utab[(ix>>16)&0xff])<<32) + | (int64(utab[(ix>>24)&0xff])<<48) + | (int64(utab[ iy &0xff])<<1) + | (int64(utab[(iy>> 8)&0xff])<<17) + | (int64(utab[(iy>>16)&0xff])<<33) + | (int64(utab[(iy>>24)&0xff])<<49) ); + } + +void Healpix_Base2::ring2xyf (int64 pix, int &ix, int &iy, int &face_num) + const + { + int64 iring, iphi, kshift, nr; + + int64 nl2 = 2*nside_; + + if (pix=(2*iring)) + { + face_num=2; + tmp-=2*iring; + } + if (tmp>=iring) ++face_num; + } + else if (pix<(npix_-ncap_)) // Equatorial region + { + int64 ip = pix - ncap_; + if (order_>=0) + { + iring = (ip>>(order_+2)) + nside_; // counted from North pole + iphi = (ip&(4*nside_-1)) + 1; + } + else + { + iring = (ip/(4*nside_)) + nside_; // counted from North pole + iphi = (ip%(4*nside_)) + 1; + } + kshift = (iring+nside_)&1; + nr = nside_; + int64 ire = iring-nside_+1; + int64 irm = nl2+2-ire; + int64 ifm, ifp; + if (order_>=0) + { + ifm = (iphi - ire/2 + nside_ -1) >> order_; + ifp = (iphi - irm/2 + nside_ -1) >> order_; + } + else + { + ifm = (iphi - ire/2 + nside_ -1) / nside_; + ifp = (iphi - irm/2 + nside_ -1) / nside_; + } + if (ifp == ifm) // faces 4 to 7 + face_num = (ifp==4) ? 4 : ifp+4; + else if (ifp=(2*nr)) + { + face_num=10; + tmp-=2*nr; + } + if (tmp>=nr) ++face_num; + } + + int64 irt = iring - (jrll[face_num]*nside_) + 1; + int64 ipt = 2*iphi- jpll[face_num]*nr - kshift -1; + if (ipt>=nl2) ipt-=8*nside_; + + ix = (ipt-irt) >>1; + iy =(-(ipt+irt))>>1; + } + +int64 Healpix_Base2::xyf2ring (int ix, int iy, int face_num) const + { + int64 nl4 = 4*nside_; + int64 jr = (jrll[face_num]*nside_) - ix - iy - 1; + + int64 nr, kshift, n_before; + if (jr 3*nside_) + { + nr = nl4-jr; + n_before = npix_ - 2*(nr+1)*nr; + kshift = 0; + } + else + { + nr = nside_; + n_before = ncap_ + (jr-nside_)*nl4; + kshift = (jr-nside_)&1; + } + + int64 jp = (jpll[face_num]*nr + ix - iy + 1 + kshift) / 2; + if (jp>nl4) + jp-=nl4; + else + if (jp<1) jp+=nl4; + + return n_before + jp - 1; + } + +double Healpix_Base2::ring2z (int64 ring) const + { + if (ring=0, "nest2ring: need hierarchical map"); + int ix, iy, face_num; + nest2xyf (pix, ix, iy, face_num); + return xyf2ring (ix, iy, face_num); + } + +int64 Healpix_Base2::ring2nest (int64 pix) const + { + planck_assert(order_>=0, "ring2nest: need hierarchical map"); + int ix, iy, face_num; + ring2xyf (pix, ix, iy, face_num); + return xyf2nest (ix, iy, face_num); + } + +int64 Healpix_Base2::nest2peano (int64 pix) const + { + static const uint8 subpix[8][4] = { + { 0, 1, 3, 2 }, { 3, 0, 2, 1 }, { 2, 3, 1, 0 }, { 1, 2, 0, 3 }, + { 0, 3, 1, 2 }, { 1, 0, 2, 3 }, { 2, 1, 3, 0 }, { 3, 2, 0, 1 } }; + static const uint8 subpath[8][4] = { + { 4, 0, 6, 0 }, { 7, 5, 1, 1 }, { 2, 4, 2, 6 }, { 3, 3, 7, 5 }, + { 0, 2, 4, 4 }, { 5, 1, 5, 3 }, { 6, 6, 0, 2 }, { 1, 7, 3, 7 } }; + static const uint8 face2path[12] = { + 2, 5, 2, 5, 3, 6, 3, 6, 2, 3, 2, 3 }; + static const uint8 face2peanoface[12] = { + 0, 5, 6, 11, 10, 1, 4, 7, 2, 3, 8, 9 }; + + int face = pix>>(2*order_); + uint8 path = face2path[face]; + int64 result = 0; + + for (int shift=2*order_-2; shift>=0; shift-=2) + { + uint8 spix = uint8((pix>>shift) & 0x3); + result <<= 2; + result |= subpix[path][spix]; + path=subpath[path][spix]; + } + + return result + (int64(face2peanoface[face])<<(2*order_)); + } + +int64 Healpix_Base2::peano2nest (int64 pix) const + { + static const uint8 subpix[8][4] = { + { 0, 1, 3, 2 }, { 1, 3, 2, 0 }, { 3, 2, 0, 1 }, { 2, 0, 1, 3 }, + { 0, 2, 3, 1 }, { 1, 0, 2, 3 }, { 3, 1, 0, 2 }, { 2, 3, 1, 0 } }; + static const uint8 subpath[8][4] = { + { 4, 0, 0, 6 }, { 5, 1, 1, 7 }, { 6, 2, 2, 4 }, { 7, 3, 3, 5 }, + { 0, 4, 4, 2 }, { 1, 5, 5, 3 }, { 2, 6, 6, 0 }, { 3, 7, 7, 1 } }; + static const uint8 face2path[12] = { + 2, 6, 2, 3, 3, 5, 2, 6, 2, 3, 3, 5 }; + static const uint8 peanoface2face[12] = { + 0, 5, 8, 9, 6, 1, 2, 7, 10, 11, 4, 3 }; + + int face = pix>>(2*order_); + uint8 path = face2path[face]; + int64 result = 0; + + for (int shift=2*order_-2; shift>=0; shift-=2) + { + uint8 spix = uint8((pix>>shift) & 0x3); + result <<= 2; + result |= subpix[path][spix]; + path=subpath[path][spix]; + } + + return result + (int64(peanoface2face[face])<<(2*order_)); + } + +int64 Healpix_Base2::ang2pix_z_phi (double z, double phi) const + { + double za = abs(z); + double tt = fmodulo(phi,twopi) * inv_halfpi; // in [0,4) + + if (scheme_==RING) + { + if (za<=twothird) // Equatorial region + { + double temp1 = nside_*(0.5+tt); + double temp2 = nside_*z*0.75; + int64 jp = int64(temp1-temp2); // index of ascending edge line + int64 jm = int64(temp1+temp2); // index of descending edge line + + // ring number counted from z=2/3 + int64 ir = nside_ + 1 + jp - jm; // in {1,2n+1} + int kshift = 1-(ir&1); // kshift=1 if ir even, 0 otherwise + + int64 ip = (jp+jm-nside_+kshift+1)/2; // in {0,4n-1} + ip = imodulo(ip,4*nside_); + + return ncap_ + (ir-1)*4*nside_ + ip; + } + else // North & South polar caps + { + double tp = tt-int(tt); + double tmp = nside_*sqrt(3*(1-za)); + + int64 jp = int64(tp*tmp); // increasing edge line index + int64 jm = int64((1.0-tp)*tmp); // decreasing edge line index + + int64 ir = jp+jm+1; // ring number counted from the closest pole + int64 ip = int64(tt*ir); // in {0,4*ir-1} + ip = imodulo(ip,4*ir); + + if (z>0) + return 2*ir*(ir-1) + ip; + else + return npix_ - 2*ir*(ir+1) + ip; + } + } + else // scheme_ == NEST + { + int face_num, ix, iy; + + if (za<=twothird) // Equatorial region + { + double temp1 = nside_*(0.5+tt); + double temp2 = nside_*(z*0.75); + int64 jp = int64(temp1-temp2); // index of ascending edge line + int64 jm = int64(temp1+temp2); // index of descending edge line + int64 ifp = jp >> order_; // in {0,4} + int64 ifm = jm >> order_; + if (ifp == ifm) // faces 4 to 7 + face_num = (ifp==4) ? 4: ifp+4; + else if (ifp < ifm) // (half-)faces 0 to 3 + face_num = ifp; + else // (half-)faces 8 to 11 + face_num = ifm + 8; + + ix = jm & (nside_-1); + iy = nside_ - (jp & (nside_-1)) - 1; + } + else // polar region, za > 2/3 + { + int ntt = int(tt); + if (ntt>=4) ntt=3; + double tp = tt-ntt; + double tmp = nside_*sqrt(3*(1-za)); + + int64 jp = int64(tp*tmp); // increasing edge line index + int64 jm = int64((1.0-tp)*tmp); // decreasing edge line index + if (jp>=nside_) jp = nside_-1; // for points too close to the boundary + if (jm>=nside_) jm = nside_-1; + if (z >= 0) + { + face_num = ntt; // in {0,3} + ix = nside_ - jm - 1; + iy = nside_ - jp - 1; + } + else + { + face_num = ntt + 8; // in {8,11} + ix = jp; + iy = jm; + } + } + + return xyf2nest(ix,iy,face_num); + } + } + +void Healpix_Base2::pix2ang_z_phi (int64 pix, double &z, double &phi) const + { + if (scheme_==RING) + { + if (pix 3*nside_) + { + nr = nl4-jr; + z = nr*nr*fact2_ - 1; + kshift = 0; + } + else + { + nr = nside_; + z = (2*nside_-jr)*fact1_; + kshift = (jr-nside_)&1; + } + + int64 jp = (jpll[face_num]*nr + ix -iy + 1 + kshift) / 2; + if (jp>nl4) jp-=nl4; + if (jp<1) jp+=nl4; + + phi = (jp-(kshift+1)*0.5)*(halfpi/nr); + } + } + +void Healpix_Base2::get_ring_info (int64 ring, int64 &startpix, int64 &ringpix, + double &costheta, double &sintheta, bool &shifted) const + { + planck_assert(scheme_==RING,"map must be in RING scheme"); + int64 northring = (ring>2*nside_) ? 4*nside_-ring : ring; + if (northring < nside_) + { + double tmp = northring*northring*fact2_; + costheta = 1 - tmp; + sintheta = sqrt(tmp*(2-tmp)); + ringpix = 4*northring; + shifted = true; + startpix = 2*northring*(northring-1); + } + else + { + costheta = (2*nside_-northring)*fact1_; + sintheta = sqrt((1+costheta)*(1-costheta)); + ringpix = 4*nside_; + shifted = ((northring-nside_) & 1) == 0; + startpix = ncap_ + (northring-nside_)*ringpix; + } + if (northring != ring) // southern hemisphere + { + costheta = -costheta; + startpix = npix_ - startpix - ringpix; + } + } + +void Healpix_Base2::neighbors (int64 pix, fix_arr &result) const + { + static const int xoffset[] = { -1,-1, 0, 1, 1, 1, 0,-1 }; + static const int yoffset[] = { 0, 1, 1, 1, 0,-1,-1,-1 }; + static const int facearray[][12] = + { { 8, 9,10,11,-1,-1,-1,-1,10,11, 8, 9 }, // S + { 5, 6, 7, 4, 8, 9,10,11, 9,10,11, 8 }, // SE + { -1,-1,-1,-1, 5, 6, 7, 4,-1,-1,-1,-1 }, // E + { 4, 5, 6, 7,11, 8, 9,10,11, 8, 9,10 }, // SW + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }, // center + { 1, 2, 3, 0, 0, 1, 2, 3, 5, 6, 7, 4 }, // NE + { -1,-1,-1,-1, 7, 4, 5, 6,-1,-1,-1,-1 }, // W + { 3, 0, 1, 2, 3, 0, 1, 2, 4, 5, 6, 7 }, // NW + { 2, 3, 0, 1,-1,-1,-1,-1, 0, 1, 2, 3 } }; // N + static const int swaparray[][12] = + { { 0,0,0,0,0,0,0,0,3,3,3,3 }, // S + { 0,0,0,0,0,0,0,0,6,6,6,6 }, // SE + { 0,0,0,0,0,0,0,0,0,0,0,0 }, // E + { 0,0,0,0,0,0,0,0,5,5,5,5 }, // SW + { 0,0,0,0,0,0,0,0,0,0,0,0 }, // center + { 5,5,5,5,0,0,0,0,0,0,0,0 }, // NE + { 0,0,0,0,0,0,0,0,0,0,0,0 }, // W + { 6,6,6,6,0,0,0,0,0,0,0,0 }, // NW + { 3,3,3,3,0,0,0,0,0,0,0,0 } }; // N + + int ix, iy, face_num; + (scheme_==RING) ? + ring2xyf(pix,ix,iy,face_num) : nest2xyf(pix,ix,iy,face_num); + + const int64 nsm1 = nside_-1; + if ((ix>0)&&(ix0)&&(iy=nside_) + { x-=nside_; nbnum+=1; } + if (y<0) + { y+=nside_; nbnum-=3; } + else if (y>=nside_) + { y-=nside_; nbnum+=3; } + + int f = facearray[nbnum][face_num]; + if (f>=0) + { + if (swaparray[nbnum][face_num]&1) x=nside_-x-1; + if (swaparray[nbnum][face_num]&2) y=nside_-y-1; + if (swaparray[nbnum][face_num]&4) std::swap(x,y); + result[i] = (scheme_==RING) ? xyf2ring(x,y,f) : xyf2nest(x,y,f); + } + else + result[i] = -1; + } + } + } + +void Healpix_Base2::get_ring_info2 (int64 ring, int64 &startpix, int64 &ringpix, + double &theta, bool &shifted) const + { + int64 northring = (ring>2*nside_) ? 4*nside_-ring : ring; + if (northring < nside_) + { + double tmp = northring*northring*fact2_; + double costheta = 1 - tmp; + double sintheta = sqrt(tmp*(2-tmp)); + theta = atan2(sintheta,costheta); + ringpix = 4*northring; + shifted = true; + startpix = 2*northring*(northring-1); + } + else + { + theta = acos((2*nside_-northring)*fact1_); + ringpix = 4*nside_; + shifted = ((northring-nside_) & 1) == 0; + startpix = ncap_ + (northring-nside_)*ringpix; + } + if (northring != ring) // southern hemisphere + { + theta = pi-theta; + startpix = npix_ - startpix - ringpix; + } + } + +void Healpix_Base2::get_interpol (const pointing &ptg, fix_arr &pix, + fix_arr &wgt) const + { + double z = cos (ptg.theta); + int64 ir1 = ring_above(z); + int64 ir2 = ir1+1; + double theta1, theta2, w1, tmp, dphi; + int64 sp,nr; + bool shift; + int64 i1,i2; + if (ir1>0) + { + get_ring_info2 (ir1, sp, nr, theta1, shift); + dphi = twopi/nr; + tmp = (ptg.phi/dphi - .5*shift); + i1 = (tmp<0) ? int64(tmp)-1 : int64(tmp); + w1 = (ptg.phi-(i1+.5*shift)*dphi)/dphi; + i2 = i1+1; + if (i1<0) i1 +=nr; + if (i2>=nr) i2 -=nr; + pix[0] = sp+i1; pix[1] = sp+i2; + wgt[0] = 1-w1; wgt[1] = w1; + } + if (ir2<(4*nside_)) + { + get_ring_info2 (ir2, sp, nr, theta2, shift); + dphi = twopi/nr; + tmp = (ptg.phi/dphi - .5*shift); + i1 = (tmp<0) ? int64(tmp)-1 : int64(tmp); + w1 = (ptg.phi-(i1+.5*shift)*dphi)/dphi; + i2 = i1+1; + if (i1<0) i1 +=nr; + if (i2>=nr) i2 -=nr; + pix[2] = sp+i1; pix[3] = sp+i2; + wgt[2] = 1-w1; wgt[3] = w1; + } + + if (ir1==0) + { + double wtheta = ptg.theta/theta2; + wgt[2] *= wtheta; wgt[3] *= wtheta; + double fac = (1-wtheta)*0.25; + wgt[0] = fac; wgt[1] = fac; wgt[2] += fac; wgt[3] +=fac; + pix[0] = (pix[2]+2)%4; + pix[1] = (pix[3]+2)%4; + } + else if (ir2==4*nside_) + { + double wtheta = (ptg.theta-theta1)/(pi-theta1); + wgt[0] *= (1-wtheta); wgt[1] *= (1-wtheta); + double fac = wtheta*0.25; + wgt[0] += fac; wgt[1] += fac; wgt[2] = fac; wgt[3] =fac; + pix[2] = ((pix[0]+2)&3)+npix_-4; + pix[3] = ((pix[1]+2)&3)+npix_-4; + } + else + { + double wtheta = (ptg.theta-theta1)/(theta2-theta1); + wgt[0] *= (1-wtheta); wgt[1] *= (1-wtheta); + wgt[2] *= wtheta; wgt[3] *= wtheta; + } + + if (scheme_==NEST) + for (tsize m=0; m0, "invalid value for Nside"); + if ((nside)&(nside-1)) return -1; + return ilog2(nside); + } + /*! Calculates the \a N_side parameter from the number of pixels. + \param npix the number of pixels */ + static int64 npix2nside (int64 npix); + /*! Constructs an unallocated object. */ + Healpix_Base2 () + : order_(-1), nside_(0), npface_(0), ncap_(0), npix_(0), + fact1_(0), fact2_(0), scheme_(RING) {} + /*! Constructs an object with a given \a order and the ordering + scheme \a scheme. */ + Healpix_Base2 (int order, Healpix_Ordering_Scheme scheme) + { Set (order, scheme); } + /*! Constructs an object with a given \a nside and the ordering + scheme \a scheme. The \a nside_dummy parameter must be set to + SET_NSIDE. */ + Healpix_Base2 (int64 nside, Healpix_Ordering_Scheme scheme, + const nside_dummy) + { SetNside (nside, scheme); } + + /* Adjusts the object to \a order and \a scheme. */ + void Set (int order, Healpix_Ordering_Scheme scheme) + { + planck_assert ((order>=0)&&(order<=order_max), "bad order"); + order_ = order; + nside_ = int64(1)<=0), + "SetNside: nside must be power of 2 for nested maps"); + nside_ = nside; + npface_ = nside_*nside_; + ncap_ = (npface_-nside_)<<1; + npix_ = 12*npface_; + fact2_ = 4./npix_; + fact1_ = (nside_<<1)*fact2_; + scheme_ = scheme; + } + + /*! Returns the z-coordinate of the ring \a ring. This also works + for the (not really existing) rings 0 and 4*nside. */ + double ring2z (int64 ring) const; + /*! Returns the number of the ring in which \a pix lies. */ + int64 pix2ring (int64 pix) const; + + /*! Translates a pixel number from NEST to RING. */ + int64 nest2ring (int64 pix) const; + /*! Translates a pixel number from RING to NEST. */ + int64 ring2nest (int64 pix) const; + /*! Translates a pixel number from NEST to its Peano index. */ + int64 nest2peano (int64 pix) const; + /*! Translates a pixel number from its Peano index to NEST. */ + int64 peano2nest (int64 pix) const; + + int64 ang2pix_z_phi (double z, double phi) const; + + /*! Returns the number of the pixel which contains the angular coordinates + \a ang. */ + int64 ang2pix (const pointing &ang) const + { return ang2pix_z_phi (cos(ang.theta), ang.phi); } + /*! Returns the number of the pixel which contains the vector \a vec + (\a vec is normalized if necessary). */ + int64 vec2pix (const vec3 &vec) const + { return ang2pix_z_phi (vec.z/vec.Length(), safe_atan2(vec.y,vec.x)); } + + void pix2ang_z_phi (int64 pix, double &z, double &phi) const; + + /*! Returns the angular coordinates of the center of the pixel with + number \a pix. */ + pointing pix2ang (int64 pix) const + { + double z, phi; + pix2ang_z_phi (pix,z,phi); + return pointing(acos(z),phi); + } + /*! Returns the vector to the center of the pixel with number \a pix. */ + vec3 pix2vec (int64 pix) const + { + double z, phi; + pix2ang_z_phi (pix,z,phi); + vec3 res; + res.set_z_phi (z, phi); + return res; + } + + /*! Returns useful information about a given ring of the map. + \param ring the ring number (the number of the first ring is 1) + \param startpix the number of the first pixel in the ring + \param ringpix the number of pixels in the ring + \param costheta the cosine of the colatitude of the ring + \param sintheta the sine of the colatitude of the ring + \param shifted if \a true, the center of the first pixel is not at + \a phi=0 */ + void get_ring_info (int64 ring, int64 &startpix, int64 &ringpix, + double &costheta, double &sintheta, bool &shifted) const; + /*! Returns useful information about a given ring of the map. + \param ring the ring number (the number of the first ring is 1) + \param startpix the number of the first pixel in the ring + \param ringpix the number of pixels in the ring + \param theta the colatitude (in radians) of the ring + \param shifted if \a true, the center of the first pixel is not at + \a phi=0 */ + void get_ring_info2 (int64 ring, int64 &startpix, int64 &ringpix, + double &theta, bool &shifted) const; + + /*! Returns the neighboring pixels of \a pix in \a result. + On exit, \a result contains (in this order) + the pixel numbers of the SW, W, NW, N, NE, E, SE and S neighbor + of \a pix. If a neighbor does not exist (this can only be the case + for the W, N, E and S neighbors), its entry is set to -1. + + \note This method works in both RING and NEST schemes, but is + considerably faster in the NEST scheme. */ + void neighbors (int64 pix, fix_arr &result) const; + /*! Returns interpolation information for the direction \a ptg. + The surrounding pixels are returned in \a pix, their corresponding + weights in \a wgt. + \note This method works in both RING and NEST schemes, but is + considerably faster in the RING scheme. */ + void get_interpol (const pointing &ptg, fix_arr &pix, + fix_arr &wgt) const; + + /*! Returns the order parameter of the object. */ + int Order() const { return order_; } + /*! Returns the \a N_side parameter of the object. */ + int64 Nside() const { return nside_; } + /*! Returns the number of pixels of the object. */ + int64 Npix() const { return npix_; } + /*! Returns the ordering scheme of the object. */ + Healpix_Ordering_Scheme Scheme() const { return scheme_; } + + /*! Returns \a true, if both objects have the same nside and scheme, + else \a false. */ + bool conformable (const Healpix_Base2 &other) const + { return ((nside_==other.nside_) && (scheme_==other.scheme_)); } + + /*! Swaps the contents of two Healpix_Base objects. */ + void swap (Healpix_Base2 &other) + { + std::swap(order_,other.order_); + std::swap(nside_,other.nside_); + std::swap(npface_,other.npface_); + std::swap(ncap_,other.ncap_); + std::swap(npix_,other.npix_); + std::swap(fact1_,other.fact1_); + std::swap(fact2_,other.fact2_); + std::swap(scheme_,other.scheme_); + } + + /*! Returns the maximum angular distance (in radian) between any pixel + center and its corners. */ + double max_pixrad() const; + }; + +#endif diff --git a/external/healpix/Healpix_cxx/healpix_data_io.cc b/external/healpix/Healpix_cxx/healpix_data_io.cc new file mode 100644 index 0000000..283e8b6 --- /dev/null +++ b/external/healpix/Healpix_cxx/healpix_data_io.cc @@ -0,0 +1,112 @@ +/* + * This file is part of Healpix_cxx. + * + * Healpix_cxx 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. + * + * Healpix_cxx 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 Healpix_cxx; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * For more information about HEALPix, see http://healpix.jpl.nasa.gov + */ + +/* + * Healpix_cxx is being developed at the Max-Planck-Institut fuer Astrophysik + * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt + * (DLR). + */ + +/* + * Copyright (C) 2003, 2005, 2009 Max-Planck-Society + * Author: Martin Reinecke + */ + +#include "healpix_data_io.h" +#include "arr.h" +#include "fitshandle.h" +#include "paramfile.h" + +using namespace std; + +void read_weight_ring (const string &dir, int nside, arr &weight) + { + fitshandle inp; + inp.open(dir+"/weight_ring_n"+intToString(nside,5)+".fits"); + inp.goto_hdu(2); + weight.alloc (2*nside); + inp.read_column(1,weight); + } + +void get_ring_weights (paramfile ¶ms, int nside, arr &weight) + { + bool weighted = params.find("weighted",false); + weight.alloc (2*nside); + if (weighted) + { + string datadir = params.find("healpix_data"); + read_weight_ring (datadir, nside, weight); + for (tsize m=0; m &temp) + { + fitshandle inp; + inp.open(dir+"/pixel_window_n"+intToString(nside,4)+".fits"); + inp.goto_hdu(2); + if (temp.size()==0) + inp.read_entire_column(1,temp); + else + inp.read_column(1,temp); + } +void read_pixwin (const string &dir, int nside, arr &temp, + arr &pol) + { + fitshandle inp; + inp.open(dir+"/pixel_window_n"+intToString(nside,4)+".fits"); + inp.goto_hdu(2); + if (temp.size()==0) + inp.read_entire_column(1,temp); + else + inp.read_column(1,temp); + if (pol.size()==0) + inp.read_entire_column(2,pol); + else + inp.read_column(2,pol); + } + +void get_pixwin (paramfile ¶ms, int lmax, int nside, arr &pixwin) + { + bool do_pixwin = params.find("pixel_window",false); + pixwin.alloc(lmax+1); + pixwin.fill(1); + if (do_pixwin) + { + string datadir = params.find("healpix_data"); + read_pixwin (datadir,nside,pixwin); + } + } +void get_pixwin (paramfile ¶ms, int lmax, int nside, arr &pixwin, + arr &pixwin_pol) + { + bool do_pixwin = params.find("pixel_window",false); + pixwin.alloc(lmax+1); + pixwin.fill(1); + pixwin_pol.alloc(lmax+1); + pixwin_pol.fill(1); + if (do_pixwin) + { + string datadir = params.find("healpix_data"); + read_pixwin (datadir,nside,pixwin,pixwin_pol); + } + } diff --git a/external/healpix/Healpix_cxx/healpix_data_io.h b/external/healpix/Healpix_cxx/healpix_data_io.h new file mode 100644 index 0000000..ba60a7a --- /dev/null +++ b/external/healpix/Healpix_cxx/healpix_data_io.h @@ -0,0 +1,51 @@ +/* + * This file is part of Healpix_cxx. + * + * Healpix_cxx 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. + * + * Healpix_cxx 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 Healpix_cxx; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * For more information about HEALPix, see http://healpix.jpl.nasa.gov + */ + +/* + * Healpix_cxx is being developed at the Max-Planck-Institut fuer Astrophysik + * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt + * (DLR). + */ + +/* + * Copyright (C) 2003, 2005 Max-Planck-Society + * Author: Martin Reinecke + */ + +#ifndef HEALPIX_DATA_IO_H +#define HEALPIX_DATA_IO_H + +#include + +class paramfile; +template class arr; + +void read_weight_ring (const std::string &dir, int nside, arr &weight); +void get_ring_weights (paramfile ¶ms, int nside, arr &weight); + +void read_pixwin (const std::string &dir, int nside, arr &temp); +void read_pixwin (const std::string &dir, int nside, arr &temp, + arr &pol); + +void get_pixwin (paramfile ¶ms, int lmax, int nside, arr &pixwin); +void get_pixwin (paramfile ¶ms, int lmax, int nside, arr &pixwin, + arr &pixwin_pol); + +#endif diff --git a/external/healpix/Healpix_cxx/healpix_map.cc b/external/healpix/Healpix_cxx/healpix_map.cc new file mode 100644 index 0000000..052f0f6 --- /dev/null +++ b/external/healpix/Healpix_cxx/healpix_map.cc @@ -0,0 +1,94 @@ +/* + * This file is part of Healpix_cxx. + * + * Healpix_cxx 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. + * + * Healpix_cxx 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 Healpix_cxx; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * For more information about HEALPix, see http://healpix.jpl.nasa.gov + */ + +/* + * Healpix_cxx is being developed at the Max-Planck-Institut fuer Astrophysik + * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt + * (DLR). + */ + +/* + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Max-Planck-Society + * Author: Martin Reinecke + */ + +#include "healpix_map.h" + +using namespace std; + +template void Healpix_Map::Import_degrade + (const Healpix_Map &orig, bool pessimistic) + { + planck_assert(nside_*to_xyf)(m,x,y,f); + int hits = 0; + double sum = 0; + for (int j=fact*y; j(orig.map[opix],Healpix_undef)) + { + ++hits; + sum += orig.map[opix]; + } + } + map[m] = T((hits::Import_degrade + (const Healpix_Map &orig, bool pessimistic); +template void Healpix_Map::Import_degrade + (const Healpix_Map &orig, bool pessimistic); + +template void Healpix_Map::minmax (T &Min, T &Max) const + { + Min = T(1e30); Max = T(-1e30); + for (int m=0; m(val,Healpix_undef)) + { + if (val>Max) Max=val; + if (val::minmax (float &Min, float &Max) const; +template void Healpix_Map::minmax (double &Min, double &Max) const; diff --git a/external/healpix/Healpix_cxx/healpix_map.h b/external/healpix/Healpix_cxx/healpix_map.h new file mode 100644 index 0000000..e8bad93 --- /dev/null +++ b/external/healpix/Healpix_cxx/healpix_map.h @@ -0,0 +1,316 @@ +/* + * This file is part of Healpix_cxx. + * + * Healpix_cxx 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. + * + * Healpix_cxx 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 Healpix_cxx; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * For more information about HEALPix, see http://healpix.jpl.nasa.gov + */ + +/* + * Healpix_cxx is being developed at the Max-Planck-Institut fuer Astrophysik + * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt + * (DLR). + */ + +/*! \file healpix_map.h + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Max-Planck-Society + * \author Martin Reinecke + */ + +#ifndef HEALPIX_MAP_H +#define HEALPIX_MAP_H + +#include "arr.h" +#include "healpix_base.h" + +//! Healpix value representing "undefined" +const double Healpix_undef=-1.6375e30; + +/*! A HEALPix map of a given datatype */ +template class Healpix_Map: public Healpix_Base + { + private: + arr map; + + public: + /*! Constructs an unallocated map. */ + Healpix_Map () {} + /*! Constructs a map with a given \a order and the ordering + scheme \a scheme. */ + Healpix_Map (int order, Healpix_Ordering_Scheme scheme) + : Healpix_Base (order, scheme), map(npix_) {} + /*! Constructs a map with a given \a nside and the ordering + scheme \a scheme. */ + Healpix_Map (int nside, Healpix_Ordering_Scheme scheme, const nside_dummy) + : Healpix_Base (nside, scheme, SET_NSIDE), map(npix_) {} + /*! Constructs a map from the contents of \a data and sets the ordering + scheme to \a Scheme. The size of \a data must be a valid HEALPix + map size. */ + Healpix_Map (const arr &data, Healpix_Ordering_Scheme scheme) + : Healpix_Base (npix2nside(data.size()), scheme, SET_NSIDE), map(data) {} + + /*! Deletes the old map, creates a map from the contents of \a data and + sets the ordering scheme to \a scheme. The size of \a data must be a + valid HEALPix map size. + \note On exit, \a data is zero-sized! */ + void Set (arr &data, Healpix_Ordering_Scheme scheme) + { + Healpix_Base::SetNside(npix2nside (data.size()), scheme); + map.transfer(data); + } + + /*! Deletes the old map and creates a new map with a given \a order + and the ordering scheme \a scheme. */ + void Set (int order, Healpix_Ordering_Scheme scheme) + { + Healpix_Base::Set(order, scheme); + map.alloc(npix_); + } + /*! Deletes the old map and creates a new map with a given \a nside + and the ordering scheme \a scheme. */ + void SetNside (int nside, Healpix_Ordering_Scheme scheme) + { + Healpix_Base::SetNside(nside, scheme); + map.alloc(npix_); + } + + /*! Fills the map with \a val. */ + void fill (const T &val) + { map.fill(val); } + + /*! Imports the map \a orig into the current map, adjusting the + ordering scheme. \a orig must have the same resolution as the + current map. */ + void Import_nograde (const Healpix_Map &orig) + { + planck_assert (nside_==orig.nside_, + "Import_nograde: maps have different nside"); + if (orig.scheme_ == scheme_) + for (int m=0; m*swapper)(m)] = orig.map[m]; +} + } + } + + /*! Imports the map \a orig into the current map, adjusting the + ordering scheme and the map resolution. \a orig must have higher + resolution than the current map. */ + void Import_upgrade (const Healpix_Map &orig) + { + planck_assert(nside_>orig.nside_,"Import_upgrade: this is no upgrade"); + int fact = nside_/orig.nside_; + planck_assert (nside_==orig.nside_*fact, + "the larger Nside must be a multiple of the smaller one"); + pix2xyf to_xyf = (orig.scheme_==RING) ? + &Healpix_Map::ring2xyf : &Healpix_Map::nest2xyf; + xyf2pix from_xyf = (scheme_==RING) ? + &Healpix_Map::xyf2ring : &Healpix_Map::xyf2nest; + +#pragma omp parallel +{ + int m; +#pragma omp for schedule (dynamic,5000) + for (m=0; m*from_xyf)(i,j,f); + map[mypix] = orig.map[m]; + } + } +} + } + + /*! Imports the map \a orig into the current map, adjusting the + ordering scheme and the map resolution. \a orig must have higher + resolution than the current map. + \a pessimistic determines whether or not + pixels are set to \a Healpix_undef when not all of the corresponding + high-resolution pixels are defined. + + This method is instantiated for \a float and \a double only. */ + void Import_degrade (const Healpix_Map &orig, bool pessimistic=false); + + /*! Imports the map \a orig into the current map, adjusting the + ordering scheme and the map resolution if necessary. + When downgrading, \a pessimistic determines whether or not + pixels are set to \a Healpix_undef when not all of the corresponding + high-resolution pixels are defined. + + This method is instantiated for \a float and \a double only. */ + void Import (const Healpix_Map &orig, bool pessimistic=false) + { + if (orig.nside_ == nside_) // no up/degrading + Import_nograde(orig); + else if (orig.nside_ < nside_) // upgrading + Import_upgrade(orig); + else + Import_degrade(orig,pessimistic); + } + + /*! Returns a constant reference to the pixel with the number \a pix. */ + const T &operator[] (int pix) const { return map[pix]; } + /*! Returns a reference to the pixel with the number \a pix. */ + T &operator[] (int pix) { return map[pix]; } + + /*! Swaps the map ordering from RING to NEST and vice versa. + This is done in-place (i.e. with negligible space overhead). */ + void swap_scheme() + { + static const int clen[] = { 0,7,5,4,12,10,13,18,14,19,18,17,27,21 }; + static const int cycle[][30] = { + { }, + { 0,1,8,12,16,21,40 }, + { 0,1,2,40,114 }, + { 0,4,160,263 }, + { 0,4,30,49,51,87,526,1027,1105,1387,1807,2637 }, + { 0,8,10,18,39,74,146,307,452,4737 }, + { 0,1,2,7,9,17,80,410,1526,1921,32859,33566,38931 }, + { 0,5,6,10,12,24,27,95,372,494,924,1409,3492,4248,9137,66043,103369, + 156899 }, + { 0,1,2,3,4,45,125,351,697,24337,102940,266194,341855,419857 }, + { 0,1,2,3,9,16,1705,2082,2126,8177,12753,15410,52642,80493,83235, + 88387,99444,1675361,2495125 }, + { 0,2,6,8,9,11,20,50,93,152,183,2137,13671,44794,486954,741908, + 4803258,5692573 }, + { 0,1,5,6,44,53,470,2847,3433,4906,13654,14710,400447,1797382, + 2744492,18775974,23541521 }, + { 0,4,9,10,16,33,83,117,318,451,5759,10015,128975,171834,211256, + 347608,1278690,2154097,2590798,3427694,5581717,21012301,27023976, + 72522811,95032729,139166747,171822389 }, + { 0,5,10,267,344,363,2968,3159,9083,18437,76602,147614,1246902, + 1593138,2035574,6529391,9511830,11340287,29565945,281666026, + 677946848 } }; + + swapfunc swapper = (scheme_ == NEST) ? + &Healpix_Base::ring2nest : &Healpix_Base::nest2ring; + + planck_assert (order_>=0, "swap_scheme(): need hierarchical map"); + + for (int m=0; m*swapper)(istart); + while (inew != istart) + { + map[iold] = map[inew]; + iold = inew; + inew = (this->*swapper)(inew); + } + map[iold] = pixbuf; + } + scheme_ = (scheme_==RING) ? NEST : RING; + } + + /*! performs the actual interpolation using \a pix and \a wgt. */ + T interpolation (const fix_arr &pix, + const fix_arr &wgt) const + { + return T(map[pix[0]]*wgt[0] + map[pix[1]]*wgt[1] + + map[pix[2]]*wgt[2] + map[pix[3]]*wgt[3]); + } + /*! Returns the interpolated map value at \a ptg */ + T interpolated_value (const pointing &ptg) const + { + fix_arr pix; + fix_arr wgt; + get_interpol (ptg, pix, wgt); + return interpolation (pix, wgt); + } + + /*! Returns a constant reference to the map data. */ + const arr &Map() const { return map; } + + /*! Returns the minimum and maximum value of the map in + \a Min and \a Max. + + This method is instantiated for \a float and \a double only. */ + void minmax (T &Min, T &Max) const; + + /*! Swaps the contents of two Healpix_Map objects. */ + void swap (Healpix_Map &other) + { + Healpix_Base::swap(other); + map.swap(other.map); + } + + /*! Returns the average of all defined map pixels. */ + double average() const + { + double avg=0; + int pix=0; + for (int m=0; m(map[m],Healpix_undef)) + { ++pix; avg+=map[m]; } + return avg/pix; + } + + /*! Adds \a val to all defined map pixels. */ + void Add (T val) + { + for (int m=0; m(map[m],Healpix_undef)) + { map[m]+=val; } + } + + /*! Multiplies all defined map pixels by \a val. */ + void Scale (T val) + { + for (int m=0; m(map[m],Healpix_undef)) + { map[m]*=val; } + } + + /*! Returns the root mean square of the map, not counting undefined + pixels. */ + double rms() const + { + using namespace std; + + double result=0; + int pix=0; + for (int m=0; m(map[m],Healpix_undef)) + { ++pix; result+=map[m]*map[m]; } + return sqrt(result/pix); + } + /*! Returns the maximum absolute value in the map, ignoring undefined + pixels. */ + T absmax() const + { + using namespace std; + + T result=0; + for (int m=0; m(map[m],Healpix_undef)) + { result = max(result,abs(map[m])); } + return result; + } + }; + +#endif diff --git a/external/healpix/Healpix_cxx/healpix_map_fitsio.cc b/external/healpix/Healpix_cxx/healpix_map_fitsio.cc new file mode 100644 index 0000000..fb8c1d0 --- /dev/null +++ b/external/healpix/Healpix_cxx/healpix_map_fitsio.cc @@ -0,0 +1,144 @@ +/* + * This file is part of Healpix_cxx. + * + * Healpix_cxx 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. + * + * Healpix_cxx 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 Healpix_cxx; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * For more information about HEALPix, see http://healpix.jpl.nasa.gov + */ + +/* + * Healpix_cxx is being developed at the Max-Planck-Institut fuer Astrophysik + * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt + * (DLR). + */ + +/* + * Copyright (C) 2003-2010 Max-Planck-Society + * Author: Martin Reinecke + */ + +#include "healpix_map_fitsio.h" +#include "healpix_map.h" +#include "fitshandle.h" + +using namespace std; + +namespace { + +unsigned int healpix_repcount (tsize npix) + { + if (npix<1024) return 1; + if ((npix%1024)==0) return 1024; + return isqrt (npix/12); + } + +} // unnamed namespace + +template void read_Healpix_map_from_fits + (fitshandle &inp, Healpix_Map &map, int colnum) + { + arr myarr; + inp.read_entire_column (colnum, myarr); + int64 nside = inp.get_key("NSIDE"); + planck_assert (int64(myarr.size())==12*nside*nside, + string("mismatch between number of map pixels (" + +dataToString(myarr.size())+") and Nside ("+dataToString(nside)+")")); + map.Set (myarr, string2HealpixScheme(inp.get_key("ORDERING"))); + } + +template void read_Healpix_map_from_fits (fitshandle &inp, + Healpix_Map &map, int colnum); +template void read_Healpix_map_from_fits (fitshandle &inp, + Healpix_Map &map, int colnum); +template void read_Healpix_map_from_fits (fitshandle &inp, + Healpix_Map &map, int colnum); + + +template void read_Healpix_map_from_fits + (const string &filename, Healpix_Map &map, int colnum, int hdunum) + { + fitshandle inp; + inp.open (filename); + inp.goto_hdu (hdunum); + read_Healpix_map_from_fits (inp,map,colnum); + } + +template void read_Healpix_map_from_fits (const string &filename, + Healpix_Map &map, int colnum, int hdunum); +template void read_Healpix_map_from_fits (const string &filename, + Healpix_Map &map, int colnum, int hdunum); +template void read_Healpix_map_from_fits (const string &filename, + Healpix_Map &map, int colnum, int hdunum); + + +void prepare_Healpix_fitsmap + (fitshandle &out, const Healpix_Base &base, PDT datatype, + const arr &colname) + { + vector cols; + int repcount = healpix_repcount (base.Npix()); + for (tsize m=0; m void write_Healpix_map_to_fits + (fitshandle &out, const Healpix_Map &map, PDT datatype) + { + arr colname(1); + colname[0] = "signal"; + prepare_Healpix_fitsmap (out, map, datatype, colname); + out.write_column(1,map.Map()); + } + +template void write_Healpix_map_to_fits + (fitshandle &out, const Healpix_Map &map, PDT datatype); +template void write_Healpix_map_to_fits + (fitshandle &out, const Healpix_Map &map, PDT datatype); +template void write_Healpix_map_to_fits + (fitshandle &out, const Healpix_Map &map, PDT datatype); + + +template void write_Healpix_map_to_fits + (fitshandle &out, const Healpix_Map &mapT, + const Healpix_Map &mapQ, const Healpix_Map &mapU, PDT datatype) + { + arr colname(3); + colname[0] = "signal"; + colname[1] = "Q-pol"; + colname[2] = "U-pol"; + prepare_Healpix_fitsmap (out, mapT, datatype, colname); + out.write_column(1,mapT.Map()); + out.write_column(2,mapQ.Map()); + out.write_column(3,mapU.Map()); + } + +template void write_Healpix_map_to_fits + (fitshandle &out, const Healpix_Map &mapT, + const Healpix_Map &mapQ, const Healpix_Map &mapU, + PDT datatype); +template void write_Healpix_map_to_fits + (fitshandle &out, const Healpix_Map &mapT, + const Healpix_Map &mapQ, const Healpix_Map &mapU, + PDT datatype); diff --git a/external/healpix/Healpix_cxx/healpix_map_fitsio.h b/external/healpix/Healpix_cxx/healpix_map_fitsio.h new file mode 100644 index 0000000..9ed99a0 --- /dev/null +++ b/external/healpix/Healpix_cxx/healpix_map_fitsio.h @@ -0,0 +1,111 @@ +/* + * This file is part of Healpix_cxx. + * + * Healpix_cxx 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. + * + * Healpix_cxx 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 Healpix_cxx; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * For more information about HEALPix, see http://healpix.jpl.nasa.gov + */ + +/* + * Healpix_cxx is being developed at the Max-Planck-Institut fuer Astrophysik + * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt + * (DLR). + */ + +/*! \file healpix_map_fitsio.h + * Copyright (C) 2003-2010 Max-Planck-Society + * \author Martin Reinecke + */ + +#ifndef HEALPIX_MAP_FITSIO_H +#define HEALPIX_MAP_FITSIO_H + +#include +#include "datatypes.h" +#include "fitshandle.h" + +class Healpix_Base; + +template class arr; +template class Healpix_Map; + +/*! \defgroup healpix_map_fitsio_group FITS-based I/O of HEALPix maps */ +/*! \{ */ + +/*! Reads the map stored in column \a colnum of the FITS binary table + pointed to by \a inp into \a map. */ +template void read_Healpix_map_from_fits + (fitshandle &inp, Healpix_Map &map, int colnum=1); +/*! Opens the FITS file \a filename, jumps to the HDU \a hdunum, + and reads the column \a colnum into \a map. */ +template void read_Healpix_map_from_fits + (const std::string &filename, Healpix_Map &map, int colnum=1, + int hdunum=2); + +template inline void read_Healpix_map_from_fits + (const std::string &filename, Healpix_Map &mapT, Healpix_Map &mapQ, + Healpix_Map &mapU, int hdunum=2) + { + fitshandle inp; + inp.open(filename); + inp.goto_hdu(hdunum); + read_Healpix_map_from_fits(inp,mapT,1); + read_Healpix_map_from_fits(inp,mapQ,2); + read_Healpix_map_from_fits(inp,mapU,3); + } + +/*! Inserts a new binary table into \a out, which contains one column + of Planck type \a datatype with the name \a name, and writes all HEALPix + specific keywords based on the information in \a base. */ +void prepare_Healpix_fitsmap + (fitshandle &out, const Healpix_Base &base, PDT datatype, + const arr &colname); + +/*! Inserts a new binary table into \a out, which contains one column + of Planck type \a datatype, and stores \a map into this column. */ +template void write_Healpix_map_to_fits + (fitshandle &out, const Healpix_Map &map, PDT datatype); +/*! Inserts a new binary table into \a out, which contains three columns + of Planck type \a datatype, and stores \a mapT, \a mapQ and \a mapU + into these columns. */ +template void write_Healpix_map_to_fits + (fitshandle &out, const Healpix_Map &mapT, + const Healpix_Map &mapQ, const Healpix_Map &mapU, PDT datatype); + +/*! Creates a new FITS file with the name \a outfile, with a binary table in + HDU 2, which contains one column of Planck type \a datatype, and stores + \a map into this column. */ +template inline void write_Healpix_map_to_fits + (const std::string &outfile, const Healpix_Map &map, PDT datatype) + { + fitshandle out; + out.create (outfile); + write_Healpix_map_to_fits (out,map,datatype); + } +/*! Creates a new FITS file with the name \a outfile, with a binary table in + HDU 2, which contains three columns of Planck type \a datatype, and stores + \a mapT, \a mapQ and \a mapU into this column. */ +template inline void write_Healpix_map_to_fits + (const std::string &outfile, const Healpix_Map &mapT, + const Healpix_Map &mapQ, const Healpix_Map &mapU, PDT datatype) + { + fitshandle out; + out.create (outfile); + write_Healpix_map_to_fits (out,mapT,mapQ,mapU,datatype); + } + +/*! \} */ + +#endif diff --git a/external/healpix/Healpix_cxx/hotspots_cxx.cc b/external/healpix/Healpix_cxx/hotspots_cxx.cc new file mode 100644 index 0000000..85d48c4 --- /dev/null +++ b/external/healpix/Healpix_cxx/hotspots_cxx.cc @@ -0,0 +1,9 @@ +#include "levels_facilities.h" +#include "error_handling.h" + +int main (int argc, const char **argv) + { + PLANCK_DIAGNOSIS_BEGIN + hotspots_cxx_module (argc, argv); + PLANCK_DIAGNOSIS_END + } diff --git a/external/healpix/Healpix_cxx/hotspots_cxx_module.cc b/external/healpix/Healpix_cxx/hotspots_cxx_module.cc new file mode 100644 index 0000000..f4e257a --- /dev/null +++ b/external/healpix/Healpix_cxx/hotspots_cxx_module.cc @@ -0,0 +1,97 @@ +/* + * This file is part of Healpix_cxx. + * + * Healpix_cxx 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. + * + * Healpix_cxx 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 Healpix_cxx; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * For more information about HEALPix, see http://healpix.jpl.nasa.gov + */ + +/* + * Healpix_cxx is being developed at the Max-Planck-Institut fuer Astrophysik + * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt + * (DLR). + */ + +/* + * Copyright (C) 2003-2010 Max-Planck-Society + * Author: Martin Reinecke + */ + +#include +#include "cxxutils.h" +#include "paramfile.h" +#include "healpix_map.h" +#include "healpix_map_fitsio.h" +#include "fitshandle.h" +#include "levels_facilities.h" + +using namespace std; + +int hotspots_cxx_module (int argc, const char **argv) + { + module_startup ("hotspots_cxx", argc, argv, 2, ""); + paramfile params (argv[1]); + + string infile = params.find("infile"); + string mapfile = params.find("outmap",""); + bool have_mapfile = mapfile!=""; + string minfile = params.find("minfile",""); + bool have_minfile = minfile!=""; + string maxfile = params.find("maxfile",""); + bool have_maxfile = maxfile!=""; + planck_assert (have_mapfile || have_minfile || have_maxfile, + "no output file specified"); + + Healpix_Map inmap; + read_Healpix_map_from_fits(infile,inmap,1,2); + Healpix_Map outmap; + if (have_mapfile) outmap.Set(inmap.Order(),inmap.Scheme()); + + ofstream minout, maxout; + if (have_minfile) minout.open(minfile.c_str()); + if (have_maxfile) maxout.open(maxfile.c_str()); + + fix_arr nb; +// FIXME: This should be parallelized + for (int m=0; m(value, Healpix_undef)) + { + inmap.neighbors(m,nb); + bool ismax=true, ismin=true; + for (tsize n=0; n=0) + { + float nbval = inmap[nb[n]]; + if (!approx(nbval, Healpix_undef)) + { + if (nbval>=value) ismax=false; + if (nbval<=value) ismin=false; + } + } + } + if (have_mapfile) + outmap[m] = float((ismax||ismin) ? value : Healpix_undef); + if (have_minfile && ismin) minout << m << " " << value << endl; + if (have_maxfile && ismax) maxout << m << " " << value << endl; + } + } + if (have_mapfile) + write_Healpix_map_to_fits (mapfile,outmap,PLANCK_FLOAT32); + + return 0; + } diff --git a/external/healpix/Healpix_cxx/hpxtest.cc b/external/healpix/Healpix_cxx/hpxtest.cc new file mode 100644 index 0000000..64a7619 --- /dev/null +++ b/external/healpix/Healpix_cxx/hpxtest.cc @@ -0,0 +1,709 @@ +/* + * This file is part of Healpix_cxx. + * + * Healpix_cxx 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. + * + * Healpix_cxx 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 Healpix_cxx; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * For more information about HEALPix, see http://healpix.jpl.nasa.gov + */ + +/* + * Healpix_cxx 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, 2005, 2006, 2007, 2008 Max-Planck-Society + * Author: Martin Reinecke + */ + +/* + +Candidates for testing the validity of the Healpix routines: + +- done: ang2pix(pix2ang(i)) = i for all Healpix_Bases +- done: pix2ang(ang2pix(ptg)) dot ptg > 1-delta for all Healpix_Bases +- done: ring2nest(nest2ring(i)) = i for all hierarchical Healpix_Bases +- done: downgrade(upgrade(map)) = map for all maps +- done: map and downgraded map should have same average +- done: alm2map(map2alm(map)) approx map (same for pol) +- partly done: neighbor tests +- powspec -> alm -> powspec (should produce similar powspecs, also for pol) +- done: two swap_schemes() should produce original map +- done: query_disc tests (dot products etc.) +- a_lms: test Set(), Scale(), Add(), alm(l,m) = alm.mstart(m)[l], etc. + +*/ + +#include +#include "healpix_base.h" +#include "healpix_base2.h" +#include "healpix_map.h" +#include "arr.h" +#include "planck_rng.h" +#include "lsconstants.h" +#include "alm.h" +#include "alm_healpix_tools.h" +#include "alm_powspec_tools.h" +#include "geom_utils.h" + +using namespace std; + +const int nsamples = 1000000; + +planck_rng rng; + +namespace { + +void random_dir (pointing &ptg) + { + ptg.theta = acos(rng.rand_uni()*2-1); + ptg.phi = rng.rand_uni()*twopi; + } + +void check_ringnestring() + { + cout << "testing ring2nest(nest2ring(m))==m" << endl; + for (int order=0; order<=13; ++order) + { + cout << "order = " << order << endl; + Healpix_Base base (order,RING); + for (int m=0; m=0) && (v_angle(base2.pix2ang(nb[n]),pixpt)>maxang)) + cout << " PROBLEM2: order = " << order << ", pix = " << pix << endl; + } + } + for (int nside=3; nside<(1<<13); nside+=nside/2+1) + { + cout << "nside = " << nside << endl; + Healpix_Base base (nside,RING,SET_NSIDE); + double maxang = 2.01*base.max_pixrad(); + for (int m=0; m nb; + vec3 pixpt = base.pix2ang(pix); + base.neighbors(pix,nb); + for (int n=0; n<8; ++n) + if ((nb[n]>=0) && (v_angle(base.pix2ang(nb[n]),pixpt)>maxang)) + cout << " PROBLEM: nside = " << nside << ", pix = " << pix << endl; + } + } + } +void check_neighbors2() + { + cout << "testing neighbor function" << endl; + for (int order=0; order<=29; ++order) + { + cout << "order = " << order << endl; + Healpix_Base2 base (order,NEST), base2(order,RING); + double maxang = 2.01*base.max_pixrad(); + for (int m=0; m nb; + vec3 pixpt = base.pix2ang(pix); + base.neighbors(pix,nb); + sort(&nb[0],&nb[0]+8); + int check=0; + for (int n=0; n<8; ++n) + { + if (nb[n]<0) + { + ++check; + } + else + { + if (v_angle(base.pix2ang(nb[n]),pixpt)>maxang) + cout << " PROBLEM: order = " << order << ", pix = " << pix << endl; + if ((n>0) && (nb[n]==nb[n-1])) + cout << " PROBLEM: order = " << order << ", pix = " << pix << endl; + } + } + planck_assert((check<=1)||((order==0)&&(check<=2)),"too few neighbors"); + pixpt = base2.pix2ang(pix); + base2.neighbors(pix,nb); + for (int n=0; n<8; ++n) + if ((nb[n]>=0) && (v_angle(base2.pix2ang(nb[n]),pixpt)>maxang)) + cout << " PROBLEM2: order = " << order << ", pix = " << pix << endl; + } + } + for (int nside=3; nside<(1<<29); nside+=nside/2+1) + { + cout << "nside = " << nside << endl; + Healpix_Base2 base (nside,RING,SET_NSIDE); + double maxang = 2.01*base.max_pixrad(); + for (int m=0; m nb; + vec3 pixpt = base.pix2ang(pix); + base.neighbors(pix,nb); + for (int n=0; n<8; ++n) + if ((nb[n]>=0) && (v_angle(base.pix2ang(nb[n]),pixpt)>maxang)) + cout << " PROBLEM: nside = " << nside << ", pix = " << pix << endl; + } + } + } + +void check_swap_scheme() + { + cout << "testing whether double swap_scheme() returns the original map" + << endl << "(for orders 0 to 10)." << endl; + for (int order=0; order<=10; ++order) + { + cout << "order = " << order << endl; + Healpix_Map map(order,NEST); + for (int m=0; m >&almT, Alm >&almG, + Alm >&almC, int lmax, int mmax) + { + almT.Set(lmax,mmax); almG.Set(lmax,mmax); almC.Set(lmax,mmax); + + for (int l=0; l<=lmax; ++l) + { + almT(l,0).re=rng.rand_gauss(); almT(l,0).im=0.; + almG(l,0).re=rng.rand_gauss(); almG(l,0).im=0.; + almC(l,0).re=rng.rand_gauss(); almC(l,0).im=0.; + } + + for (int m=1; m<=mmax; ++m) + for (int l=m; l<=lmax; ++l) + { + almT(l,m).re=rng.rand_gauss(); almT(l,m).im=rng.rand_gauss(); + almG(l,m).re=rng.rand_gauss(); almG(l,m).im=rng.rand_gauss(); + almC(l,m).re=rng.rand_gauss(); almC(l,m).im=rng.rand_gauss(); + } + almG(0,0)=almC(0,0)=almG(1,0)=almC(1,0)=almG(1,1)=almC(1,1)=0; + } + +void random_alm (Alm >&alm, int lmax, int mmax) + { + alm.Set(lmax,mmax); + + for (int l=0; l<=lmax; ++l) + { alm(l,0).re=rng.rand_gauss(); alm(l,0).im=0.; } + + for (int m=1; m<=mmax; ++m) + for (int l=m; l<=lmax; ++l) + { alm(l,m).re=rng.rand_gauss(); alm(l,m).im=rng.rand_gauss(); } + } + +void check_alm (const Alm >&oalm, + const Alm >&alm, double epsilon) + { + for (int m=0; m<=alm.Mmax(); ++m) + for (int l=m; l<=alm.Lmax(); ++l) + { + if (!abs_approx(oalm(l,m).re,alm(l,m).re,epsilon)) + cout << "Problemr " << l << " " << m << endl; + if (!abs_approx(oalm(l,m).im,alm(l,m).im,epsilon)) + cout << "Problemi " << l << " " << m << endl; + } + } + +void check_alm2map2alm (int lmax, int mmax, int nside) + { + cout << "testing whether a_lm->map->a_lm returns original a_lm" << endl; + cout << "lmax=" << lmax <<", mmax=" << mmax << ", nside=" << nside << endl; + const double epsilon = 1e-8; + Alm > oalmT(lmax,mmax),almT(lmax,mmax), + oalmG(lmax,mmax),almG(lmax,mmax),oalmC(lmax,mmax),almC(lmax,mmax); + Healpix_Map mapT(nside,RING,SET_NSIDE), mapQ(nside,RING,SET_NSIDE), + mapU(nside,RING,SET_NSIDE); + + random_alm(oalmT,oalmG,oalmC,lmax,mmax); + alm2map(oalmT,mapT); + map2alm_iter2(mapT,almT,1e-12,1e-12); + check_alm (oalmT, almT, epsilon); + + alm2map_spin(oalmG,oalmC,mapQ,mapU,1); + map2alm_spin_iter2(mapQ,mapU,almG,almC,1,1e-12,1e-12); + check_alm (oalmG, almG, epsilon); + check_alm (oalmC, almC, epsilon); + + alm2map_pol(oalmT,oalmG,oalmC,mapT,mapQ,mapU); + map2alm_pol_iter2(mapT,mapQ,mapU,almT,almG,almC,1e-12,1e-12); + check_alm (oalmT, almT, epsilon); + check_alm (oalmG, almG, epsilon); + check_alm (oalmC, almC, epsilon); + } + +void check_smooth_alm () + { + cout << "testing whether unsmooth(smooth(a_lm)) returns a_lm" << endl; + const double epsilon = 1e-14; + const double fwhm = 100.*arcmin2rad; + const int lmax=300, mmax=300; + Alm > oalmT(lmax,mmax),almT(lmax,mmax), + oalmG(lmax,mmax),almG(lmax,mmax),oalmC(lmax,mmax),almC(lmax,mmax); + + random_alm(oalmT,oalmG,oalmC,lmax,mmax); + + almT=oalmT; almG=oalmG; almC=oalmC; + smoothWithGauss (almT, fwhm); + smoothWithGauss (almT, -fwhm); + check_alm (oalmT, almT, epsilon); + almT=oalmT; + smoothWithGauss (almT, almG, almC, fwhm); + smoothWithGauss (almT, almG, almC, -fwhm); + check_alm (oalmT, almT, epsilon); + check_alm (oalmG, almG, epsilon); + check_alm (oalmC, almC, epsilon); + } + +void check_rot_alm () + { + cout << "testing whether rot^-1(rot(a_lm)) returns a_lm" << endl; + const double epsilon = 2e-13; + const int lmax=300; + Alm > oalm(lmax,lmax),alm(lmax,lmax); + + random_alm(oalm,lmax,lmax); + + alm=oalm; + rotate_alm (alm,3,4,5); + rotate_alm (alm,-5,-4,-3); + check_alm (oalm, alm, epsilon); + } + +} // unnamed namespace + +int main(int argc, const char **argv) + { + module_startup ("hpxtest",argc,argv,1,""); + + check_smooth_alm(); + check_rot_alm(); + check_alm2map2alm(620,620,256); + check_alm2map2alm(620,2,256); + check_average(); + check_import(); + check_neighbors(); + check_neighbors2(); + check_pixangpix(); + check_pixangpix2(); + check_pixvecpix(); + check_pixvecpix2(); + check_angpixang(); + check_angpixang2(); + check_ringnestring(); + check_ringnestring2(); + check_nestpeanonest(); + check_nestpeanonest2(); + check_query_disc(); + check_swap_scheme(); + } diff --git a/external/healpix/Healpix_cxx/map2tga.cc b/external/healpix/Healpix_cxx/map2tga.cc new file mode 100644 index 0000000..6cb6da3 --- /dev/null +++ b/external/healpix/Healpix_cxx/map2tga.cc @@ -0,0 +1,9 @@ +#include "levels_facilities.h" +#include "error_handling.h" + +int main (int argc, const char **argv) + { + PLANCK_DIAGNOSIS_BEGIN + map2tga_module (argc, argv); + PLANCK_DIAGNOSIS_END + } diff --git a/external/healpix/Healpix_cxx/map2tga.par.txt b/external/healpix/Healpix_cxx/map2tga.par.txt new file mode 100644 index 0000000..1cfc2a3 --- /dev/null +++ b/external/healpix/Healpix_cxx/map2tga.par.txt @@ -0,0 +1,76 @@ +Usage: + map2tga + +or: + map2tga [-sig ] [-pal ] + [-xsz ] [-bar] [-log] [-asinh] [-lon ] [-lat ] + [-mul ] [-add ] [-min ] [-max ] + [-res ] [-title ] [-flippal] [-gnomonic] + [-interpol] [-equalize] [-viewer ] + + +Parameters read by map2tga: + +infile (string): + input file containing the Healpix map + +outfile (string): + output TGA file + +sig (integer, default=1): + column number of the requested Healpix map + +pal (integer, default=4): + number of the color palette + +flippal (bool, default=false): + whether the palette should be flipped + +xsz (integer, default=1024): + number of image pixels in x direction + +bar (logical, default=false): + whether a color bar should be added to the image + +log (logical, default=false): + whether the logarithm of the map values should be displayed + +equalize (logical, default=false): + whether histogram equalisation should be performed + +asinh (logical, default=false): + whether the hyperbolic arcsine of the map values should be displayed + +lon (double, default=0): + the longitude (in degrees) of the image center + +lat (double, default=0): + the latitude (in degrees) of the image center + +mul (double, default=1): + scale factor applied to the data + +add (double, default=0): + offset added to the data (before multiplication) + +min (double, optional): + if specified, this value is used as minimum of the color scale + +max (double, optional): + if specified, this value is used as maximum of the color scale + +res (double, default=1): + only for gnomonic projection: the size (in arcmin) of an image pixel + +title (string, optional): + if specified, this value is used as the image title + +viewer (string, optional): + if specified, this executable is used to show the resulting image + +pro (string, default="mollw"): + if this is equal to "gno", gnomonic projection is used, else Mollweide + +interpol (bool, default=false): + false: no interpolation + true : bilinear interpolation diff --git a/external/healpix/Healpix_cxx/map2tga_module.cc b/external/healpix/Healpix_cxx/map2tga_module.cc new file mode 100644 index 0000000..f321e62 --- /dev/null +++ b/external/healpix/Healpix_cxx/map2tga_module.cc @@ -0,0 +1,388 @@ +/* + * This file is part of Healpix_cxx. + * + * Healpix_cxx 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. + * + * Healpix_cxx 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 Healpix_cxx; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * For more information about HEALPix, see http://healpix.jpl.nasa.gov + */ + +/* + * Healpix_cxx is being developed at the Max-Planck-Institut fuer Astrophysik + * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt + * (DLR). + */ + +/* + * Copyright (C) 2003-2010 Max-Planck-Society + * Author: Martin Reinecke + */ + +#include +#include +#include +#include "healpix_map.h" +#include "healpix_map_fitsio.h" +#include "rotmatrix.h" +#include "pointing.h" +#include "ls_image.h" +#include "paramfile.h" +#include "levels_facilities.h" +#include "lsconstants.h" + +using namespace std; + +namespace { + +void histo_eq (arr2 &img, float &minv, float &maxv, arr &newpos) + { + const int nbins=100; + arr bincnt (nbins); + bincnt.fill(0); + int pixels=0; + + double fact = 1./(maxv-minv); + for (tsize i=0; i-1e30) + { + img[i][j] = float((img[i][j]-minv)*fact); + int idx = int(img[i][j]*nbins); + idx=max(0,min(idx,nbins-1)); + ++bincnt[idx]; + ++pixels; + } + + newpos.alloc(nbins+1); + int accu=0; + for (int m=0; m-1e30) + { + int idx = int(img[i][j]*nbins); + idx=max(0,min(idx,nbins-1)); + double frac = nbins*img[i][j] - idx; + img[i][j] = float((1-frac)*newpos[idx] + frac*newpos[idx+1]); + img[i][j] = float(minv+(maxv-minv)*img[i][j]); + } + } + +void pro_mollw (const Healpix_Map &map, double lon0, double lat0, + int xsize, arr2 &img, float &minv, float &maxv, bool smooth) + { + int ysize=xsize/2; + img.alloc(xsize,ysize); + img.fill(-1e35); + double xc=(xsize-1)/2., yc=(ysize-1)/2.; + + rotmatrix rot; + rot.Make_CPAC_Euler_Matrix(0,-lat0,-lon0); + + minv=1e30; + maxv=-1e30; + for (tsize i=0; i(img[i][j],Healpix_undef)) + { + if (img[i][j]maxv) maxv=img[i][j]; + } + } + } + } + +void pro_gno (const Healpix_Map &map, double lon0, double lat0, + int xsize, double delta, arr2 &img, float &minv, float &maxv, + bool smooth) + { + rotmatrix rot; + rot.Make_CPAC_Euler_Matrix(lon0,-lat0,0); + + double start=-(xsize/2.)*delta; + img.alloc(xsize,xsize); + minv=1e30; + maxv=-1e30; + for (tsize i=0; i(img[i][j],Healpix_undef)) + { + if (img[i][j]maxv) maxv=img[i][j]; + } + } + } + +void colorbar (LS_Image &img, const Palette &pal, int xmin, int xmax, + int ymin, int ymax, bool flippal, const arr &newpos) + { + int nbins = newpos.size()-1; + for (int i=xmin; i<=xmax; ++i) + { + double val = (double(i)-xmin)/(xmax-xmin); + if (nbins>0) + { + int idx = int(val*nbins); + idx=max(0,min(idx,nbins-1)); + double frac = nbins*val - idx; + val = (1-frac)*newpos[idx] + frac*newpos[idx+1]; + } + if (flippal) val=1-val; + Colour c = pal.Get_Colour(float(val)); + for (int j=ymin; j<=ymax; ++j) + img.put_pixel(i,j,c); + } + } + +string conv (double val) + { + ostringstream os; + if (abs(val)>100 || abs(val)<0.01) + { + os << setw(10) << setprecision(3) << scientific << val; + return os.str(); + } + os << setw(10) << setprecision(6) << fixed << val; + return trim(os.str()); + } + +void usage() + { + cout << + "\nUsage:\n" + " map2tga \n\n" + "or:\n" + " map2tga [-sig ] [-pal ]\n" + " [-xsz ] [-bar] [-log] [-asinh] [-lon ] [-lat ]\n" + " [-mul ] [-add ] [-min ] [-max ]\n" + " [-res ] [-title ] [-flippal] [-gnomonic]\n" + " [-interpol] [-equalize] [-viewer ]\n\n"; + planck_fail_quietly("Incorrect usage"); + } + +} // unnamed namespace + +int map2tga_module (int argc, const char **argv) + { + announce ("map2tga"); + if (argc<2) usage(); + + string infile = ""; + string outfile = ""; + string title = ""; + int xres = 1024; + bool bar = false, mollpro=true; + double lat0=0, lon0=0, res=1*arcmin2rad; + float usermin=-1e30, usermax=1e30, offset=0, factor=1; + bool min_supplied=false, max_supplied=false; + bool logflag=false, asinhflag=false, eqflag=false; + int palnr = 4; + int colnum=1; + bool flippal = false; + bool interpol = false; + string viewer = ""; + + if (argc>2) + { + infile = argv[1]; + outfile = argv[2]; + int m=3; + while (m("infile"); + outfile = params.find("outfile"); + colnum = params.find("sig",colnum); + palnr = params.find("pal",palnr); + flippal = params.find("flippal",flippal); + xres = params.find("xsz",xres); + bar = params.find("bar",bar); + logflag = params.find("log",logflag); + eqflag = params.find("equalize",eqflag); + asinhflag = params.find("asinh",asinhflag); + lon0 = degr2rad*params.find("lon",lon0); + lat0 = degr2rad*params.find("lat",lat0); + factor = params.find("mul",factor); + offset = params.find("add",offset); + usermin = params.find("min", usermin); + if (usermin>-1e29) min_supplied = true; + usermax = params.find("max", usermax); + if (usermax<1e29) max_supplied = true; + res = arcmin2rad*params.find("res",res); + title = params.find("title",""); + viewer = params.find("viewer",""); + string tmp = params.find("pro",""); + if (tmp == "gno") mollpro=false; + interpol = params.find("interpol",interpol); + } + + Healpix_Map map(0,RING); + read_Healpix_map_from_fits(infile,map,colnum,2); + for (int m=0; m(map[m],Healpix_undef)) + { + map[m] = (map[m]+offset)*factor; + if (logflag) + { + if (map[m]<=0) + map[m] = Healpix_undef; + else + map[m] = float(log(double(map[m]))/ln10); + } + if (asinhflag) + { + if (map[m]>=0) + map[m] = float(log(double(map[m]+sqrt(map[m]*map[m]+1)))); + else + map[m] = float(-log(double(-map[m]+sqrt(map[m]*map[m]+1)))); + } + if (min_supplied) if (map[m] < usermin) map[m] = usermin; + if (max_supplied) if (map[m] > usermax) map[m] = usermax; + } + } + + arr2 imgarr; + float minv, maxv; + if (mollpro) + pro_mollw (map,lon0,lat0,xres,imgarr,minv,maxv,interpol); + else + pro_gno (map,lon0,lat0,xres,res,imgarr,minv,maxv,interpol); + + arr newpos; + if (eqflag) histo_eq(imgarr,minv,maxv,newpos); + + if (min_supplied) minv = usermin; + if (max_supplied) maxv = usermax; + if (maxv==minv) maxv=minv+1e-10f; + + int xsz=imgarr.size1(); + int ysz=imgarr.size2(); + int yofs=ysz; + int scale = max(1,xsz/800); + if (bar) ysz+=60*scale; + if (title != "") { ysz+=50*scale; yofs+=50*scale; } + LS_Image img(xsz,ysz); + img.fill(Colour(1,1,1)); + img.set_font (giant_font); + Palette pal; + pal.setPredefined(palnr); + if (title != "") + img.annotate_centered(xsz/2,25*scale,Colour(0,0,0),title,scale); + for (tsize i=0; i-1e32) + { + Colour c(0.5,0.5,0.5); + if (!approx(imgarr[i][j],Healpix_undef)) + { + int col = int((imgarr[i][j]-minv)/(maxv-minv)*256); + col = min(255,max(col,0)); + float colfrac = (imgarr[i][j]-minv)/(maxv-minv); + if (flippal) colfrac = 1-colfrac; + c = pal.Get_Colour(colfrac); + } + img.put_pixel(i,yofs-j-1,c); + } + } + + if (bar) + { + colorbar (img,pal,xsz/10,(xsz*9)/10,ysz-40*scale,ysz-20*scale,flippal, + newpos); + img.set_font (medium_bold_font); + img.annotate_centered (xsz/20,ysz-30*scale,Colour(0,0,0),conv(minv),scale); + img.annotate_centered ((xsz*19)/20,ysz-30*scale,Colour(0,0,0),conv(maxv), + scale); + } + img.write_TGA(outfile); + + if (viewer!="") + { + int retcode = system((viewer+" "+outfile).c_str()); + if (retcode != 0) + cout << "Warning: viewer return code was " << retcode << endl; + } + + return 0; + } diff --git a/external/healpix/Healpix_cxx/median_filter_cxx.cc b/external/healpix/Healpix_cxx/median_filter_cxx.cc new file mode 100644 index 0000000..91b6b24 --- /dev/null +++ b/external/healpix/Healpix_cxx/median_filter_cxx.cc @@ -0,0 +1,9 @@ +#include "levels_facilities.h" +#include "error_handling.h" + +int main (int argc, const char **argv) + { + PLANCK_DIAGNOSIS_BEGIN + median_filter_cxx_module (argc, argv); + PLANCK_DIAGNOSIS_END + } diff --git a/external/healpix/Healpix_cxx/median_filter_cxx_module.cc b/external/healpix/Healpix_cxx/median_filter_cxx_module.cc new file mode 100644 index 0000000..a228b7e --- /dev/null +++ b/external/healpix/Healpix_cxx/median_filter_cxx_module.cc @@ -0,0 +1,80 @@ +/* + * This file is part of Healpix_cxx. + * + * Healpix_cxx 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. + * + * Healpix_cxx 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 Healpix_cxx; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * For more information about HEALPix, see http://healpix.jpl.nasa.gov + */ + +/* + * Healpix_cxx 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-2010 Max-Planck-Society + * Author: Martin Reinecke + */ + +#include "cxxutils.h" +#include "healpix_map.h" +#include "healpix_map_fitsio.h" +#include "fitshandle.h" +#include "levels_facilities.h" +#include "lsconstants.h" + +using namespace std; + +namespace { + +template typename iterator_traits::value_type + median(Iterator first, Iterator last) + { + Iterator mid = first+(last-first-1)/2; + nth_element(first,mid,last); + if ((last-first)&1) return *mid; + return typename iterator_traits::value_type + (0.5*((*mid)+(*min_element(mid+1,last)))); + } + +} // unnamed namespace + +int median_filter_cxx_module (int argc, const char **argv) + { + module_startup ("median_filter_cxx", argc, argv, 4, + " "); + + double radius = stringToData(argv[3])*arcmin2rad; + + Healpix_Map inmap; + read_Healpix_map_from_fits(argv[1],inmap,1,2); + Healpix_Map outmap (inmap.Nside(), inmap.Scheme(), SET_NSIDE); + + vector list; + vector list2; + for (int m=0; m0)||(nside_pixwin_out>0)) + healpix_data (string): + directory containing the Healpix data files +endif + +double_precision (bool, default=false): + if false, the a_lm are read/written in single precision, + otherwise in double precision. diff --git a/external/healpix/Healpix_cxx/mult_alm_module.cc b/external/healpix/Healpix_cxx/mult_alm_module.cc new file mode 100644 index 0000000..0d9584f --- /dev/null +++ b/external/healpix/Healpix_cxx/mult_alm_module.cc @@ -0,0 +1,124 @@ +/* + * This file is part of Healpix_cxx. + * + * Healpix_cxx 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. + * + * Healpix_cxx 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 Healpix_cxx; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * For more information about HEALPix, see http://healpix.jpl.nasa.gov + */ + +/* + * Healpix_cxx is being developed at the Max-Planck-Institut fuer Astrophysik + * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt + * (DLR). + */ + +/* + * Copyright (C) 2003-2010 Max-Planck-Society + * Author: Martin Reinecke + */ + +#include "xcomplex.h" +#include "cxxutils.h" +#include "paramfile.h" +#include "healpix_data_io.h" +#include "alm.h" +#include "alm_fitsio.h" +#include "alm_powspec_tools.h" +#include "fitshandle.h" +#include "levels_facilities.h" +#include "lsconstants.h" + +using namespace std; + +namespace { + +template void mult_alm (paramfile ¶ms) + { + string infile = params.template find("infile"); + string outfile = params.template find("outfile"); + int nside_pixwin_in = params.template find("nside_pixwin_in",0); + planck_assert (nside_pixwin_in>=0,"nside_pixwin_in must be >= 0"); + int nside_pixwin_out = params.template find("nside_pixwin_out",0); + planck_assert (nside_pixwin_out>=0,"nside_pixwin_out must be >= 0"); + double fwhm_in = arcmin2rad*params.template find("fwhm_arcmin_in",0); + planck_assert (fwhm_in>=0,"fwhm_arcmin_in must be >= 0"); + double fwhm_out = arcmin2rad*params.template find("fwhm_arcmin_out",0); + planck_assert (fwhm_out>=0,"fwhm_arcmin_out must be >= 0"); + + string datadir; + if ((nside_pixwin_in>0) || (nside_pixwin_out>0)) + datadir = params.template find("healpix_data"); + + bool polarisation = params.template find("polarisation"); + if (!polarisation) + { + int nlmax, nmmax; + get_almsize(infile, nlmax, nmmax, 2); + Alm > alm; + read_Alm_from_fits(infile,alm,nlmax,nmmax,2); + if (fwhm_in>0) smoothWithGauss (alm, -fwhm_in); + arr temp(nlmax+1); + if (nside_pixwin_in>0) + { + read_pixwin(datadir,nside_pixwin_in,temp); + for (int l=0; l<=nlmax; ++l) + temp[l] = 1/temp[l]; + alm.ScaleL (temp); + } + if (nside_pixwin_out>0) + { + read_pixwin(datadir,nside_pixwin_out,temp); + alm.ScaleL (temp); + } + if (fwhm_out>0) smoothWithGauss (alm, fwhm_out); + write_Alm_to_fits (outfile,alm,nlmax,nmmax,planckType()); + } + else + { + int nlmax, nmmax; + get_almsize_pol(infile, nlmax, nmmax); + Alm > almT, almG, almC; + read_Alm_from_fits(infile,almT,almG,almC,nlmax,nmmax,2); + if (fwhm_in>0) smoothWithGauss (almT, almG, almC, -fwhm_in); + arr temp(nlmax+1), pol(nlmax+1); + if (nside_pixwin_in>0) + { + read_pixwin(datadir,nside_pixwin_in,temp,pol); + for (int l=0; l<=nlmax; ++l) + { temp[l] = 1/temp[l]; pol[l] = 1/pol[l]; } + almT.ScaleL(temp); almG.ScaleL(pol); almC.ScaleL(pol); + } + if (nside_pixwin_out>0) + { + read_pixwin(datadir,nside_pixwin_out,temp,pol); + almT.ScaleL(temp); almG.ScaleL(pol); almC.ScaleL(pol); + } + if (fwhm_out>0) smoothWithGauss (almT, almG, almC, fwhm_out); + write_Alm_to_fits (outfile,almT,almG,almC,nlmax,nmmax,planckType()); + } + } + +} // unnamed namespace + +int mult_alm_module (int argc, const char **argv) + { + module_startup ("mult_alm", argc, argv, 2, ""); + paramfile params (argv[1]); + + bool dp = params.find ("double_precision",false); + dp ? mult_alm(params) : mult_alm(params); + + return 0; + } diff --git a/external/healpix/Healpix_cxx/planck.make b/external/healpix/Healpix_cxx/planck.make new file mode 100644 index 0000000..87bc1cf --- /dev/null +++ b/external/healpix/Healpix_cxx/planck.make @@ -0,0 +1,27 @@ +PKG:=Healpix_cxx + +SD:=$(SRCROOT)/$(PKG) +OD:=$(BLDROOT)/$(PKG) + +FULL_INCLUDE+= -I$(SD) + +HDR_$(PKG):=$(SD)/*.h +LIB_$(PKG):=$(LIBDIR)/libhealpix_cxx.a +CXXBIN:=syn_alm_cxx alm2map_cxx anafast_cxx map2tga udgrade_cxx hotspots_cxx calc_powspec median_filter_cxx hpxtest smoothing_cxx mult_alm rotalm_cxx +LIBOBJ:=alm_powspec_tools.o powspec.o alm_fitsio.o powspec_fitsio.o healpix_base.o healpix_map.o alm_healpix_tools.o healpix_data_io.o healpix_map_fitsio.o healpix_base2.o syn_alm_cxx_module.o anafast_cxx_module.o alm2map_cxx_module.o map2tga_module.o udgrade_cxx_module.o smoothing_cxx_module.o hotspots_cxx_module.o calc_powspec_module.o median_filter_cxx_module.o mult_alm_module.o +ALLOBJ:=$(LIBOBJ) $(CXXBIN:%=%.o) +LIBOBJ:=$(LIBOBJ:%=$(OD)/%) +ALLOBJ:=$(ALLOBJ:%=$(OD)/%) + +ODEP:=$(HDR_$(PKG)) $(HDR_cxxsupport) $(HDR_libpsht) $(HDR_libfftpack) $(HDR_c_utils) +BDEP:=$(LIB_$(PKG)) $(LIB_cxxsupport) $(LIB_libpsht) $(LIB_libfftpack) $(LIB_c_utils) $(LIB_libcfitsio) + +$(LIB_$(PKG)): $(LIBOBJ) + +$(ALLOBJ): $(ODEP) | $(OD)_mkdir +CXXBIN:=$(CXXBIN:%=$(BINDIR)/%) +$(CXXBIN): $(BINDIR)/% : $(OD)/%.o $(BDEP) + +all_hdr+=$(HDR_$(PKG)) +all_lib+=$(LIB_$(PKG)) +all_cxxbin+=$(CXXBIN) diff --git a/external/healpix/Healpix_cxx/powspec.cc b/external/healpix/Healpix_cxx/powspec.cc new file mode 100644 index 0000000..d9d19af --- /dev/null +++ b/external/healpix/Healpix_cxx/powspec.cc @@ -0,0 +1,132 @@ +/* + * This file is part of Healpix_cxx. + * + * Healpix_cxx 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. + * + * Healpix_cxx 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 Healpix_cxx; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * For more information about HEALPix, see http://healpix.jpl.nasa.gov + */ + +/* + * Healpix_cxx is being developed at the Max-Planck-Institut fuer Astrophysik + * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt + * (DLR). + */ + +/* + * Copyright (C) 2003-2010 Max-Planck-Society + * Author: Martin Reinecke + */ + +#include "powspec.h" +#include "lsconstants.h" + +using namespace std; + +void PowSpec::dealloc() + { + tt_.dealloc(); + gg_.dealloc(); + cc_.dealloc(); + tg_.dealloc(); + tc_.dealloc(); + gc_.dealloc(); + } + +void PowSpec::assertArraySizes() const + { + planck_assert((num_specs==1) || (num_specs==4) || (num_specs==6), + "incorrect number of spectral components"); + if (num_specs==1) + planck_assert(multiequal(tsize(0),gg_.size(),cc_.size(),tg_.size(), + tc_.size(),gc_.size()), "incorrect array sizes"); + if (num_specs==4) + { + planck_assert(multiequal(tt_.size(),gg_.size(),cc_.size(),tg_.size()), + "incorrect array sizes"); + planck_assert(multiequal(tsize(0),tc_.size(),gc_.size()), + "incorrect array sizes"); + } + if (num_specs==6) + planck_assert(multiequal(tt_.size(),gg_.size(),cc_.size(),tg_.size(), + tc_.size(),gc_.size()), "incorrect array sizes"); + } + +bool PowSpec::consistentAutoPowspec() const + { + for (tsize l=0; l=4) + for (tsize l=0; lsqrt(tt_[l]*gg_[l])) return false; + } + if (num_specs==6) + for (tsize l=0; lsqrt(tt_[l]*cc_[l])) return false; + if (abs(gc_[l])>sqrt(gg_[l]*cc_[l])) return false; + } + return true; + } + +void PowSpec::Set(arr &tt_new) + { + dealloc(); + num_specs = 1; + tt_.transfer(tt_new); +//FIXME: temporarily relaxed to allow cross-spectra + if (!consistentAutoPowspec()) + cerr << "Warning: negative values in TT spectrum" << endl; + } + +void PowSpec::Set(arr &tt_new, arr &gg_new, + arr &cc_new, arr &tg_new) + { + dealloc(); + num_specs = 4; + tt_.transfer(tt_new); gg_.transfer(gg_new); + cc_.transfer(cc_new); tg_.transfer(tg_new); + assertArraySizes(); + } + +void PowSpec::Set(arr &tt_new, arr &gg_new, arr &cc_new, + arr &tg_new, arr &tc_new, arr &gc_new) + { + Set (tt_new, gg_new, cc_new, tg_new); + num_specs = 6; + tc_.transfer(tc_new); gc_.transfer(gc_new); + assertArraySizes(); + } + +void PowSpec::smoothWithGauss (double fwhm) + { + planck_assert (num_specs<=4, "not yet implemented for num_specs>4"); + double sigma = fwhm*fwhm2sigma; + double fact_pol = exp(2*sigma*sigma); + for (tsize l=0; l1) + { + gg_[l] *= f2*f2; + cc_[l] *= f2*f2; + tg_[l] *= f1*f2; + } + } + } diff --git a/external/healpix/Healpix_cxx/powspec.h b/external/healpix/Healpix_cxx/powspec.h new file mode 100644 index 0000000..1844667 --- /dev/null +++ b/external/healpix/Healpix_cxx/powspec.h @@ -0,0 +1,138 @@ +/* + * This file is part of Healpix_cxx. + * + * Healpix_cxx 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. + * + * Healpix_cxx 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 Healpix_cxx; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * For more information about HEALPix, see http://healpix.jpl.nasa.gov + */ + +/* + * Healpix_cxx is being developed at the Max-Planck-Institut fuer Astrophysik + * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt + * (DLR). + */ + +/* + * Copyright (C) 2003-2010 Max-Planck-Society + * Author: Martin Reinecke + */ + +#ifndef POWSPEC_H +#define POWSPEC_H + +#include "arr.h" + +/*! Class for storing unpolarised and polarised power spectra. */ +class PowSpec + { + private: + arr tt_, gg_, cc_, tg_, tc_, gc_; + int num_specs; + + void dealloc(); + + public: + /*! */ + PowSpec() {} + /*! Constructs a \a PowSpec with \a nspec components and a maximum + multipole of \a lmax. \a nspec can be 1 (TT), 4 (TT,GG,CC,TG) or + 6 (TT,GG,CC,TG,TC,GC). */ + PowSpec(int nspec, int lmax) + : num_specs(nspec) + { + planck_assert ((num_specs==1) || (num_specs==4) || (num_specs==6), + "wrong number of spectrums"); + tt_.alloc(lmax+1); + if (num_specs>1) + { + gg_.alloc(lmax+1); + cc_.alloc(lmax+1); + tg_.alloc(lmax+1); + } + if (num_specs>4) + { + tc_.alloc(lmax+1); + gc_.alloc(lmax+1); + } + } + + /*! Ensures that the internal array sizes are consistent with the + \a num_specs variable. */ + void assertArraySizes() const; + + /*! Checks whether the object can be an auto power spectrum. If this + is not the case, an exception is thrown. */ + bool consistentAutoPowspec() const; + + /*! Returns the number of spectral components. */ + int Num_specs() const { return num_specs; } + /*! Returns the maximum \a l. */ + int Lmax() const { return tt_.size()-1; } + /*! Returns the TT array (read-only). */ + const arr &tt() const { return tt_; } + /*! Returns the GG array (read-only). */ + const arr &gg() const { return gg_; } + /*! Returns the CC array (read-only). */ + const arr &cc() const { return cc_; } + /*! Returns the TG array (read-only). */ + const arr &tg() const { return tg_; } + /*! Returns the TC array (read-only). */ + const arr &tc() const { return tc_; } + /*! Returns the GC array (read-only). */ + const arr &gc() const { return gc_; } + /*! Returns TT(l) (read-write). */ + double &tt (int l) { return tt_[l]; } + /*! Returns GG(l) (read-write). */ + double &gg (int l) { return gg_[l]; } + /*! Returns CC(l) (read-write). */ + double &cc (int l) { return cc_[l]; } + /*! Returns TG(l) (read-write). */ + double &tg (int l) { return tg_[l]; } + /*! Returns TC(l) (read-write). */ + double &tc (int l) { return tc_[l]; } + /*! Returns GC(l) (read-write). */ + double &gc (int l) { return gc_[l]; } + /*! Returns TT(l) (read-only). */ + const double &tt (int l) const { return tt_[l]; } + /*! Returns GG(l) (read-only). */ + const double &gg (int l) const { return gg_[l]; } + /*! Returns CC(l) (read-only). */ + const double &cc (int l) const { return cc_[l]; } + /*! Returns TG(l) (read-only). */ + const double &tg (int l) const { return tg_[l]; } + /*! Returns TC(l) (read-only). */ + const double &tc (int l) const { return tc_[l]; } + /*! Returns GC(l) (read-only). */ + const double &gc (int l) const { return gc_[l]; } + + /*! Sets the whole TT array. + \note On exit, \a tt_new is zero-sized! */ + void Set(arr &tt_new); + /*! Sets the four first components. + \note On exit, all arguments are zero-sized! */ + void Set(arr &tt_new, arr &gg_new, + arr &cc_new, arr &tg_new); + /*! Sets all components. + \note On exit, all arguments are zero-sized! */ + void Set(arr &tt_new, arr &gg_new, + arr &cc_new, arr &tg_new, + arr &tc_new, arr &gc_new); + /*! Smooths the spectrum with a Gaussian beam. + \a fwhm is given in radian. + \note This is only implememted for 1 and 4 spectra so far. */ + void smoothWithGauss (double fwhm); + }; + +#endif diff --git a/external/healpix/Healpix_cxx/powspec_fitsio.cc b/external/healpix/Healpix_cxx/powspec_fitsio.cc new file mode 100644 index 0000000..4466afa --- /dev/null +++ b/external/healpix/Healpix_cxx/powspec_fitsio.cc @@ -0,0 +1,113 @@ +/* + * This file is part of Healpix_cxx. + * + * Healpix_cxx 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. + * + * Healpix_cxx 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 Healpix_cxx; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * For more information about HEALPix, see http://healpix.jpl.nasa.gov + */ + +/* + * Healpix_cxx is being developed at the Max-Planck-Institut fuer Astrophysik + * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt + * (DLR). + */ + +/* + * Copyright (C) 2003-2010 Max-Planck-Society + * Author: Martin Reinecke + */ + +#include "powspec_fitsio.h" +#include "powspec.h" +#include "fitshandle.h" + +using namespace std; + +void read_powspec_from_fits (const string &infile, PowSpec &powspec, + int nspecs, int lmax) + { + planck_assert ((nspecs==1)||(nspecs==4)||(nspecs==6), + "wrong number of spectra"); + fitshandle inp; + inp.open(infile); + inp.goto_hdu(2); + + arr tt(lmax+1,0),gg(lmax+1,0),cc(lmax+1,0),tg(lmax+1,0), + tc(lmax+1,0),gc(lmax+1,0); + + int lmax_file = safe_cast(inp.nelems(1)-1); + if (lmax_file=4) + { + inp.read_column_raw (2,&gg[0],lmax_read+1); + inp.read_column_raw (3,&cc[0],lmax_read+1); + inp.read_column_raw (4,&tg[0],lmax_read+1); + } + if (nspecs==6) + { + inp.read_column_raw (5,&tc[0],lmax_read+1); + inp.read_column_raw (6,&gc[0],lmax_read+1); + } + + if (nspecs==1) powspec.Set(tt); + if (nspecs==4) powspec.Set(tt,gg,cc,tg); + if (nspecs==6) powspec.Set(tt,gg,cc,tg,tc,gc); + } + +void write_powspec_to_fits (fitshandle &out, + const PowSpec &powspec, int nspecs) + { + planck_assert ((nspecs==1)||(nspecs==4)||(nspecs==6), + "incorrect number of spectra"); + vector cols; + cols.push_back(fitscolumn("Temperature C_l","unknown",1,PLANCK_FLOAT64)); + if (nspecs>1) + { + cols.push_back(fitscolumn("E-mode C_l","unknown",1,PLANCK_FLOAT64)); + cols.push_back(fitscolumn("B-mode C_l","unknown",1,PLANCK_FLOAT64)); + cols.push_back(fitscolumn("T-E cross-corr.","unknown",1, + PLANCK_FLOAT64)); + } + if (nspecs>4) + { + cols.push_back(fitscolumn("T-B cross-corr.","unknown",1,PLANCK_FLOAT64)); + cols.push_back(fitscolumn("E-B cross-corr.","unknown",1,PLANCK_FLOAT64)); + } + out.insert_bintab(cols); + out.write_column(1,powspec.tt()); + if (nspecs>1) + { + out.write_column(2,powspec.gg()); + out.write_column(3,powspec.cc()); + out.write_column(4,powspec.tg()); + } + if (nspecs>4) + { + out.write_column(5,powspec.tc()); + out.write_column(6,powspec.gc()); + } + } + +void write_powspec_to_fits (const string &outfile, + const PowSpec &powspec, int nspecs) + { + fitshandle out; + out.create(outfile); + write_powspec_to_fits(out,powspec,nspecs); + } diff --git a/external/healpix/Healpix_cxx/powspec_fitsio.h b/external/healpix/Healpix_cxx/powspec_fitsio.h new file mode 100644 index 0000000..ff6000b --- /dev/null +++ b/external/healpix/Healpix_cxx/powspec_fitsio.h @@ -0,0 +1,61 @@ +/* + * This file is part of Healpix_cxx. + * + * Healpix_cxx 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. + * + * Healpix_cxx 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 Healpix_cxx; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * For more information about HEALPix, see http://healpix.jpl.nasa.gov + */ + +/* + * Healpix_cxx is being developed at the Max-Planck-Institut fuer Astrophysik + * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt + * (DLR). + */ + +/*! \file powspec_fitsio.h + * Copyright (C) 2003-2010 Max-Planck-Society + * \author Martin Reinecke + */ + +#ifndef POWSPEC_FITSIO_H +#define POWSPEC_FITSIO_H + +#include +class fitshandle; + +class PowSpec; + +/*! \defgroup powspec_fitsio_group FITS-based I/O of power spectra */ +/*! \{ */ + +/*! Opens the FITS file \a filename, jumps to HDU 2, and reads \a nspecs + columns into \a powspec. \a nspecs must be 1, 4, or 6. */ +void read_powspec_from_fits (const std::string &infile, + PowSpec &powspec, int nspecs, int lmax); +/*! Inserts a new binary table into \a out, which contains \a nspecs columns + of FITS type TDOUBLE, and writes the components of \a powspec into it. + \a nspecs must be 1, 4, or 6. */ +void write_powspec_to_fits (fitshandle &out, + const PowSpec &powspec, int nspecs); + +/*! Creates a new FITS file called \a outfile, inserts a binary table, + which contains \a nspecs columns of FITS type TDOUBLE, and writes the + components of \a powspec into it. \a nspecs must be 1, 4, or 6. */ +void write_powspec_to_fits (const std::string &outfile, + const PowSpec &powspec, int nspecs); + +/*! \} */ + +#endif diff --git a/external/healpix/Healpix_cxx/rotalm_cxx.cc b/external/healpix/Healpix_cxx/rotalm_cxx.cc new file mode 100644 index 0000000..9ddd3ff --- /dev/null +++ b/external/healpix/Healpix_cxx/rotalm_cxx.cc @@ -0,0 +1,124 @@ +/* + * This file is part of Healpix_cxx. + * + * Healpix_cxx 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. + * + * Healpix_cxx 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 Healpix_cxx; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * For more information about HEALPix, see http://healpix.jpl.nasa.gov + */ + +/* + * Healpix_cxx 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 Max-Planck-Society + * Author: Martin Reinecke + */ + +#include "alm.h" +#include "alm_fitsio.h" +#include "fitshandle.h" +#include "alm_powspec_tools.h" +#include "trafos.h" + +using namespace std; + +namespace { + +Trafo maketrafo (int num) + { + switch (num) + { + case 1: return Trafo(2000,2000,Equatorial,Galactic); + case 2: return Trafo(2000,2000,Galactic,Equatorial); + case 3: return Trafo(2000,2000,Equatorial,Ecliptic); + case 4: return Trafo(2000,2000,Ecliptic,Equatorial); + case 5: return Trafo(2000,2000,Ecliptic,Galactic); + case 6: return Trafo(2000,2000,Galactic,Ecliptic); + case 7: return Trafo(1950,1950,Equatorial,Galactic); + case 8: return Trafo(1950,1950,Galactic,Equatorial); + case 9: return Trafo(1950,1950,Equatorial,Ecliptic); + case 10: return Trafo(1950,1950,Ecliptic,Equatorial); + case 11: return Trafo(1950,1950,Ecliptic,Galactic); + case 12: return Trafo(1950,1950,Galactic,Ecliptic); + default: planck_fail("Unsupported transformation "+dataToString(num)); + } + } + +} // unnamed namespace + +int main(int argc, const char **argv) + { +PLANCK_DIAGNOSIS_BEGIN + announce ("rotalm_cxx"); + + if (argc!=5) + { + cout << "Usage: rotalm_cxx " + << endl + << "Transform 1: Equatorial (2000) -> Galactic (2000)" << endl + << " 2: Galactic (2000) -> Equatorial (2000)" << endl + << " 3: Equatorial (2000) -> Ecliptic (2000)" << endl + << " 4: Ecliptic (2000) -> Equatorial (2000)" << endl + << " 5: Ecliptic (2000) -> Galactic (2000)" << endl + << " 6: Galactic (2000) -> Ecliptic (2000)" << endl + << " 7: Equatorial (1950) -> Galactic (1950)" << endl + << " 8: Galactic (1950) -> Equatorial (1950)" << endl + << " 9: Equatorial (1950) -> Ecliptic (1950)" << endl + << " 10: Ecliptic (1950) -> Equatorial (1950)" << endl + << " 11: Ecliptic (1950) -> Galactic (1950)" << endl + << " 12: Galactic (1950) -> Ecliptic (1950)" << endl + << endl + << "pol: T or F" << endl << endl; + planck_fail_quietly("Incorrect usage"); + } + + string infile = argv[1]; + string outfile = argv[2]; + int trafo = stringToData(argv[3]); + bool polarisation = stringToData(argv[4]); + + Trafo tr(maketrafo(trafo)); + + fitshandle out; + out.create (outfile); + + Alm > almT,almG,almC; + + if (!polarisation) + { + int lmax, dummy; + get_almsize (infile,lmax,dummy); + read_Alm_from_fits (infile, almT, lmax, lmax); + rotate_alm(almT,tr.Matrix()); + write_Alm_to_fits (out,almT,lmax,lmax,PLANCK_FLOAT32); + } + else + { + int lmax, dummy; + get_almsize_pol (infile,lmax,dummy); + read_Alm_from_fits (infile, almT, lmax, lmax, 2); + read_Alm_from_fits (infile, almG, lmax, lmax, 3); + read_Alm_from_fits (infile, almC, lmax, lmax, 4); + rotate_alm(almT,almG,almC,tr.Matrix()); + write_Alm_to_fits (out,almT,lmax,lmax,PLANCK_FLOAT64); + write_Alm_to_fits (out,almG,lmax,lmax,PLANCK_FLOAT64); + write_Alm_to_fits (out,almC,lmax,lmax,PLANCK_FLOAT64); + } + +PLANCK_DIAGNOSIS_END + } diff --git a/external/healpix/Healpix_cxx/smoothing_cxx.cc b/external/healpix/Healpix_cxx/smoothing_cxx.cc new file mode 100644 index 0000000..15f53ee --- /dev/null +++ b/external/healpix/Healpix_cxx/smoothing_cxx.cc @@ -0,0 +1,9 @@ +#include "levels_facilities.h" +#include "error_handling.h" + +int main (int argc, const char **argv) + { + PLANCK_DIAGNOSIS_BEGIN + smoothing_cxx_module (argc, argv); + PLANCK_DIAGNOSIS_END + } diff --git a/external/healpix/Healpix_cxx/smoothing_cxx.par.txt b/external/healpix/Healpix_cxx/smoothing_cxx.par.txt new file mode 100644 index 0000000..2a6e36e --- /dev/null +++ b/external/healpix/Healpix_cxx/smoothing_cxx.par.txt @@ -0,0 +1,34 @@ +Parameters read by smoothing_cxx: + +fwhm_arcmin (double): + FWHM (in arcmin) of the Gaussian beam used for smoothing. If the value + is negative, the smoothing of a Gaussian beam with an FWHM of -fwhm_arcmin + will be _removed_ from the input map. + +nlmax (integer): + maximum order of l + +infile (string): + input file containing the Healpix map + +outfile (string, default=""): + output file for the smoothed Healpix map + +polarisation (bool): + if false, only an intensity map is smoothed + if true, an IQU map is smoothed + +weighted (bool, default=false): + if true, weighted quadrature is used + +if (weighted) + healpix_data (string): + directory containing the Healpix data files +endif + +iter_order (integer, default=0) + number of iterations for the analysis (0: standard analysis) + +double_precision (bool, default=false): + if false, a_lm are read/written in single precision, otherwise in + double precision. diff --git a/external/healpix/Healpix_cxx/smoothing_cxx_module.cc b/external/healpix/Healpix_cxx/smoothing_cxx_module.cc new file mode 100644 index 0000000..7476c07 --- /dev/null +++ b/external/healpix/Healpix_cxx/smoothing_cxx_module.cc @@ -0,0 +1,114 @@ +/* + * This file is part of Healpix_cxx. + * + * Healpix_cxx 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. + * + * Healpix_cxx 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 Healpix_cxx; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * For more information about HEALPix, see http://healpix.jpl.nasa.gov + */ + +/* + * Healpix_cxx 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-2010 Max-Planck-Society + * Author: Martin Reinecke + */ + +#include "xcomplex.h" +#include "cxxutils.h" +#include "paramfile.h" +#include "healpix_data_io.h" +#include "alm.h" +#include "healpix_map.h" +#include "healpix_map_fitsio.h" +#include "alm_healpix_tools.h" +#include "alm_powspec_tools.h" +#include "fitshandle.h" +#include "levels_facilities.h" +#include "lsconstants.h" + +using namespace std; + +namespace { + +template void smoothing_cxx (paramfile ¶ms) + { + int nlmax = params.template find("nlmax"); + string infile = params.template find("infile"); + string outfile = params.template find("outfile"); + bool polarisation = params.template find("polarisation"); + int num_iter = params.template find("iter_order",0); + double fwhm = arcmin2rad*params.template find("fwhm_arcmin"); + if (fwhm<0) + cout << "NOTE: negative FWHM supplied, doing a deconvolution..." << endl; + + if (!polarisation) + { + Healpix_Map map; + read_Healpix_map_from_fits(infile,map,1,2); + arr weight; + get_ring_weights (params,map.Nside(),weight); + + Alm > alm(nlmax,nlmax); + double avg=map.average(); + map.Add(T(-avg)); + if (map.Scheme()==NEST) map.swap_scheme(); + + map2alm_iter(map,alm,num_iter,weight); + smoothWithGauss (alm, fwhm); + alm2map(alm,map); + + map.Add(T(avg)); + write_Healpix_map_to_fits (outfile,map,planckType()); + } + else + { + Healpix_Map mapT, mapQ, mapU; + read_Healpix_map_from_fits(infile,mapT,mapQ,mapU); + arr weight; + get_ring_weights (params,mapT.Nside(),weight); + + Alm > almT(nlmax,nlmax), almG(nlmax,nlmax), almC(nlmax,nlmax); + double avg=mapT.average(); + mapT.Add(T(-avg)); + if (mapT.Scheme()==NEST) mapT.swap_scheme(); + if (mapQ.Scheme()==NEST) mapQ.swap_scheme(); + if (mapU.Scheme()==NEST) mapU.swap_scheme(); + + map2alm_pol_iter + (mapT,mapQ,mapU,almT,almG,almC,num_iter,weight); + smoothWithGauss (almT, almG, almC, fwhm); + alm2map_pol(almT,almG,almC,mapT,mapQ,mapU); + + mapT.Add(T(avg)); + write_Healpix_map_to_fits (outfile,mapT,mapQ,mapU,planckType()); + } + } + +} // unnamed namespace + +int smoothing_cxx_module (int argc, const char **argv) + { + module_startup ("smoothing_cxx", argc, argv, 2, ""); + paramfile params (argv[1]); + + bool dp = params.find ("double_precision",false); + dp ? smoothing_cxx(params) : smoothing_cxx(params); + + return 0; + } diff --git a/external/healpix/Healpix_cxx/syn_alm_cxx.cc b/external/healpix/Healpix_cxx/syn_alm_cxx.cc new file mode 100644 index 0000000..75a1f61 --- /dev/null +++ b/external/healpix/Healpix_cxx/syn_alm_cxx.cc @@ -0,0 +1,9 @@ +#include "levels_facilities.h" +#include "error_handling.h" + +int main (int argc, const char **argv) + { + PLANCK_DIAGNOSIS_BEGIN + syn_alm_cxx_module (argc, argv); + PLANCK_DIAGNOSIS_END + } diff --git a/external/healpix/Healpix_cxx/syn_alm_cxx.par.txt b/external/healpix/Healpix_cxx/syn_alm_cxx.par.txt new file mode 100644 index 0000000..e0d02dc --- /dev/null +++ b/external/healpix/Healpix_cxx/syn_alm_cxx.par.txt @@ -0,0 +1,28 @@ +Parameters read by syn_alm_cxx: + +nlmax (integer): + maximum order of l + +nmmax (integer): + maximum order of m (must not be larger than nlmax, default=nlmax) + +infile (string): + input file containing the CMB power spectrum + +outfile (string): + output file name for the calculated a_lm + +rand_seed (integer): + random-number seed + +fwhm_arcmin (real): + FWHM (in arcmin) of a Gaussian beam, which is used to smooth the + resulting sky a_lm (default=0) + +polarisation (bool): + if false, only the intensity a_lm are generated, + if true, T, G and C a_lm are generated + +double_precision (bool, default=false): + if false, the a_lm are created in single precision, + otherwise in double precision. diff --git a/external/healpix/Healpix_cxx/syn_alm_cxx_module.cc b/external/healpix/Healpix_cxx/syn_alm_cxx_module.cc new file mode 100644 index 0000000..3716809 --- /dev/null +++ b/external/healpix/Healpix_cxx/syn_alm_cxx_module.cc @@ -0,0 +1,92 @@ +/* + * This file is part of Healpix_cxx. + * + * Healpix_cxx 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. + * + * Healpix_cxx 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 Healpix_cxx; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * For more information about HEALPix, see http://healpix.jpl.nasa.gov + */ + +/* + * Healpix_cxx is being developed at the Max-Planck-Institut fuer Astrophysik + * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt + * (DLR). + */ + +/* + * Copyright (C) 2003-2010 Max-Planck-Society + * Author: Martin Reinecke + */ + +#include "xcomplex.h" +#include "cxxutils.h" +#include "paramfile.h" +#include "planck_rng.h" +#include "alm.h" +#include "alm_fitsio.h" +#include "powspec.h" +#include "powspec_fitsio.h" +#include "alm_powspec_tools.h" +#include "fitshandle.h" +#include "levels_facilities.h" +#include "lsconstants.h" + +using namespace std; + +namespace { + +template void syn_alm_cxx (paramfile ¶ms) + { + int nlmax = params.template find("nlmax"); + int nmmax = params.template find("nmmax",nlmax); + planck_assert(nmmax<=nlmax,"nmmax must not be larger than nlmax"); + string infile = params.template find("infile"); + string outfile = params.template find("outfile"); + int rand_seed = params.template find("rand_seed"); + double fwhm = arcmin2rad*params.template find("fwhm_arcmin",0.); + bool polarisation = params.template find("polarisation"); + + PowSpec powspec; + int nspecs = polarisation ? 4 : 1; + read_powspec_from_fits (infile, powspec, nspecs, nlmax); + powspec.smoothWithGauss(fwhm); + + planck_rng rng(rand_seed); + + if (polarisation) + { + Alm > + almT(nlmax,nmmax), almG(nlmax,nmmax), almC(nlmax,nmmax); + create_alm_pol (powspec, almT, almG, almC, rng); + write_Alm_to_fits(outfile,almT,almG,almC,nlmax,nmmax,planckType()); + } + else + { + Alm > almT(nlmax,nmmax); + create_alm (powspec, almT, rng); + write_Alm_to_fits(outfile,almT,nlmax,nmmax,planckType()); + } + } + +} // unnamed namespace + +int syn_alm_cxx_module (int argc, const char **argv) + { + module_startup ("syn_alm_cxx", argc, argv, 2, ""); + paramfile params (argv[1]); + + bool dp = params.find ("double_precision",false); + dp ? syn_alm_cxx(params) : syn_alm_cxx(params); + return 0; + } diff --git a/external/healpix/Healpix_cxx/udgrade_cxx.cc b/external/healpix/Healpix_cxx/udgrade_cxx.cc new file mode 100644 index 0000000..cb8fc15 --- /dev/null +++ b/external/healpix/Healpix_cxx/udgrade_cxx.cc @@ -0,0 +1,9 @@ +#include "levels_facilities.h" +#include "error_handling.h" + +int main (int argc, const char **argv) + { + PLANCK_DIAGNOSIS_BEGIN + udgrade_cxx_module (argc, argv); + PLANCK_DIAGNOSIS_END + } diff --git a/external/healpix/Healpix_cxx/udgrade_cxx_module.cc b/external/healpix/Healpix_cxx/udgrade_cxx_module.cc new file mode 100644 index 0000000..7e217f1 --- /dev/null +++ b/external/healpix/Healpix_cxx/udgrade_cxx_module.cc @@ -0,0 +1,88 @@ +/* + * This file is part of Healpix_cxx. + * + * Healpix_cxx 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. + * + * Healpix_cxx 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 Healpix_cxx; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * For more information about HEALPix, see http://healpix.jpl.nasa.gov + */ + +/* + * Healpix_cxx is being developed at the Max-Planck-Institut fuer Astrophysik + * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt + * (DLR). + */ + +/* + * Copyright (C) 2003-2010 Max-Planck-Society + * Author: Martin Reinecke + */ + +#include "cxxutils.h" +#include "paramfile.h" +#include "healpix_map.h" +#include "healpix_map_fitsio.h" +#include "fitshandle.h" +#include "levels_facilities.h" + +using namespace std; + +namespace { + +template void udgrade_cxx (paramfile ¶ms) + { + string infile = params.template find("infile"); + string outfile = params.template find("outfile"); + int order = Healpix_Base::nside2order (params.template find("nside")); + bool polarisation = params.template find("polarisation",false); + bool pessimistic = params.template find("pessimistic",false); + + if (!polarisation) + { + Healpix_Map inmap; + read_Healpix_map_from_fits(infile,inmap,1,2); + Healpix_Map outmap (order, inmap.Scheme()); + + outmap.Import(inmap,pessimistic); + write_Healpix_map_to_fits (outfile,outmap,planckType()); + } + else + { + Healpix_Map inmap; + read_Healpix_map_from_fits(infile,inmap,1,2); + Healpix_Map outmapT (order, inmap.Scheme()), + outmapQ (order, inmap.Scheme()), + outmapU (order, inmap.Scheme()); + + outmapT.Import(inmap,pessimistic); + read_Healpix_map_from_fits(infile,inmap,2,2); + outmapQ.Import(inmap,pessimistic); + read_Healpix_map_from_fits(infile,inmap,3,2); + outmapU.Import(inmap,pessimistic); + write_Healpix_map_to_fits (outfile,outmapT,outmapQ,outmapU,planckType()); + } + } + +} // unnamed namespace + +int udgrade_cxx_module (int argc, const char **argv) + { + module_startup ("udgrade_cxx", argc, argv, 2, ""); + paramfile params (argv[1]); + + bool dp = params.find ("double_precision",false); + dp ? udgrade_cxx(params) : udgrade_cxx(params); + + return 0; + } diff --git a/external/healpix/Makefile b/external/healpix/Makefile new file mode 100644 index 0000000..f0bb3d1 --- /dev/null +++ b/external/healpix/Makefile @@ -0,0 +1,54 @@ +ifndef HEALPIX_TARGET + HEALPIX_TARGET:=$(error HEALPIX_TARGET undefined. Please see README.compilation for help)UNDEFINED +endif + +default: compile_all +SRCROOT:=$(shell pwd) +include $(SRCROOT)/config/config.$(HEALPIX_TARGET) +include $(SRCROOT)/config/rules.common + +.SILENT: + +.PHONY: test + +all_hdr:= +all_lib:= +all_cbin:= +all_cxxbin:= + +FULL_INCLUDE:= + +include libcfitsio/planck.make +include c_utils/planck.make +include libfftpack/planck.make +include libpsht/planck.make +include cxxsupport/planck.make +include Healpix_cxx/planck.make +#include alice/planck.make +#include docsrc/planck.make + +$(all_lib): %: | $(LIBDIR)_mkdir + @echo "# creating library $*" + $(ARCREATE) $@ $^ + +$(all_cxxbin): %: | $(BINDIR)_mkdir + @echo "# linking C++ binary $*" + $(CXXL) $(CXXLFLAGS) -o $@ $^ $(CXX_EXTRALIBS) + +$(all_cbin): %: | $(BINDIR)_mkdir + @echo "# linking C binary $*" + $(CXXL) $(CXXLFLAGS) -o $@ $^ $(CXX_EXTRALIBS) + +compile_all: $(all_cbin) $(all_cxxbin) hdrcopy + +hdrclean: + @if [ -d $(INCDIR) ]; then rm -rf $(INCDIR)/* ; fi + +hdrcopy: | $(INCDIR)_mkdir + @if [ "$(all_hdr)" ]; then cp -f $(all_hdr) $(INCDIR); fi + +$(notdir $(all_cbin) $(all_cxxbin)) : % : $(BINDIR)/% +$(notdir $(all_lib)) libcfitsio.a : % : $(LIBDIR)/% + +test: compile_all + cd test; ./runtest.sh diff --git a/external/healpix/README.compilation b/external/healpix/README.compilation new file mode 100644 index 0000000..3464835 --- /dev/null +++ b/external/healpix/README.compilation @@ -0,0 +1,45 @@ +Starting with HEALPix 2.20, Healpix_cxx supports compilation using a +pre-installed libcfitsio. In order to use this feature, simply set +the following environment variables before running "make": + +EXTERNAL_CFITSIO=yes +CFITSIO_EXT_LIB= +CFITSIO_EXT_INC= + +The installed version of libcfitsio should be at least 3.23. + +Alternatively, Healpix_cxx can be instructed to compile its own libcfitsio. +For that purpose the file cfitsio3260.tar.gz needs to be present in +the subdirectory libcfitsio/. It can be obtained from +http://heasarc.gsfc.nasa.gov/FTP/software/fitsio/c/cfitsio3260.tar.gz +Please simply put the .tar.gz file into the libcfitsio/ directory; it will +be unpacked and compiled automatically. + +If you have a more recent version of the cfitsio package, please edit the +line starting with "PACKAGE =" in the file libcfitsio/planck.make accordingly. + +GNU make is also required for compilation. + +To compile the package, set the environment variable +HEALPIX_TARGET to the target for which you want to compile +(e.g. generic_gcc, linux_icc etc.). If a fairly recent version +(4.2 or higher) of gcc and g++ is installed on the system, the target +"generic_gcc" should work in most cases; however, for Mac OS X, "osx" is +recommended. For each possible target there exists a configuration file with +the name config.$HEALPIX_TARGET in the directory config/. + +Afterwards, just type "gmake" or "make". + +If the compilers on your platform have different names or you +want to make other changes, editing the configuration files +should be quite straightforward. + +Please note that all temporary and object files are created +separately from the source files in a directory called +"build.$HEALPIX_TARGET". This allows simultaneous compilation +for different platforms. + +Documentation can be created by the command "(g)make doc". +However this requires the doxygen application to be installed +on your system. +The documentation will be created in the subdirectory doc/. diff --git a/external/healpix/c_utils/c_utils.c b/external/healpix/c_utils/c_utils.c new file mode 100644 index 0000000..a66764a --- /dev/null +++ b/external/healpix/c_utils/c_utils.c @@ -0,0 +1,83 @@ +/* + * This file is part of libc_utils. + * + * libc_utils 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. + * + * libc_utils 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 libc_utils; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * libc_utils is being developed at the Max-Planck-Institut fuer Astrophysik + * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt + * (DLR). + */ + +/* + * Convenience functions + * + * Copyright (C) 2008, 2009, 2010 Max-Planck-Society + * Author: Martin Reinecke + */ + +#include +#include +#include "c_utils.h" + +void util_fail_ (const char *file, int line, const char *func, const char *msg) + { + fprintf(stderr,"%s, %i (%s):\n%s\n",file,line,func,msg); + exit(1); + } +void util_warn_ (const char *file, int line, const char *func, const char *msg) + { + fprintf(stderr,"%s, %i (%s):\n%s\n",file,line,func,msg); + exit(1); + } + +/* This function tries to avoid allocations with a total size close to a high + power of two (called the "critical stride" here), by adding a few more bytes + if necssary. This lowers the probability that two arrays differ by a multiple + of the critical stride in their starting address, which in turn lowers the + risk of cache line contention. */ +static size_t manipsize(size_t sz) + { + const size_t critical_stride=4096, cacheline=64, overhead=32; + if (sz < (critical_stride/2)) return sz; + if (((sz+overhead)%critical_stride)>(2*cacheline)) return sz; + return sz+2*cacheline; + } + +#ifdef __SSE__ +#include +void *util_malloc_ (size_t sz) + { + void *res; + if (sz==0) return NULL; + res = _mm_malloc(manipsize(sz),16); + UTIL_ASSERT(res,"_mm_malloc() failed"); + return res; + } +void util_free_ (void *ptr) + { if ((ptr)!=NULL) _mm_free(ptr); } +#else +void *util_malloc_ (size_t sz) + { + void *res; + if (sz==0) return NULL; + res = malloc(manipsize(sz)); + UTIL_ASSERT(res,"malloc() failed"); + return res; + } +void util_free_ (void *ptr) + { if ((ptr)!=NULL) free(ptr); } +#endif diff --git a/external/healpix/c_utils/c_utils.h b/external/healpix/c_utils/c_utils.h new file mode 100644 index 0000000..5820c4a --- /dev/null +++ b/external/healpix/c_utils/c_utils.h @@ -0,0 +1,125 @@ +/* + * This file is part of libc_utils. + * + * libc_utils 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. + * + * libc_utils 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 libc_utils; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * libc_utils is being developed at the Max-Planck-Institut fuer Astrophysik + * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt + * (DLR). + */ + +/*! \file c_utils.h + * Convenience functions + * + * Copyright (C) 2008, 2009, 2010 Max-Planck-Society + * \author Martin Reinecke + * \note This file should only be included from .c files, NOT from .h files. + */ + +#ifndef PLANCK_C_UTILS_H +#define PLANCK_C_UTILS_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void util_fail_ (const char *file, int line, const char *func, const char *msg); +void util_warn_ (const char *file, int line, const char *func, const char *msg); +void *util_malloc_ (size_t sz); +void util_free_ (void *ptr); + +#if defined (__GNUC__) +#define UTIL_FUNC_NAME__ __func__ +#else +#define UTIL_FUNC_NAME__ "unknown" +#endif + +#define UTIL_ASSERT(cond,msg) \ + if(!(cond)) util_fail_(__FILE__,__LINE__,UTIL_FUNC_NAME__,msg) +#define UTIL_WARN(cond,msg) \ + if(!(cond)) util_warn_(__FILE__,__LINE__,UTIL_FUNC_NAME__,msg) +#define UTIL_FAIL(msg) \ + util_fail_(__FILE__,__LINE__,UTIL_FUNC_NAME__,msg) + +#define ALLOC(ptr,type,num) \ + do { (ptr)=(type *)util_malloc_((num)*sizeof(type)); } while (0) +#define RALLOC(type,num) \ + ((type *)util_malloc_((num)*sizeof(type))) +#define DEALLOC(ptr) \ + do { util_free_(ptr); (ptr)=NULL; } while(0) +#define RESIZE(ptr,type,num) \ + do { util_free_(ptr); ALLOC(ptr,type,num); } while(0) +#define REALLOC(ptr,type,num) \ + do { \ + ptr = (type *)realloc(ptr,(num)*sizeof(type)); \ + UTIL_ASSERT(ptr,"realloc() failed"); \ + } while(0) +#define GROW(ptr,type,sz_old,sz_new) \ + do { \ + if ((sz_new)>(sz_old)) \ + { RESIZE(ptr,type,2*(sz_new));sz_old=2*(sz_new); } \ + } while(0) +#define SET_ARRAY(ptr,i1,i2,val) \ + do { \ + ptrdiff_t cnt_; \ + for (cnt_=(i1);cnt_<(i2);++cnt_) (ptr)[cnt_]=(val); \ + } while(0) +#define COPY_ARRAY(src,dest,i1,i2) \ + do { \ + ptrdiff_t cnt_; \ + for (cnt_=(i1);cnt_<(i2);++cnt_) (dest)[cnt_]=(src)[cnt_]; \ + } while(0) + +#define ALLOC2D(ptr,type,num1,num2) \ + do { \ + size_t cnt_, num1_=(num1), num2_=(num2); \ + ALLOC(ptr,type *,num1_); \ + ALLOC(ptr[0],type,num1_*num2_); \ + for (cnt_=1; cnt_(b)) ? (a) : (b)) +#define IMIN(a,b) \ + (((a)<(b)) ? (a) : (b)) + +#define SWAP(a,b,type) \ + do { type tmp_=(a); (a)=(b); (b)=tmp_; } while(0) + +#define CHECK_STACK_ALIGN(align) \ + do { \ + double foo; \ + UTIL_WARN((((size_t)(&foo))&(align-1))==0, \ + "WARNING: stack not sufficiently aligned!"); \ + } while(0) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/external/healpix/c_utils/planck.make b/external/healpix/c_utils/planck.make new file mode 100644 index 0000000..f4a2d30 --- /dev/null +++ b/external/healpix/c_utils/planck.make @@ -0,0 +1,18 @@ +PKG:=c_utils + +SD:=$(SRCROOT)/$(PKG) +OD:=$(BLDROOT)/$(PKG) + +FULL_INCLUDE+= -I$(SD) + +HDR_$(PKG):=$(SD)/*.h +LIB_$(PKG):=$(LIBDIR)/libc_utils.a + +OBJ:=c_utils.o walltime_c.o +OBJ:=$(OBJ:%=$(OD)/%) + +$(OBJ): $(HDR_$(PKG)) | $(OD)_mkdir +$(LIB_$(PKG)): $(OBJ) + +all_hdr+=$(HDR_$(PKG)) +all_lib+=$(LIB_$(PKG)) diff --git a/external/healpix/c_utils/sse_utils.h b/external/healpix/c_utils/sse_utils.h new file mode 100644 index 0000000..db27620 --- /dev/null +++ b/external/healpix/c_utils/sse_utils.h @@ -0,0 +1,137 @@ +/* + * This file is part of libc_utils. + * + * libc_utils 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. + * + * libc_utils 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 libc_utils; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * libc_utils is being developed at the Max-Planck-Institut fuer Astrophysik + * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt + * (DLR). + */ + +/*! \file sse_utils.h + * SSE/SSE2/SSE3-related functionality + * + * Copyright (C) 2010 Max-Planck-Society + * \author Martin Reinecke + */ + +#ifndef PLANCK_SSE_UTILS_H +#define PLANCK_SSE_UTILS_H + +#ifndef PLANCK_DISABLE_SSE + +#if (defined(__SSE__)) + +#include + +#define PLANCK_HAVE_SSE + +#ifdef __cplusplus +extern "C" { +#endif + +typedef __m128 v4sf; /* vector of 4 floats (SSE1) */ + +typedef union { + float f[4]; + v4sf v; +} V4SF; + +static inline v4sf build_v4sf (float a, float b, float c, float d) + { return _mm_set_ps(d,c,b,a); } +static inline void read_v4sf (v4sf v, float *a, float *b, float *c, float *d) + { + V4SF tmp; + tmp.v = v; + if (a) *a=tmp.f[0]; + if (b) *b=tmp.f[1]; + if (c) *c=tmp.f[2]; + if (d) *d=tmp.f[3]; + } + +#ifdef __cplusplus +} +#endif + +#endif + +#if (defined(__SSE2__)) + +#include + +#define PLANCK_HAVE_SSE2 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef __m128d v2df; /* vector of 2 doubles (SSE2) */ + +typedef union { + double d[2]; + v2df v; +} V2DF; + +typedef struct { + v2df a,b; +} v2df2; +typedef struct { + V2DF a,b; +} V2DF2; + +#define V2DF_SIGNMASK \ + _mm_castsi128_pd(_mm_set_epi32(-0x80000000,0,-0x80000000,0)) + +static inline v2df build_v2df (double a, double b) + { return _mm_set_pd(b,a); } +static inline void read_v2df (v2df v, double *a, double *b) + { _mm_store_sd(a,v); _mm_storeh_pd(b,v); } + +static inline int v2df_any_gt (v2df a, v2df b) + { + return (_mm_movemask_pd(_mm_cmpgt_pd(_mm_andnot_pd(V2DF_SIGNMASK,a),b))!=0); + } +static inline int v2df_all_ge (v2df a, v2df b) + { + return (_mm_movemask_pd(_mm_cmplt_pd(_mm_andnot_pd(V2DF_SIGNMASK,a),b))==0); + } +static inline V2DF to_V2DF (v2df x) + { V2DF X; X.v=x; return X; } +static inline V2DF2 to_V2DF2 (v2df2 x) + { V2DF2 X; X.a.v=x.a; X.b.v=x.b; return X; } +static inline v2df2 to_v2df2 (V2DF2 X) + { v2df2 x; x.a=X.a.v; x.b=X.b.v; return x; } +static inline v2df2 zero_v2df2(void) + { v2df2 x; x.a=x.b=_mm_setzero_pd(); return x; } + +#ifdef __cplusplus +} +#endif + +#endif + +#if (defined(__SSE3__)) + +#include + +#define PLANCK_HAVE_SSE3 + +#endif + +#endif + +#endif diff --git a/external/healpix/c_utils/walltime_c.c b/external/healpix/c_utils/walltime_c.c new file mode 100644 index 0000000..8eb896f --- /dev/null +++ b/external/healpix/c_utils/walltime_c.c @@ -0,0 +1,78 @@ +/* + * This file is part of libc_utils. + * + * libc_utils 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. + * + * libc_utils 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 libc_utils; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * libc_utils is being developed at the Max-Planck-Institut fuer Astrophysik + * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt + * (DLR). + */ + +/* + * Functionality for reading wall clock time + * + * Copyright (C) 2010 Max-Planck-Society + * Author: Martin Reinecke + */ + +#if defined (_OPENMP) +#include +#elif defined (USE_MPI) +#include "mpi.h" +#else +#include +#include +#endif + +#include "walltime_c.h" + +double wallTime(void) + { +#if defined (_OPENMP) + return omp_get_wtime(); +#elif defined (USE_MPI) + return MPI_Wtime(); +#else + struct timeval t; + gettimeofday(&t, NULL); + return t.tv_sec + 1e-6*t.tv_usec; +#endif + } + +typedef struct + { + double ts,ta; + int on; + } wTimer; + +#define NTIMERS 100 + +static wTimer wT[NTIMERS]; + +int wTimer_num(void) + { return NTIMERS; } +void wTimer_reset(int n) + { wT[n].ts=wT[n].ta=wT[n].on=0; } +void wTimer_start(int n) + { wT[n].ts=wallTime(); wT[n].on=1; } +void wTimer_stop(int n) + { + if (wT[n].on) + { wT[n].ta+=wallTime()-wT[n].ts; wT[n].on=0; } + } +double wTimer_acc(int n) + { return wT[n].on ? wT[n].ta+wallTime()-wT[n].ts : wT[n].ta; } diff --git a/external/healpix/c_utils/walltime_c.h b/external/healpix/c_utils/walltime_c.h new file mode 100644 index 0000000..7753d19 --- /dev/null +++ b/external/healpix/c_utils/walltime_c.h @@ -0,0 +1,59 @@ +/* + * This file is part of libc_utils. + * + * libc_utils 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. + * + * libc_utils 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 libc_utils; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * libc_utils is being developed at the Max-Planck-Institut fuer Astrophysik + * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt + * (DLR). + */ + +/*! \file walltime_c.h + * Functionality for reading wall clock time + * + * Copyright (C) 2010 Max-Planck-Society + * \author Martin Reinecke + */ + +#ifndef PLANCK_WALLTIME_C_H +#define PLANCK_WALLTIME_C_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*! Returns an approximation of the current wall time (in seconds). + The first available of the following timers will be used: +
    +
  • \a omp_get_wtime(), if OpenMP is available +
  • \a MPI_Wtime(), if MPI is available +
  • \a gettimeofday() otherwise +
  • + \note Only useful for measuring time differences. */ +double wallTime(void); + +int wTimer_num(void); +void wTimer_reset(int n); +void wTimer_start(int n); +void wTimer_stop(int n); +double wTimer_acc(int n); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/external/healpix/config/config.sampler b/external/healpix/config/config.sampler new file mode 100644 index 0000000..86bc5e4 --- /dev/null +++ b/external/healpix/config/config.sampler @@ -0,0 +1,33 @@ +LS_OPTFLAGS:= -O2 -ffast-math -fomit-frame-pointer $(EXTRA_CPPFLAGS) $(HEALPIX_EXTRAFLAGS) +LS_DEBUGFLAGS:= #-g + +ifeq ($(strip $(OMP_SUPPORT)),ON) +LS_OMPFLAGS= $(OMP_FLAGS) +else +LS_OMPFLAGS= -U_OPENMP +endif + +LS_PROFILEFLAGS:= #-pg +LS_STATICFLAGS:= #-static +LS_PICFLAGS:= -fPIC + +EXTERNAL_CFITSIO= yes +CFITSIO_EXT_PREFIX= ${HEALPIX_BASE_PATH}/ext_build/cfitsio +CFITSIO_EXT_LIB= ${CFITSIO_EXT_PREFIX}/lib/libcfitsio.a +CFITSIO_EXT_INC= ${CFITSIO_EXT_PREFIX}/include/ + +CC= $(HEALPIX_CC) +CL= $(HEALPIX_CC) +CWARNFLAGS= -Wall -Wextra -Wno-long-long -Wno-unknown-pragmas -Wshadow -Wmissing-prototypes -Wfatal-errors +CCFLAGS_NO_C= $(CWARNFLAGS) $(LS_PROFILEFLAGS) $(LS_DEBUGFLAGS) $(LS_OMPFLAGS) $(LS_PICFLAGS) $(LS_OPTFLAGS) -fno-strict-aliasing --std=gnu89 -pedantic -fdata-sections -ffunction-sections +CCFLAGS= $(CCFLAGS_NO_C) -c +CLFLAGS= -L. -L$(LIBDIR) $(LS_PROFILEFLAGS) $(LS_OMPFLAGS) $(LS_STATICFLAGS) $(LS_PICFLAGS) $(LS_OPTFLAGS) -lm + +CXX= $(HEALPIX_CXX) +CXXL= $(HEALPIX_CXX) +CXXWARNFLAGS= -Wall -Wextra -Wstrict-aliasing=2 -Wundef -Wshadow -Wwrite-strings -Wredundant-decls -Woverloaded-virtual -Wcast-qual -Wcast-align -Wpointer-arith -Wold-style-cast -Wno-unknown-pragmas -Wfatal-errors +CXXCFLAGS_NO_C= $(CXXWARNFLAGS) $(LS_PROFILEFLAGS) $(LS_DEBUGFLAGS) $(LS_OMPFLAGS) $(LS_PICFLAGS) $(LS_OPTFLAGS) -ansi -fdata-sections -ffunction-sections +CXXCFLAGS= $(CXXCFLAGS_NO_C) -c +CXXLFLAGS= -L. -L$(LIBDIR) $(LS_PROFILEFLAGS) $(LS_OMPFLAGS) $(LS_STATICFLAGS) $(LS_PICFLAGS) $(LS_OPTFLAGS) + +ARCREATE= ar cr diff --git a/external/healpix/config/config.sampler_osx b/external/healpix/config/config.sampler_osx new file mode 100644 index 0000000..b3d5f6c --- /dev/null +++ b/external/healpix/config/config.sampler_osx @@ -0,0 +1,27 @@ +LS_OPTFLAGS:= -O2 -ffast-math -fomit-frame-pointer $(HEALPIX_EXTRAFLAGS) +LS_DEBUGFLAGS:= #-g +LS_OMPFLAGS:= #-fopenmp +LS_PROFILEFLAGS:= #-pg +LS_STATICFLAGS:= #-static +LS_PICFLAGS:= -fPIC + +EXTERNAL_CFITSIO= yes +CFITSIO_EXT_PREFIX= ${HEALPIX_BASE_PATH}/../cfitsio +CFITSIO_EXT_LIB= ${CFITSIO_EXT_PREFIX}/libcfitsio.a +CFITSIO_EXT_INC= ${CFITSIO_EXT_PREFIX} + +CC= gcc +CL= gcc +CWARNFLAGS= -Wall -Wextra -Wno-long-long -Wno-unknown-pragmas -Wshadow -Wmissing-prototypes -Wfatal-errors +CCFLAGS_NO_C= $(CWARNFLAGS) $(LS_PROFILEFLAGS) $(LS_DEBUGFLAGS) $(LS_OMPFLAGS) $(LS_PICFLAGS) $(LS_OPTFLAGS) -fno-strict-aliasing --std=gnu89 -pedantic -fdata-sections -ffunction-sections +CCFLAGS= $(CCFLAGS_NO_C) -c +CLFLAGS= -L. -L$(LIBDIR) $(LS_PROFILEFLAGS) $(LS_OMPFLAGS) $(LS_STATICFLAGS) $(LS_PICFLAGS) $(LS_OPTFLAGS) -lm + +CXX= g++ +CXXL= g++ +CXXWARNFLAGS= -Wall -Wextra -Wstrict-aliasing=2 -Wundef -Wshadow -Wwrite-strings -Wredundant-decls -Woverloaded-virtual -Wcast-qual -Wcast-align -Wpointer-arith -Wold-style-cast -Wno-unknown-pragmas -Wfatal-errors +CXXCFLAGS_NO_C= $(CXXWARNFLAGS) $(LS_PROFILEFLAGS) $(LS_DEBUGFLAGS) $(LS_OMPFLAGS) $(LS_PICFLAGS) $(LS_OPTFLAGS) -ansi -fdata-sections -ffunction-sections +CXXCFLAGS= $(CXXCFLAGS_NO_C) -c +CXXLFLAGS= -L. -L$(LIBDIR) $(LS_PROFILEFLAGS) $(LS_OMPFLAGS) $(LS_STATICFLAGS) $(LS_PICFLAGS) $(LS_OPTFLAGS) + +ARCREATE= libtool -static -o diff --git a/external/healpix/config/rules.common b/external/healpix/config/rules.common new file mode 100644 index 0000000..1ceab63 --- /dev/null +++ b/external/healpix/config/rules.common @@ -0,0 +1,25 @@ +BLDROOT = $(SRCROOT)/build.$(HEALPIX_TARGET) +PREFIX = $(SRCROOT)/$(HEALPIX_TARGET) +BINDIR = $(PREFIX)/bin +INCDIR = $(PREFIX)/include +LIBDIR = $(PREFIX)/lib +DOCDIR = $(SRCROOT)/doc + +# do not use any suffix rules +.SUFFIXES: +# do not use any default rules +.DEFAULT: + +$(BLDROOT)/%.o : $(SRCROOT)/%.c + @echo "# compiling $*.c" + cd $(@D) && $(CC) $(FULL_INCLUDE) -I$(BLDROOT) $(CCFLAGS) $< + +$(BLDROOT)/%.o : $(SRCROOT)/%.cc + @echo "# compiling $*.cc" + cd $(@D) && $(CXX) $(FULL_INCLUDE) -I$(BLDROOT) $(CXXCFLAGS) $< + +%_mkdir: + @if [ ! -d $* ]; then mkdir -p $* ; fi + +distclean: docsrc_clean + rm -rf $(BLDROOT) $(PREFIX) $(DOCDIR) $(SRCROOT)/test/test* diff --git a/external/healpix/cxxsupport/arr.h b/external/healpix/cxxsupport/arr.h new file mode 100644 index 0000000..cddee1c --- /dev/null +++ b/external/healpix/cxxsupport/arr.h @@ -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 +#include +#include "cxxutils.h" + +/*! \defgroup arraygroup Array classes */ +/*! \{ */ + +template class normalAlloc__ + { + public: + T *alloc(tsize sz) const { return (sz>0) ? new T[sz] : 0; } + void dealloc (T *ptr) const { delete[] ptr; } + }; + +template 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(res); + } + void dealloc(T *ptr) const + { + using namespace std; + if (ptr) free(ptr); + } + }; + + +/*! View of a 1D array */ +template 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 T &operator[] (T2 n) {return d[n];} + /*! Returns a constant reference to element \a n */ + template 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 void copyToPtr (T *ptr) const + { for (tsize m=0; m 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 vald[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 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; mmaxv) 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 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 T &operator[] (T2 n) {return d[n];} + /*! Returns a constant reference to element \a n */ + template const T &operator[] (T2 n) const {return d[n];} + }; + + +/*! One-dimensional array type, with selectable storage management. */ +template class arrT: public arr_ref + { + private: + storageManager stm; + bool own; + + void reset() + { this->d=0; this->s=0; own=true; } + + public: + /*! Creates a zero-sized array. */ + arrT() : arr_ref(0,0), own(true) {} + /*! Creates an array with \a sz entries. */ + arrT(tsize sz) : arr_ref(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(stm.alloc(sz),sz), own(true) + { arr_ref::fill(inival); } + /*! Creates an array with \a sz entries, which uses the memory pointed + to by \a ptr. + \note \a ptr will not 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 +
      +
    • \a T is a POD type
    • +
    • \a ptr survives during the lifetime of the array object
    • +
    • \a ptr is not subject to garbage collection
    • +
    + Other restrictions may apply. You have been warned. */ + arrT (T *ptr, tsize sz): arr_ref(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(stm.alloc(orig.s),orig.s), own(true) + { for (tsize m=0; ms; ++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; ms; ++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 void copyFromPtr (const T2 *ptr, tsize sz) + { + alloc(sz); + for (tsize m=0; ms; ++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 + class arr: public arrT > + { + public: + /*! Creates a zero-sized array. */ + arr() : arrT >() {} + /*! Creates an array with \a sz entries. */ + arr(tsize sz) : arrT >(sz) {} + /*! Creates an array with \a sz entries, and initializes them with + \a inival. */ + arr(tsize sz, const T &inival) : arrT >(sz,inival) {} + /*! Creates an array with \a sz entries, which uses the memory pointed + to by \a ptr. + \note \a ptr will not 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 +
      +
    • \a T is a POD type
    • +
    • \a ptr survives during the lifetime of the array object
    • +
    • \a ptr is not subject to garbage collection
    • +
    + Other restrictions may apply. You have been warned. */ + arr (T *ptr, tsize sz): arrT >(ptr,sz) {} + }; + +/*! One-dimensional array type, with selectable storage alignment. */ +template + class arr_align: public arrT > + { + public: + /*! Creates a zero-sized array. */ + arr_align() : arrT >() {} + /*! Creates an array with \a sz entries. */ + arr_align(tsize sz) : arrT >(sz) {} + /*! Creates an array with \a sz entries, and initializes them with + \a inival. */ + arr_align(tsize sz, const T &inival) + : arrT >(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 class arr2T + { + private: + tsize s1, s2; + arrT 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 T *operator[] (T2 n) {return &d[n*s2];} + /*! Returns a constant pointer to the beginning of slice \a n. */ + template 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 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 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; mmaxv) 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 bool conformable + (const arr2T &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 + class arr2: public arr2T > + { + public: + /*! Creates a zero-sized array. */ + arr2() : arr2T > () {} + /*! Creates an array with the dimensions \a sz1 and \a sz2. */ + arr2(tsize sz1, tsize sz2) : arr2T > (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 > (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 + class arr2_align: public arr2T > + { + public: + /*! Creates a zero-sized array. */ + arr2_align() : arr2T > () {} + /*! Creates an array with the dimensions \a sz1 and \a sz2. */ + arr2_align(tsize sz1, tsize sz2) + : arr2T > (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 > (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 class arr2b + { + private: + tsize s1, s2; + arr d; + arr d1; + + void fill_d1() + { for (tsize m=0; m T *operator[] (T2 n) {return d1[n];} + /*! Returns a constant pointer to the beginning of slice \a n. */ + template 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 class arr3 + { + private: + tsize s1, s2, s3, s2s3; + arr 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 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 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 bool conformable (const arr3 &other) const + { return (other.size1()==s1)&&(other.size2()==s2)&&(other.size3()==s3); } + }; + +/*! \} */ + +#endif diff --git a/external/healpix/cxxsupport/bstream.h b/external/healpix/cxxsupport/bstream.h new file mode 100644 index 0000000..6c7d030 --- /dev/null +++ b/external/healpix/cxxsupport/bstream.h @@ -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 +#include +#include +#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 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 inline void byteswap (T &val) + { byteswap_helper__ (reinterpret_cast (&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 bostream &put (const T *data, size_t num) + { + if ((sizeof(T)>1) && doswap) + for (size_t m=0; m (&tmp), sizeof(T)); + } + else + s.write (reinterpret_cast (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 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 bistream &get (T *data, size_t num) + { + s.read (reinterpret_cast (data), num*sizeof(T)); + if ((sizeof(T)>1) && doswap) + for (size_t m=0; m 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 bofstream &operator<< (const T &data) + { + if (doswap) + { + T tmp = data; + byteswap (tmp); + write (reinterpret_cast (&tmp), sizeof(T)); + } + else + write (reinterpret_cast (&data), sizeof(T)); + return *this; + } + template bofstream &put (const T *data, size_t num) + { + if (doswap) + for (size_t m=0; m (&tmp), sizeof(T)); + } + else + write (reinterpret_cast (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 bifstream &operator>> (T &data) + { + read (reinterpret_cast (&data), sizeof(T)); + if (doswap) byteswap (data); + return *this; + } + template bifstream &get (T *data, size_t num) + { + read (reinterpret_cast (data), num*sizeof(T)); + if (doswap) + for (size_t m=0; mModules page for an overview + of the supplied functionality. + */ diff --git a/external/healpix/cxxsupport/cxxutils.cc b/external/healpix/cxxsupport/cxxutils.cc new file mode 100644 index 0000000..9b2242d --- /dev/null +++ b/external/healpix/cxxsupport/cxxutils.cc @@ -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 +#include +#include +#include +#include +#include +#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 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 void stringToData (const string &x, T &value) + { + istringstream strstrm(x); + strstrm >> value; + end_stringToData (x,type2typename(),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(\""+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; m1) + 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 &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 void split (istream &stream, vector &list) + { + while (stream) + { + string word; + stream >> word; + planck_assert (stream||stream.eof(), + string("error while splitting stream into ") + type2typename() + + "components"); + if (stream) list.push_back(stringToData(word)); + } + } + +} // unnamed namespace + +template void split (const string &inp, vector &list) + { + istringstream stream(inp); + split (stream,list); + } + +template void split (const string &inp, vector &list); +template void split (const string &inp, vector &list); +template void split (const string &inp, vector &list); +template void split (const string &inp, vector &list); +template void split (const string &inp, vector &list); + +void tokenize (const string &inp, char delim, vector &list) + { + istringstream stream(inp); + string token; + list.clear(); + while (getline(stream,token,delim)) + list.push_back(token); + } diff --git a/external/healpix/cxxsupport/cxxutils.h b/external/healpix/cxxsupport/cxxutils.h new file mode 100644 index 0000000..d0cedaf --- /dev/null +++ b/external/healpix/cxxsupport/cxxutils.h @@ -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 +#include +#include +#include +#include +#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 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 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 inline I ifloor (F arg) + { + using namespace std; + return I(floor(arg)); + } + +/*! Returns the integer which is nearest to \a arg. */ +template inline I nearest (F arg) + { return ifloor(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 inline T weak_modulo (T v1, T v2) + { return (v1>=0) ? ((v1=0) ? ((v1 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 inline T sign (const T& signvalue) + { return (signvalue>=0) ? 1 : -1; } + +/*! Returns \a val*pow(-1,m) */ +template inline T xpow (I m, T val) + { return (m&1) ? -val : val; } + +template struct isqrt_helper__ + {}; +template struct isqrt_helper__ + { + static uint32 isqrt (I arg) + { + using namespace std; + return uint32 (sqrt(arg+0.5)); + } + }; +template struct isqrt_helper__ + { + static uint32 isqrt (I arg) + { + using namespace std; + long double arg2 = static_cast(arg)+0.5; + return uint32 (sqrt(arg2)); + } + }; + +/*! Returns the integer \a n, which fulfills \a n*n<=arg<(n+1)*(n+1). */ +template inline uint32 isqrt (I arg) + { return isqrt_helper__4)>::isqrt(arg); } + +/*! Returns the largest integer \a n that fulfills \a 2^n<=arg. */ +template 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 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 inline void interpol_helper + (const Iter &begin, const Iter &end, const T &val, tsize &idx, T &frac) + { interpol_helper (begin,end,val,std::less(),idx,frac); } + +/*! \} */ + +template inline bool multiequal (const T &a, const T &b, const T &c) + { return (a==b) && (a==c); } + +template inline bool multiequal (const T &a, const T &b, const T &c, + const T &d) + { return (a==b) && (a==c) && (a==d); } + +template 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 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 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 + inline void buildIndex (It begin, It end, std::vector &idx, Comp comp) + { + using namespace std; + T2 num=end-begin; + idx.resize(num); + for (T2 i=0; i(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 inline void buildIndex (It begin, It end, + std::vector &idx) + { + using namespace std; + typedef typename iterator_traits::value_type T; + buildIndex(begin,end,idx,less()); + } + +/*! 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 inline void sortByIndex (It begin, It end, + const std::vector &idx) + { + using namespace std; + typedef typename iterator_traits::value_type T; + T2 num=end-begin; + T *tmp= new T[num]; + for (T2 i=0; i inline void sortByIndex_inplace + (It begin, It end, const std::vector &idx) + { + using namespace std; + typedef typename iterator_traits::value_type T; + T2 num=end-begin; + vector done(num,false); + T2 cnt=0; + while (cnt inline void indirectSort (It begin, It end, + Comp comp) + { + using namespace std; + typedef typename iterator_traits::value_type T; + vector idx; + buildIndex (begin,end,idx,comp); + sortByIndex (begin,end,idx); + } + +template inline void indirectSort (It begin, It end) + { + using namespace std; + typedef typename iterator_traits::value_type T; + indirectSort(begin,end,less()); + } + +/*! \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 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 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 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 &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 void split (const std::string &inp, std::vector &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 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 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 &list); + +#endif diff --git a/external/healpix/cxxsupport/datatypes.h b/external/healpix/cxxsupport/datatypes.h new file mode 100644 index 0000000..7f6a322 --- /dev/null +++ b/external/healpix/cxxsupport/datatypes.h @@ -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 +#include +#include "error_handling.h" + +// Template magic to select the proper data types. These templates +// should not be used outside this file. + +template struct sizeChooserHelper__ + { typedef void TYPE; }; + +template struct sizeChooserHelper__ + { typedef T TYPE; }; + +template struct sizeChooserHelper2__ + { typedef T1 TYPE; }; + +template struct sizeChooserHelper2__ + { typedef T2 TYPE; }; + +template struct sizeChooserHelper2__ + { typedef T3 TYPE; }; + +template <> struct sizeChooserHelper2__ + { }; + +template + struct sizeChooser__ + { + typedef typename sizeChooserHelper2__ + ::TYPE, + typename sizeChooserHelper__::TYPE, + typename sizeChooserHelper__::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 inline PDT planckType(); +template<> inline PDT planckType () { return PLANCK_INT8; } +template<> inline PDT planckType () { return PLANCK_UINT8; } +template<> inline PDT planckType () { return PLANCK_INT16; } +template<> inline PDT planckType () { return PLANCK_UINT16; } +template<> inline PDT planckType () { return PLANCK_INT32; } +template<> inline PDT planckType () { return PLANCK_UINT32; } +template<> inline PDT planckType () { return PLANCK_INT64; } +template<> inline PDT planckType () { return PLANCK_UINT64; } +template<> inline PDT planckType () { return PLANCK_FLOAT32;} +template<> inline PDT planckType () { return PLANCK_FLOAT64;} +template<> inline PDT planckType () { return PLANCK_BOOL; } +template<> inline PDT planckType() { 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 inline const char *type2typename (); +template<> inline const char *type2typename () + { return "signed char"; } +template<> inline const char *type2typename () + { return "unsigned char"; } +template<> inline const char *type2typename () + { return "short"; } +template<> inline const char *type2typename () + { return "unsigned short"; } +template<> inline const char *type2typename () + { return "int"; } +template<> inline const char *type2typename () + { return "unsigned int"; } +template<> inline const char *type2typename () + { return "long"; } +template<> inline const char *type2typename () + { return "unsigned long"; } +template<> inline const char *type2typename () + { return "long long"; } +template<> inline const char *type2typename () + { return "unsigned long long"; } +template<> inline const char *type2typename () + { return "float"; } +template<> inline const char *type2typename () + { return "double"; } +template<> inline const char *type2typename () + { return "bool"; } +template<> inline const char *type2typename () + { 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 inline NDT nativeType(); +template<> inline NDT nativeType () { return NAT_CHAR; } +template<> inline NDT nativeType () { return NAT_SCHAR; } +template<> inline NDT nativeType () { return NAT_UCHAR; } +template<> inline NDT nativeType () { return NAT_SHORT; } +template<> inline NDT nativeType () { return NAT_USHORT; } +template<> inline NDT nativeType () { return NAT_INT; } +template<> inline NDT nativeType () { return NAT_UINT; } +template<> inline NDT nativeType () { return NAT_LONG; } +template<> inline NDT nativeType () { return NAT_ULONG; } +template<> inline NDT nativeType () { return NAT_LONGLONG; } +template<> inline NDT nativeType() { return NAT_ULONGLONG; } +template<> inline NDT nativeType () { return NAT_FLOAT; } +template<> inline NDT nativeType () { return NAT_DOUBLE; } +template<> inline NDT nativeType () { return NAT_LONGDOUBLE;} +template<> inline NDT nativeType () { 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 diff --git a/external/healpix/cxxsupport/error_handling.cc b/external/healpix/cxxsupport/error_handling.cc new file mode 100644 index 0000000..301ae91 --- /dev/null +++ b/external/healpix/cxxsupport/error_handling.cc @@ -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 +#include + +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; } diff --git a/external/healpix/cxxsupport/error_handling.h b/external/healpix/cxxsupport/error_handling.h new file mode 100644 index 0000000..1b2f288 --- /dev/null +++ b/external/healpix/cxxsupport/error_handling.h @@ -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 +#include + +#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 diff --git a/external/healpix/cxxsupport/fftpack_support.h b/external/healpix/cxxsupport/fftpack_support.h new file mode 100644 index 0000000..3351d01 --- /dev/null +++ b/external/healpix/cxxsupport/fftpack_support.h @@ -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 *data) + { complex_plan_forward(plan,&(data->re)); } + void backward (xcomplex *data) + { complex_plan_backward(plan,&(data->re)); } + void forward (arr >&data) + { forward(&(data[0].re)); } + void backward (arr >&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 &data) + { forward_fftpack(&(data[0])); } + void backward_fftpack (arr &data) + { backward_fftpack(&(data[0])); } + void forward_c (arr >&data) + { real_plan_forward_c(plan,&(data[0].re)); } + void backward_c (arr >&data) + { real_plan_backward_c(plan,&(data[0].re)); } + }; + +#endif diff --git a/external/healpix/cxxsupport/fitshandle.cc b/external/healpix/cxxsupport/fitshandle.cc new file mode 100644 index 0000000..0c8dd91 --- /dev/null +++ b/external/healpix/cxxsupport/fitshandle.cc @@ -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 +#include +#include +#include "fitsio.h" +#include "fitshandle.h" +#include "cxxutils.h" +#include "safe_cast.h" + +#define FPTR (static_cast (fptr)) +#define OFPTR (static_cast (orig.fptr)) + +using namespace std; + +namespace { + +template inline int fitsType(); +template<> inline int fitsType () { return TFLOAT; } +template<> inline int fitsType() { 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; mcolumns_.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 naxes(naxis); + fits_get_img_sizell (FPTR, naxis, &naxes[0], &status); + for (long m=0; m(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 &cols, + const string &extname) + { + clean_data(); + int ncol=cols.size(); + arr2b ttype(ncol,81), tform(ncol,81), tunit(ncol,81); + + for (long m=0; m(extname.c_str()), 0, &status); + check_errors(); + init_data(); + } + +void fitshandle::insert_asctab (const vector &cols, + const string &extname) + { + clean_data(); + int ncol=cols.size(); + arr2b ttype(ncol,81), tform(ncol,81), tunit(ncol,81); + + for (long m=0; m(extname.c_str()), &status); + check_errors(); + init_data(); + } + +void fitshandle::insert_image (PDT type, const vector &Axes) + { + clean_data(); + arr tmpax(Axes.size()); + for (long m=0; m + void fitshandle::insert_image (PDT type, const arr2 &data) + { + clean_data(); + arr tmpax(2); + tmpax[0] = data.size2(); tmpax[1] = data.size1(); + fits_insert_imgll (FPTR, type2bitpix(type), 2, &tmpax[0], &status); + arr2 &tmparr = const_cast &> (data); + fits_write_img (FPTR, fitsType(), 1, tmpax[0]*tmpax[1], + &tmparr[0][0], &status); + check_errors(); + init_data(); + } + +template void fitshandle::insert_image (PDT type, const arr2 &data); +template void fitshandle::insert_image (PDT type, const arr2 &data); + +void fitshandle::write_checksum() + { + planck_assert(connected(),"handle not connected to a file"); + fits_write_chksum (FPTR, &status); + check_errors(); + } + +const vector &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 &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(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(key2.c_str()), + const_cast(value), const_cast(comment.c_str()), + &status); + break; + case PLANCK_BOOL: + { + int val = *(static_cast(value)); + fits_update_key (FPTR, TLOGICAL, const_cast(key2.c_str()), + &val, const_cast(comment.c_str()), &status); + break; + } + case PLANCK_STRING: + { + string val = *(static_cast(value)); + fits_update_key_longstr (FPTR, const_cast(key2.c_str()), + const_cast(val.c_str()), const_cast(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(name.c_str()), + value, 0, &status); + getKeyHelper(name); + break; + case PLANCK_BOOL: + { + int val; + fits_read_key (FPTR, TLOGICAL, const_cast(name.c_str()), &val, 0, + &status); + getKeyHelper(name); + *(static_cast(value))=val; + break; + } + case PLANCK_STRING: + { + char *tmp=0; + fits_read_key_longstr (FPTR, const_cast(name.c_str()), &tmp, 0, + &status); + getKeyHelper(name); + *(static_cast(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(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(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(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 (data); + planck_assert(table_hdu(colnum),"incorrect FITS table access"); + planck_assert (num<=(nrows_-offset), + "read_column(): array too large"); + arr2b tdata(safe_cast(num), + safe_cast(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 (data); + planck_assert(table_hdu(colnum),"incorrect FITS table access"); + tsize stringlen = safe_cast(columns_[colnum-1].repcount()+1); + arr2b tdata(safe_cast(num), stringlen); + for (long m=0;m(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(data), + &status); + check_errors(); + } + +template void fitshandle::read_image (arr2 &data) const + { + planck_assert(image_hdu(),"not connected to an image"); + planck_assert (axes_.size()==2, "wrong number of dimensions"); + data.alloc(safe_cast(axes_[0]), safe_cast(axes_[1])); + fits_read_img (FPTR, fitsType(), 1, axes_[0]*axes_[1], 0, &data[0][0], 0, + &status); + check_errors(); + } + +template void fitshandle::read_image (arr2 &data) const; +template void fitshandle::read_image (arr2 &data) const; + +template void fitshandle::read_image (arr3 &data) const + { + planck_assert(image_hdu(),"not connected to an image"); + planck_assert (axes_.size()==3, "wrong number of dimensions"); + data.alloc(safe_cast(axes_[0]), safe_cast(axes_[1]), + safe_cast(axes_[2])); + fits_read_img (FPTR, fitsType(), 1, axes_[0]*axes_[1]*axes_[2], + 0, &data(0,0,0), 0, &status); + check_errors(); + } + +template void fitshandle::read_image (arr3 &data) const; +template void fitshandle::read_image (arr3 &data) const; + +template void fitshandle::read_subimage + (arr2 &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(), (xl+m)*axes_[1]+yl+1, + data.size2(), 0, &data[m][0], 0, &status); + check_errors(); + } + +template void fitshandle::read_subimage + (arr2 &data, int xl, int yl) const; +template void fitshandle::read_subimage + (arr2 &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(1000.*CFITSIO_VERSION), + v_library = nearest(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 diff --git a/external/healpix/cxxsupport/fitshandle.h b/external/healpix/cxxsupport/fitshandle.h new file mode 100644 index 0000000..17d9b76 --- /dev/null +++ b/external/healpix/cxxsupport/fitshandle.h @@ -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 +#include +#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 axes_; + std::vector 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 &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 &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 &Axes); + /*! Inserts a 2D FITS image with the type given by \a type, whose + contents are given in \a data. */ + template + void insert_image (PDT type, const arr2 &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 &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 &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 void set_key (const std::string &name, + const T &value, const std::string &comment="") + { set_key_void (name, &value, planckType(), 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 void get_key (const std::string &name, T &value) const + { get_key_void (name,&value,planckType()); } + /*! Returms the value belonging to \a key. */ + template 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 void read_column_raw + (int colnum, T *data, int64 num, int64 offset=0) const + { read_column_raw_void (colnum, data, planckType(), num, offset); } + /*! Fills \a data with elements from column \a colnum, + starting at offset \a offset in the column. */ + template void read_column + (int colnum, arr &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 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 void read_entire_column + (int colnum, arr &data) const + { + data.alloc(safe_cast(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 void write_column_raw + (int colnum, const T *data, int64 num, int64 offset=0) + { write_column_raw_void (colnum, data, planckType(), num, offset); } + /*! Copies all elements from \a data to the + column \a colnum, starting at offset \a offset in the column. */ + template void write_column + (int colnum, const arr &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 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 void read_image (arr2 &data) const; + /*! Reads the current image into \a data, which is resized accordingly. */ + template void read_image (arr3 &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 void read_subimage + (arr2 &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 void read_subimage (arr &data, int64 offset=0) + const + { read_subimage_void (&data[0],planckType(),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 void write_image (const arr2 &data) + { + write_image2D_void (&data[0][0],planckType(),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 void write_subimage (const arr &data, + int64 offset=0) + { write_subimage_void(&data[0],planckType(),data.size(),offset); } + + /*! \} */ + }; + +/*! \} */ + +#endif diff --git a/external/healpix/cxxsupport/font_data.inc b/external/healpix/cxxsupport/font_data.inc new file mode 100644 index 0000000..ea669e2 --- /dev/null +++ b/external/healpix/cxxsupport/font_data.inc @@ -0,0 +1,3848 @@ +#ifndef PLANCK_FONT_DATA_INC +#define PLANCK_FONT_DATA_INC + +const char *medium_bold_font_data= +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " + +" " +" " +" " +" " +" " +" XX " +" XXXX " +"XXXXXX " +" XXXX " +" XX " +" " +" " +" " + +" " +" " +" " +"XX XX " +"XX XX " +" XX " +"XX XX " +"XX XX " +" XX " +"XX XX " +"XX XX " +" " +" " + +" " +"XX XX " +"XX XX " +"XXXXX " +"XX XX " +"XX XX " +" " +" XXXX " +" XX " +" XX " +" XX " +" XX " +" " + +" " +"XXXX " +"XX " +"XXX " +"XX " +"XX " +" " +" XXXX " +" XX " +" XXX " +" XX " +" XX " +" " + +" " +" XXX " +"XX " +"XX " +"XX " +" XXX " +" " +" XXX " +" XX X " +" XXX " +" XX X " +" XX X " +" " + +" " +"XX " +"XX " +"XX " +"XX " +"XXXX " +" " +" XXXX " +" XX " +" XXX " +" XX " +" XX " +" " + +" " +" " +" XXXX " +"XX XX " +"XX XX " +" XXXX " +" " +" " +" " +" " +" " +" " +" " + +" " +" " +" XX " +" XX " +"XXXXXX " +"XXXXXX " +" XX " +" XX " +" " +"XXXXXX " +"XXXXXX " +" " +" " + +" " +"XX XX " +"XXX XX " +"XXXXXX " +"XX XXX " +"XX XX " +" " +" XX " +" XX " +" XX " +" XX " +" XXXX " +" " + +" " +"XX XX " +"XX XX " +" X X " +" XXXX " +" XX " +" " +" XXXX " +" XX " +" XX " +" XX " +" XX " +" " + +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +"XXXX " +"XXXX " +" " +" " +" " +" " +" " + +" " +" " +" " +" " +" " +" " +"XXXX " +"XXXX " +" XX " +" XX " +" XX " +" XX " +" XX " + +" " +" " +" " +" " +" " +" " +" XXXXX" +" XXXXX" +" XX " +" XX " +" XX " +" XX " +" XX " + +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XXXXX" +" XXXXX" +" " +" " +" " +" " +" " + +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +"XXXXXXX" +"XXXXXXX" +" XX " +" XX " +" XX " +" XX " +" XX " + +" " +" " +"XXXXXXX" +"XXXXXXX" +" " +" " +" " +" " +" " +" " +" " +" " +" " + +" " +" " +" " +" " +"XXXXXXX" +"XXXXXXX" +" " +" " +" " +" " +" " +" " +" " + +" " +" " +" " +" " +" " +" " +"XXXXXXX" +"XXXXXXX" +" " +" " +" " +" " +" " + +" " +" " +" " +" " +" " +" " +" " +" " +"XXXXXXX" +"XXXXXXX" +" " +" " +" " + +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +"XXXXXXX" +"XXXXXXX" +" " + +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XXXXX" +" XXXXX" +" XX " +" XX " +" XX " +" XX " +" XX " + +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +"XXXX " +"XXXX " +" XX " +" XX " +" XX " +" XX " +" XX " + +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +"XXXXXXX" +"XXXXXXX" +" " +" " +" " +" " +" " + +" " +" " +" " +" " +" " +" " +"XXXXXXX" +"XXXXXXX" +" XX " +" XX " +" XX " +" XX " +" XX " + +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " + +" " +" " +" XX " +" XX " +" XX " +"XX " +" XX " +" XX " +" XX " +"XXXXXX " +"XXXXXX " +" " +" " + +" " +" " +"XX " +" XX " +" XX " +" XX " +" XX " +" XX " +"XX " +"XXXXXX " +"XXXXXX " +" " +" " + +" " +" " +" " +" " +" " +"XXXXXX " +" XX XX " +" XX XX " +" XX XX " +"XXX XX " +"XX XX " +" " +" " + +" " +" " +" X " +" XX " +"XXXXXX " +"XXXXXX " +" XX " +"XXXXXX " +"XXXXXX " +"XX " +"X " +" " +" " + +" " +" " +" XXX " +" XX XX " +" XX " +" XX " +"XXXX " +" XX " +" XX " +" XX XX " +"X XXX " +" " +" " + +" " +" " +" " +" " +" " +" " +" XX " +" XX " +" " +" " +" " +" " +" " + +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " + +" " +" " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" " +" XX " +" XX " +" " +" " + +" " +" " +" XX XX " +" XX XX " +" XX XX " +" " +" " +" " +" " +" " +" " +" " +" " + +" " +" " +" X X " +" X X " +" XXXXX " +" XXXXX " +" X X " +" XXXXX " +" XXXXX " +" X X " +" X X " +" " +" " + +" " +" " +" XX " +" XXXX " +"X XX X " +"X XX " +" XXXX " +" XX X " +"X XX X " +" XXXX " +" XX " +" " +" " + +" " +" " +"XXX X " +"X X XX " +"XXX X " +" XX " +" XX " +" XX " +" X XXX " +"XX X X " +"X XXX " +" " +" " + +" " +" " +" XXX " +"XX XX " +"XX XX " +"XX XX " +" XXX " +"XX X X " +"XX XXX " +"XX XX " +" XXX X " +" " +" " + +" " +" " +" XXX " +" XXX " +" XX " +" XX " +" " +" " +" " +" " +" " +" " +" " + +" " +" " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" " +" " + +" " +" " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" " +" " + +" " +" " +" " +" " +" X X " +" XX " +"XXXXXX " +"XXXXXX " +" XX " +" X X " +" " +" " +" " + +" " +" " +" " +" " +" XX " +" XX " +"XXXXXX " +"XXXXXX " +" XX " +" XX " +" " +" " +" " + +" " +" " +" " +" " +" " +" " +" " +" " +" XXX " +" XXX " +" XX " +" XX " +" " + +" " +" " +" " +" " +" " +" " +"XXXXXX " +"XXXXXX " +" " +" " +" " +" " +" " + +" " +" " +" " +" " +" " +" " +" " +" " +" " +" XX " +" XXXX " +" XX " +" " + +" " +" " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +"XX " +"XX " +" " +" " + +" " +" " +" XX " +" X X " +"XX XX " +"XX XX " +"XX XX " +"XX XX " +"XX XX " +" X X " +" XX " +" " +" " + +" " +" " +" XX " +" XXX " +"X XX " +" XX " +" XX " +" XX " +" XX " +" XX " +"XXXXXX " +" " +" " + +" " +" " +" XXXX " +"XX XX " +"XX XX " +" XX " +" XXX " +" XX " +"XX " +"XX " +"XXXXXX " +" " +" " + +" " +" " +" XXXX " +"XX XX " +" XX " +" XX " +" XXX " +" XX " +" XX " +"XX XX " +" XXXX " +" " +" " + +" " +" " +" XX " +" XXX " +" XXXX " +" XX XX " +"XX XX " +"XX XX " +"XXXXXX " +" XX " +" XX " +" " +" " + +" " +" " +"XXXXXX " +"XX " +"XX " +"XXXXX " +"XX XX " +" XX " +" XX " +"XX XX " +" XXXX " +" " +" " + +" " +" " +" XXXX " +"XX XX " +"XX " +"XX " +"XXXXX " +"XX XX " +"XX XX " +"XX XX " +" XXXX " +" " +" " + +" " +" " +"XXXXXX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" " +" " + +" " +" " +" XXXX " +"XX XX " +"XX XX " +"XX XX " +" XXXX " +"XX XX " +"XX XX " +"XX XX " +" XXXX " +" " +" " + +" " +" " +" XXXX " +"XX XX " +"XX XX " +"XX XX " +" XXXXX " +" XX " +" XX " +"XX XX " +" XXXX " +" " +" " + +" " +" " +" " +" " +" XX " +" XXXX " +" XX " +" " +" " +" XX " +" XXXX " +" XX " +" " + +" " +" " +" " +" " +" XX " +" XXXX " +" XX " +" " +" XXX " +" XXX " +" XX " +" XX " +" " + +" " +" " +" XX " +" XX " +" XX " +" XX " +"XX " +" XX " +" XX " +" XX " +" XX " +" " +" " + +" " +" " +" " +" " +"XXXXXX " +"XXXXXX " +" " +"XXXXXX " +"XXXXXX " +" " +" " +" " +" " + +" " +" " +"XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +"XX " +" " +" " + +" " +" " +" XXXX " +"XX XX " +"XX XX " +" XX " +" XXX " +" XX " +" " +" XX " +" XX " +" " +" " + +" " +" " +" XXXX " +"X XX " +"X XX " +"X XXXX " +"X X XX " +"X XXXX " +"X " +"X XX " +" XXXX " +" " +" " + +" " +" " +" XXXX " +"XX XX " +"XX XX " +"XX XX " +"XXXXXX " +"XX XX " +"XX XX " +"XX XX " +"XX XX " +" " +" " + +" " +" " +"XXXXX " +"XX XX " +"XX XX " +"XX XX " +"XXXXX " +"XX XX " +"XX XX " +"XX XX " +"XXXXX " +" " +" " + +" " +" " +" XXXX " +"XX XX " +"XX " +"XX " +"XX " +"XX " +"XX " +"XX XX " +" XXXX " +" " +" " + +" " +" " +"XXXXX " +"XX XX " +"XX XX " +"XX XX " +"XX XX " +"XX XX " +"XX XX " +"XX XX " +"XXXXX " +" " +" " + +" " +" " +"XXXXXX " +"XX " +"XX " +"XX " +"XXXXX " +"XX " +"XX " +"XX " +"XXXXXX " +" " +" " + +" " +" " +"XXXXXX " +"XX " +"XX " +"XX " +"XXXXX " +"XX " +"XX " +"XX " +"XX " +" " +" " + +" " +" " +" XXXX " +"XX XX " +"XX " +"XX " +"XX XXX " +"XX XX " +"XX XX " +"XX XX " +" XXXXX " +" " +" " + +" " +" " +"XX XX " +"XX XX " +"XX XX " +"XX XX " +"XXXXXX " +"XX XX " +"XX XX " +"XX XX " +"XX XX " +" " +" " + +" " +" " +"XXXXXX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +"XXXXXX " +" " +" " + +" " +" " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +"XX XX " +" XXXX " +" " +" " + +" " +" " +"XX X " +"XX XX " +"XX XX " +"XXXX " +"XXX " +"XXXX " +"XX XX " +"XX XX " +"XX X " +" " +" " + +" " +" " +"XX " +"XX " +"XX " +"XX " +"XX " +"XX " +"XX " +"XX " +"XXXXXX " +" " +" " + +" " +" " +"X X " +"XX XX " +"XXXXXX " +"XXXXXX " +"XX XX " +"XX XX " +"XX XX " +"XX XX " +"XX XX " +" " +" " + +" " +" " +"XX XX " +"XX XX " +"XXX XX " +"XXX XX " +"XXXXXX " +"XX XXX " +"XX XXX " +"XX XX " +"XX XX " +" " +" " + +" " +" " +" XXXX " +"XX XX " +"XX XX " +"XX XX " +"XX XX " +"XX XX " +"XX XX " +"XX XX " +" XXXX " +" " +" " + +" " +" " +"XXXXX " +"XX XX " +"XX XX " +"XX XX " +"XXXXX " +"XX " +"XX " +"XX " +"XX " +" " +" " + +" " +" " +" XXXX " +"XX XX " +"XX XX " +"XX XX " +"XX XX " +"XX XX " +"XXX XX " +"XX XXX " +" XXXX " +" XX " +" " + +" " +" " +"XXXXX " +"XX XX " +"XX XX " +"XX XX " +"XXXXX " +"XXXX " +"XX XX " +"XX XX " +"XX X " +" " +" " + +" " +" " +" XXXX " +"XX XX " +"XX " +"XX " +" XXXX " +" XX " +" XX " +"XX XX " +" XXXX " +" " +" " + +" " +" " +"XXXXXX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" " +" " + +" " +" " +"XX XX " +"XX XX " +"XX XX " +"XX XX " +"XX XX " +"XX XX " +"XX XX " +"XX XX " +" XXXX " +" " +" " + +" " +" " +"XX XX " +"XX XX " +"XX XX " +" X X " +" X X " +" XXXX " +" XX " +" XX " +" XX " +" " +" " + +" " +" " +"XX XX " +"XX XX " +"XX XX " +"XX XX " +"XX XX " +"XXXXXX " +"XXXXXX " +"XX XX " +"X X " +" " +" " + +" " +" " +"X X " +"XX XX " +" X X " +" XXXX " +" XX " +" XXXX " +" X X " +"XX XX " +"X X " +" " +" " + +" " +" " +"XX XX " +"XX XX " +" XXXX " +" XXXX " +" XX " +" XX " +" XX " +" XX " +" XX " +" " +" " + +" " +" " +"XXXXXX " +" XX " +" XX " +" XX " +" XX " +" XX " +"XX " +"XX " +"XXXXXX " +" " +" " + +" " +" " +" XXXX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XXXX " +" " +" " + +" " +" " +"XX " +"XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" " +" " + +" " +" " +" XXXX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XXXX " +" " +" " + +" " +" " +" XX " +" XXXX " +"XX XX " +"X X " +" " +" " +" " +" " +" " +" " +" " + +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +"XXXXXX " +"XXXXXX " +" " + +" " +" " +" XXX " +" XXX " +" XX " +" XX " +" " +" " +" " +" " +" " +" " +" " + +" " +" " +" " +" " +" " +" XXXX " +" XX " +" XXXXX " +"XX XX " +"XX XX " +" XXXXX " +" " +" " + +" " +" " +"XX " +"XX " +"XX " +"XXXXX " +"XX XX " +"XX XX " +"XX XX " +"XX XX " +"XXXXX " +" " +" " + +" " +" " +" " +" " +" " +" XXXX " +"XX XX " +"XX " +"XX " +"XX XX " +" XXXX " +" " +" " + +" " +" " +" XX " +" XX " +" XX " +" XXXXX " +"XX XX " +"XX XX " +"XX XX " +"XX XX " +" XXXXX " +" " +" " + +" " +" " +" " +" " +" " +" XXXX " +"XX XX " +"XXXXXX " +"XX " +"XX XX " +" XXXX " +" " +" " + +" " +" " +" XXX " +" XX XX " +" XX " +" XX " +"XXXX " +" XX " +" XX " +" XX " +" XX " +" " +" " + +" " +" " +" " +" " +" " +" XXX X " +"XX XX " +"XX XX " +" XXXX " +"XX " +" XXXX " +"XX XX " +" XXXX " + +" " +" " +"XX " +"XX " +"XX " +"XXXXX " +"XX XX " +"XX XX " +"XX XX " +"XX XX " +"XX XX " +" " +" " + +" " +" " +" XX " +" XX " +" " +" XXX " +" XX " +" XX " +" XX " +" XX " +"XXXXXX " +" " +" " + +" " +" " +" XX " +" XX " +" " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +"XX XX " +" XXXX " + +" " +" " +"XX " +"XX " +"XX " +"XX XX " +"XX XX " +"XXXX " +"XXXX " +"XX XX " +"XX XX " +" " +" " + +" " +" " +" XXX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +"XXXXXX " +" " +" " + +" " +" " +" " +" " +" " +"XX XX " +"XXXXXX " +"XXXXXX " +"XX XX " +"XX XX " +"XX XX " +" " +" " + +" " +" " +" " +" " +" " +"XXXXX " +"XX XX " +"XX XX " +"XX XX " +"XX XX " +"XX XX " +" " +" " + +" " +" " +" " +" " +" " +" XXXX " +"XX XX " +"XX XX " +"XX XX " +"XX XX " +" XXXX " +" " +" " + +" " +" " +" " +" " +" " +"XXXXX " +"XX XX " +"XX XX " +"XX XX " +"XXXXX " +"XX " +"XX " +"XX " + +" " +" " +" " +" " +" " +" XXXXX " +"XX XX " +"XX XX " +"XX XX " +" XXXXX " +" XX " +" XX " +" XX " + +" " +" " +" " +" " +" " +"XXXXX " +"XX XX " +"XX " +"XX " +"XX " +"XX " +" " +" " + +" " +" " +" " +" " +" " +" XXXX " +"XX XX " +" XX " +" XX " +"XX XX " +" XXXX " +" " +" " + +" " +" " +" " +"XX " +"XX " +"XXXX " +"XX " +"XX " +"XX " +"XX XX " +" XXXX " +" " +" " + +" " +" " +" " +" " +" " +"XX XX " +"XX XX " +"XX XX " +"XX XX " +"XX XX " +" XXXXX " +" " +" " + +" " +" " +" " +" " +" " +"XX XX " +"XX XX " +"XX XX " +" XXXX " +" XXXX " +" XX " +" " +" " + +" " +" " +" " +" " +" " +"XX XX " +"XX XX " +"XX XX " +"XXXXXX " +"XXXXXX " +" X X " +" " +" " + +" " +" " +" " +" " +" " +"XX XX " +"XX XX " +" XXXX " +" XXXX " +"XX XX " +"XX XX " +" " +" " + +" " +" " +" " +" " +" " +"XX XX " +"XX XX " +"XX XX " +"XX XX " +" XXXXX " +" XX " +"XX XX " +" XXXX " + +" " +" " +" " +" " +" " +"XXXXXX " +" XX " +" XX " +" XX " +"XX " +"XXXXXX " +" " +" " + +" " +" " +" XXX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XXX " +" " +" " + +" " +" " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" " +" " + +" " +" " +" XXX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XXX " +" " +" " + +" " +" " +" XX X " +"XXXXXX " +"X XX " +" " +" " +" " +" " +" " +" " +" " +" " + +" X X X " +" X X " +" X X X " +" X X " +" X X X " +" X X " +" X X X " +" X X " +" X X X " +" X X " +" X X X " +" X X " +" X X X " +; + +const char *giant_font_data = +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " + +" " +" " +" " +" " +" " +" XX " +" XXXX " +" XXXXXX " +" XXXXXXXX" +" XXXXXX " +" XXXX " +" XX " +" " +" " +" " + +" " +" " +" " +" " +" " +" XX XX XX" +" XX XX " +" XX XX XX" +" XX XX " +" XX XX XX" +" XX XX " +" XX XX XX" +" " +" " +" " + +" " +" " +" " +" XX XX " +" XX XX " +" XXXXXX " +" XX XX " +" XX XX " +" " +" XXXXXX" +" XX " +" XX " +" XX " +" XX " +" " + +" " +" " +" " +" XXXXX " +" XX " +" XXXX " +" XX " +" XX " +" " +" XXXXX" +" XX " +" XXXX " +" XX " +" XX " +" " + +" " +" " +" " +" XXXXX " +" XX X " +" XX " +" XX X " +" XXXXX " +" " +" XXXXX " +" XX XX" +" XXXXX " +" XX XX" +" XX XX" +" " + +" " +" " +" " +" XX " +" XX " +" XX " +" XX " +" XXXXX " +" " +" XXXXX" +" XX " +" XXXX " +" XX " +" XX " +" " + +" " +" " +" " +" " +" " +" XXXX " +" XX XX " +" XX XX " +" XXXX " +" " +" " +" " +" " +" " +" " + +" " +" " +" XX " +" XX " +" XX " +" XXXXXXXX" +" XXXXXXXX" +" XX " +" XX " +" XX " +" " +" XXXXXXXX" +" XXXXXXXX" +" " +" " + +" " +" " +" " +" XX XX " +" XXX XX " +" XXXXXX " +" XX XXX " +" XX XX " +" " +" XX " +" XX " +" XX " +" XX " +" XXXXX" +" " + +" " +" " +" " +" XX XX " +" XX XX " +" XX XX " +" XXXX " +" XX " +" " +" XXXXXX" +" XX " +" XX " +" XX " +" XX " +" " + +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +"XXXXXX " +"XXXXXX " +" " +" " +" " +" " +" " +" " + +" " +" " +" " +" " +" " +" " +" " +"XXXXXX " +"XXXXXX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " + +" " +" " +" " +" " +" " +" " +" " +" XXXXX" +" XXXXX" +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " + +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XXXXX" +" XXXXX" +" " +" " +" " +" " +" " +" " + +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +"XXXXXXXXX" +"XXXXXXXXX" +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " + +" " +" " +" " +"XXXXXXXXX" +"XXXXXXXXX" +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " + +" " +" " +" " +" " +" " +"XXXXXXXXX" +"XXXXXXXXX" +" " +" " +" " +" " +" " +" " +" " +" " + +" " +" " +" " +" " +" " +" " +" " +"XXXXXXXXX" +"XXXXXXXXX" +" " +" " +" " +" " +" " +" " + +" " +" " +" " +" " +" " +" " +" " +" " +" " +"XXXXXXXXX" +"XXXXXXXXX" +" " +" " +" " +" " + +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +"XXXXXXXXX" +"XXXXXXXXX" +" " +" " + +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XXXXX" +" XXXXX" +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " + +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +"XXXXXX " +"XXXXXX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " + +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +"XXXXXXXXX" +"XXXXXXXXX" +" " +" " +" " +" " +" " +" " + +" " +" " +" " +" " +" " +" " +" " +"XXXXXXXXX" +"XXXXXXXXX" +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " + +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " + +" " +" " +" " +" XXX" +" XXX " +" XXX " +" XX " +" XXX " +" XXX " +" XXX" +" " +" XXXXXXXX" +" XXXXXXXX" +" " +" " + +" " +" " +" " +" XXX " +" XXX " +" XXX " +" XX" +" XXX " +" XXX " +" XXX " +" " +" XXXXXXXX" +" XXXXXXXX" +" " +" " + +" " +" " +" " +" " +" " +" XXXXXXXX" +" XXXXXXXX" +" X XX " +" X XX " +" X XX " +" XXX XX " +" XXX XX " +" " +" " +" " + +" " +" " +" " +" XX" +" XX " +" XXXXXXXX" +" XXXXXXXX" +" XX " +" XXXXXXXX" +" XXXXXXXX" +" XX " +" XX " +" " +" " +" " + +" " +" " +" " +" XXXX " +" XX XX" +" XX " +" XX " +" XXXXXX " +" XX " +" XX " +" XXXXX " +" X XXXXXX" +" XXX " +" " +" " + +" " +" " +" " +" " +" " +" " +" " +" XX " +" XX " +" " +" " +" " +" " +" " +" " + +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " + +" " +" " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" " +" XX " +" " +" " +" " + +" " +" " +" XX XX " +" XX XX " +" XX XX " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " + +" " +" " +" " +" XX XX " +" XX XX " +" XXXXXXX " +" XX XX " +" XX XX " +" XXXXXXX " +" XX XX " +" XX XX " +" " +" " +" " +" " + +" " +" " +" X " +" XXXXX " +" XX X XX" +" XX X " +" XXXX " +" XXXXX " +" XXXX" +" X XX" +" XX X XX" +" XXXXX " +" X " +" " +" " + +" " +" " +" XX XX" +" XXXX XX " +" XXXX XX " +" XX XX " +" XX " +" XX " +" XX XX " +" XX XXXX" +" XX XXXX" +" XX XX " +" " +" " +" " + +" " +" " +" XXXX " +" XX XX " +" XX XX " +" XX XX " +" XXXX " +" XX XX " +" XX XXXX" +" XX XX " +" XX XXX " +" XXXX XX" +" " +" " +" " + +" " +" " +" XXXX " +" XXX " +" XX " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " + +" " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" " +" " + +" " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" " +" " + +" " +" " +" " +" X " +" XX X XX " +" XXXXX " +" XXX " +" XXX XXX " +" XXX " +" XXXXX " +" XX X XX " +" X " +" " +" " +" " + +" " +" " +" " +" " +" XX " +" XX " +" XX " +" XXXXXXXX" +" XX " +" XX " +" XX " +" " +" " +" " +" " + +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" XXXX " +" XXX " +" XX " +" " +" " + +" " +" " +" " +" " +" " +" " +" " +" XXXXXXXX" +" " +" " +" " +" " +" " +" " +" " + +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" XX " +" XXXX " +" XX " +" " +" " + +" " +" " +" XX" +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" " +" " +" " + +" " +" " +" XXXX " +" XX XX " +" XX XX" +" XX XX" +" XX XX" +" XX XX" +" XX XX" +" XX XX" +" XX XX " +" XXXX " +" " +" " +" " + +" " +" " +" XX " +" XXX " +" XXXX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XXXXXX " +" " +" " +" " + +" " +" " +" XXXXXX " +" XX XX" +" XX XX" +" XX" +" XX " +" XX " +" XXX " +" XX " +" XX " +" XXXXXXXX" +" " +" " +" " + +" " +" " +" XXXXXXXX" +" XX" +" XX " +" XX " +" XXXX " +" XX" +" XX" +" XX" +" XX XX" +" XXXXXX " +" " +" " +" " + +" " +" " +" XX " +" XXX " +" XXXX " +" XX XX " +" XX XX " +" XX XX " +" XXXXXXXX" +" XX " +" XX " +" XX " +" " +" " +" " + +" " +" " +" XXXXXXXX" +" XX " +" XX " +" XXXXXXX " +" XXX XX" +" XX" +" XX" +" XX" +" XX XX" +" XXXXXX " +" " +" " +" " + +" " +" " +" XXXXX " +" XX " +" XX " +" XX " +" XXXXXXX " +" XXX XX" +" XX XX" +" XX XX" +" XX XX" +" XXXXXX " +" " +" " +" " + +" " +" " +" XXXXXXXX" +" XX" +" XX" +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" " +" " +" " + +" " +" " +" XXXXXX " +" XX XX" +" XX XX" +" XX XX" +" XXXXXX " +" XX XX" +" XX XX" +" XX XX" +" XX XX" +" XXXXXX " +" " +" " +" " + +" " +" " +" XXXXXX " +" XX XX" +" XX XX" +" XX XX" +" XX XXX" +" XXXXXXX" +" XX" +" XX" +" XX " +" XXXXX " +" " +" " +" " + +" " +" " +" " +" " +" " +" XX " +" XXXX " +" XX " +" " +" " +" XX " +" XXXX " +" XX " +" " +" " + +" " +" " +" " +" " +" " +" XX " +" XXXX " +" XX " +" " +" " +" XXXX " +" XXX " +" XX " +" " +" " + +" " +" " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" " +" " +" " + +" " +" " +" " +" " +" " +" " +" XXXXXXXX" +" " +" " +" XXXXXXXX" +" " +" " +" " +" " +" " + +" " +" " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" " +" " +" " + +" " +" " +" XXXXXX " +" XX XX" +" XX XX" +" XX" +" XX " +" XX " +" XX " +" XX " +" " +" XX " +" " +" " +" " + +" " +" " +" XXXXXX " +" XX XX" +" XX XX" +" XX XXXXX" +" XXXX XX" +" XXXX XXX" +" XX XXXXX" +" XX " +" XX " +" XXXXXX " +" " +" " +" " + +" " +" " +" XX " +" XXXX " +" XX XX " +" XX XX" +" XX XX" +" XX XX" +" XXXXXXXX" +" XX XX" +" XX XX" +" XX XX" +" " +" " +" " + +" " +" " +" XXXXXXX " +" XX XX" +" XX XX" +" XX XX" +" XXXXXX " +" XX XX" +" XX XX" +" XX XX" +" XX XX" +" XXXXXXX " +" " +" " +" " + +" " +" " +" XXXXXX " +" XX XX" +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX XX" +" XXXXXX " +" " +" " +" " + +" " +" " +" XXXXXXX " +" XX XX" +" XX XX" +" XX XX" +" XX XX" +" XX XX" +" XX XX" +" XX XX" +" XX XX" +" XXXXXXX " +" " +" " +" " + +" " +" " +" XXXXXXXX" +" XX " +" XX " +" XX " +" XXXXX " +" XX " +" XX " +" XX " +" XX " +" XXXXXXXX" +" " +" " +" " + +" " +" " +" XXXXXXXX" +" XX " +" XX " +" XX " +" XXXXX " +" XX " +" XX " +" XX " +" XX " +" XX " +" " +" " +" " + +" " +" " +" XXXXXX " +" XX XX" +" XX " +" XX " +" XX " +" XX XXXX" +" XX XX" +" XX XX" +" XX XX" +" XXXXXX " +" " +" " +" " + +" " +" " +" XX XX" +" XX XX" +" XX XX" +" XX XX" +" XXXXXXXX" +" XX XX" +" XX XX" +" XX XX" +" XX XX" +" XX XX" +" " +" " +" " + +" " +" " +" XXXXXX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XXXXXX " +" " +" " +" " + +" " +" " +" XXXXX" +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX XX " +" XXXXX " +" " +" " +" " + +" " +" " +" XX XX" +" XX XX " +" XX XX " +" XX XX " +" XXXX " +" XXXX " +" XX XX " +" XX XX " +" XX XX " +" XX XX" +" " +" " +" " + +" " +" " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XXXXXXXX" +" " +" " +" " + +" " +" " +" XX XX" +" XX XX" +" XXX XXX" +" XXXXXXXX" +" XXXXXXXX" +" XX XX XX" +" XX XX XX" +" XX XX" +" XX XX" +" XX XX" +" " +" " +" " + +" " +" " +" XX XX" +" XX XX" +" XXX XX" +" XXXX XX" +" XX XX XX" +" XX XXXX" +" XX XXX" +" XX XX" +" XX XX" +" XX XX" +" " +" " +" " + +" " +" " +" XXXXXX " +" XX XX" +" XX XX" +" XX XX" +" XX XX" +" XX XX" +" XX XX" +" XX XX" +" XX XX" +" XXXXXX " +" " +" " +" " + +" " +" " +" XXXXXXX " +" XX XX" +" XX XX" +" XX XX" +" XXXXXXX " +" XX " +" XX " +" XX " +" XX " +" XX " +" " +" " +" " + +" " +" " +" XXXXXX " +" XX XX" +" XX XX" +" XX XX" +" XX XX" +" XX XX" +" XX XX" +" XX XX XX" +" XX XXXX" +" XXXXXX " +" XX" +" " +" " + +" " +" " +" XXXXXXX " +" XX XX" +" XX XX" +" XX XX" +" XXXXXXX " +" XX XX " +" XX XX " +" XX XX " +" XX XX" +" XX XX" +" " +" " +" " + +" " +" " +" XXXXXX " +" XX XX" +" XX " +" XX " +" XXXXXX " +" XX" +" XX" +" XX" +" XX XX" +" XXXXXX " +" " +" " +" " + +" " +" " +" XXXXXXXX" +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" " +" " +" " + +" " +" " +" XX XX" +" XX XX" +" XX XX" +" XX XX" +" XX XX" +" XX XX" +" XX XX" +" XX XX" +" XX XX" +" XXXXXX " +" " +" " +" " + +" " +" " +" XX XX" +" XX XX" +" XX XX" +" XX XX " +" XX XX " +" XX XX " +" XXXX " +" XXXX " +" XXXX " +" XX " +" " +" " +" " + +" " +" " +" XX XX" +" XX XX" +" XX XX" +" XX XX" +" XX XX XX" +" XX XX XX" +" XX XX XX" +" XX XX XX" +" XXXXXXXX" +" XX XX " +" " +" " +" " + +" " +" " +" XX XX" +" XX XX" +" XX XX " +" XXXX " +" XX " +" XX " +" XXXX " +" XX XX " +" XX XX" +" XX XX" +" " +" " +" " + +" " +" " +" XX XX" +" XX XX" +" XX XX " +" XXXX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" " +" " +" " + +" " +" " +" XXXXXXXX" +" XX" +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XXXXXXXX" +" " +" " +" " + +" " +" " +" XXXXX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XXXXX " +" " +" " +" " + +" " +" " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX" +" " +" " +" " + +" " +" " +" XXXXX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XXXXX " +" " +" " +" " + +" " +" " +" XX " +" XXXX " +" XX XX " +" XX XX" +" " +" " +" " +" " +" " +" " +" " +" " +" " + +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +"XXXXXXXXX" +" " +" " + +" " +" " +" XXXX " +" XXX " +" XX " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " + +" " +" " +" " +" " +" " +" XXXXXX " +" XX" +" XX" +" XXXXXXX" +" XX XX" +" XX XXX" +" XXXXXXX" +" " +" " +" " + +" " +" " +" XX " +" XX " +" XX " +" XXXXXXX " +" XXX XX" +" XX XX" +" XX XX" +" XX XX" +" XXX XX" +" XXXXXXX " +" " +" " +" " + +" " +" " +" " +" " +" " +" XXXXXX " +" XX XX" +" XX " +" XX " +" XX " +" XX XX" +" XXXXXX " +" " +" " +" " + +" " +" " +" XX" +" XX" +" XX" +" XXXXXXX" +" XX XXX" +" XX XX" +" XX XX" +" XX XX" +" XX XXX" +" XXXXXXX" +" " +" " +" " + +" " +" " +" " +" " +" " +" XXXXXX " +" XX XX" +" XX XX" +" XXXXXXXX" +" XX " +" XX " +" XXXXXX " +" " +" " +" " + +" " +" " +" XXXX " +" XX XX" +" XX XX" +" XX " +" XX " +" XXXXXX " +" XX " +" XX " +" XX " +" XX " +" " +" " +" " + +" " +" " +" " +" " +" " +" XXXXXXX" +" XX XX " +" XX XX " +" XX XX " +" XXXXX " +" XX " +" XXXXXX " +" XX XX" +" XX XX" +" XXXXXX " + +" " +" " +" XX " +" XX " +" XX " +" XXXXXXX " +" XXX XX" +" XX XX" +" XX XX" +" XX XX" +" XX XX" +" XX XX" +" " +" " +" " + +" " +" " +" " +" XX " +" " +" XXX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XXXXXX " +" " +" " +" " + +" " +" " +" " +" XX " +" " +" XXXX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX XX " +" XX XX " +" XX XX " +" XXXXX " + +" " +" " +" XX " +" XX " +" XX " +" XX XX" +" XX XXX " +" XXXXX " +" XXX " +" XXXXX " +" XX XXX " +" XX XX" +" " +" " +" " + +" " +" " +" XXX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XXXXXX " +" " +" " +" " + +" " +" " +" " +" " +" " +" XXXXXXX " +" XX XX XX" +" XX XX XX" +" XX XX XX" +" XX XX XX" +" XX XX XX" +" XX XX" +" " +" " +" " + +" " +" " +" " +" " +" " +" XXXXXXX " +" XXX XX" +" XX XX" +" XX XX" +" XX XX" +" XX XX" +" XX XX" +" " +" " +" " + +" " +" " +" " +" " +" " +" XXXXXX " +" XX XX" +" XX XX" +" XX XX" +" XX XX" +" XX XX" +" XXXXXX " +" " +" " +" " + +" " +" " +" " +" " +" " +" XXXXXXX " +" XXX XX" +" XX XX" +" XX XX" +" XX XX" +" XXX XX" +" XXXXXXX " +" XX " +" XX " +" XX " + +" " +" " +" " +" " +" " +" XXXXXXX" +" XX XXX" +" XX XX" +" XX XX" +" XX XX" +" XX XXX" +" XXXXXXX" +" XX" +" XX" +" XX" + +" " +" " +" " +" " +" " +" XX XXXX " +" XXX XX" +" XX XX" +" XX " +" XX " +" XX " +" XX " +" " +" " +" " + +" " +" " +" " +" " +" " +" XXXXXX " +" XX XX" +" XX " +" XXXXXX " +" XX" +" XX XX" +" XXXXXX " +" " +" " +" " + +" " +" " +" " +" XX " +" XX " +" XXXXXXX " +" XX " +" XX " +" XX " +" XX " +" XX XX" +" XXXX " +" " +" " +" " + +" " +" " +" " +" " +" " +" XX XX " +" XX XX " +" XX XX " +" XX XX " +" XX XX " +" XX XX " +" XXXXXXX" +" " +" " +" " + +" " +" " +" " +" " +" " +" XX XX" +" XX XX" +" XX XX " +" XX XX " +" XXXX " +" XXXX " +" XX " +" " +" " +" " + +" " +" " +" " +" " +" " +" XX XX" +" XX XX" +" XX XX XX" +" XX XX XX" +" XX XX XX" +" XXXXXXXX" +" XX XX " +" " +" " +" " + +" " +" " +" " +" " +" " +" XX XX" +" XX XX " +" XXXX " +" XX " +" XXXX " +" XX XX " +" XX XX" +" " +" " +" " + +" " +" " +" " +" " +" " +" XX XX " +" XX XX " +" XX XX " +" XX XX " +" XX XX " +" XX XXX " +" XXXXXX " +" XX " +" XX XX " +" XXXXX " + +" " +" " +" " +" " +" " +" XXXXXXXX" +" XX " +" XX " +" XX " +" XX " +" XX " +" XXXXXXXX" +" " +" " +" " + +" " +" " +" XXXX" +" XX " +" XX " +" XX " +" XXX " +" XXX " +" XX " +" XX " +" XX " +" XXXX" +" " +" " +" " + +" " +" " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" XX " +" " +" " +" " + +" " +" " +" XXXX " +" XX " +" XX " +" XX " +" XXX " +" XXX " +" XX " +" XX " +" XX " +" XXXX " +" " +" " +" " + +" " +" " +" XXX XX" +" XX XX XX" +" XX XXX " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " + +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +; + +#endif diff --git a/external/healpix/cxxsupport/geom_utils.h b/external/healpix/cxxsupport/geom_utils.h new file mode 100644 index 0000000..f18ce52 --- /dev/null +++ b/external/healpix/cxxsupport/geom_utils.h @@ -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 diff --git a/external/healpix/cxxsupport/levels_facilities.h b/external/healpix/cxxsupport/levels_facilities.h new file mode 100644 index 0000000..ecdc5ad --- /dev/null +++ b/external/healpix/cxxsupport/levels_facilities.h @@ -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 diff --git a/external/healpix/cxxsupport/ls_image.cc b/external/healpix/cxxsupport/ls_image.cc new file mode 100644 index 0000000..6d455cd --- /dev/null +++ b/external/healpix/cxxsupport/ls_image.cc @@ -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 +#include +#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 &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 &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 px(xres); + for (tsize x=0; x +#include +#include +#include +#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 cv; + std::vector 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 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 +#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 diff --git a/external/healpix/cxxsupport/paramfile.h b/external/healpix/cxxsupport/paramfile.h new file mode 100644 index 0000000..4f576d8 --- /dev/null +++ b/external/healpix/cxxsupport/paramfile.h @@ -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 +#include +#include +#include +#include "cxxutils.h" + +class paramfile + { + private: + typedef std::map params_type; + params_type params; + mutable std::set 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 T find (const std::string &key) const + { + T result; + stringToData(get_valstr(key),result); + std::string output = dataToString(result); + if (planckType()==PLANCK_STRING) output = "'"+output+"'"; + if (verbose && param_unread(key)) + std::cout << "Parser: " << key << " = " << output << std::endl; + read_params.insert(key); + return result; + } + template T find + (const std::string &key, const T &deflt) + { + if (param_present(key)) return find(key); + std::string output = dataToString(deflt); + if (planckType()==PLANCK_STRING) output = "'"+output+"'"; + if (verbose && param_unread(key)) + std::cout << "Parser: " << key << " = " << output + << " " << std::endl; + params[key]=dataToString(deflt); + read_params.insert(key); + return deflt; + } + + const params_type &getParams() const + { return params; } + }; + +#endif diff --git a/external/healpix/cxxsupport/planck.make b/external/healpix/cxxsupport/planck.make new file mode 100644 index 0000000..8e2f584 --- /dev/null +++ b/external/healpix/cxxsupport/planck.make @@ -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)) diff --git a/external/healpix/cxxsupport/planck_rng.h b/external/healpix/cxxsupport/planck_rng.h new file mode 100644 index 0000000..d916322 --- /dev/null +++ b/external/healpix/cxxsupport/planck_rng.h @@ -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 +#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 diff --git a/external/healpix/cxxsupport/pointing.h b/external/healpix/cxxsupport/pointing.h new file mode 100644 index 0000000..327b2fc --- /dev/null +++ b/external/healpix/cxxsupport/pointing.h @@ -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 +#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 diff --git a/external/healpix/cxxsupport/rotmatrix.cc b/external/healpix/cxxsupport/rotmatrix.cc new file mode 100644 index 0000000..cfe3bfa --- /dev/null +++ b/external/healpix/cxxsupport/rotmatrix.cc @@ -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 + +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; + } diff --git a/external/healpix/cxxsupport/rotmatrix.h b/external/healpix/cxxsupport/rotmatrix.h new file mode 100644 index 0000000..2b369a3 --- /dev/null +++ b/external/healpix/cxxsupport/rotmatrix.h @@ -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 +#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 diff --git a/external/healpix/cxxsupport/safe_cast.h b/external/healpix/cxxsupport/safe_cast.h new file mode 100644 index 0000000..323903e --- /dev/null +++ b/external/healpix/cxxsupport/safe_cast.h @@ -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 +#include "error_handling.h" + +template struct safe_cast_helper__ + {}; + +template struct safe_cast_helper__ + { + static T1 cast (const T2 &arg) + { + T1 res = T1(arg); + planck_assert(T2(res)==arg, "safe_cast: value changed during cast"); + return res; + } + }; + +template struct safe_cast_helper__ + { + static T1 cast (const T2 &arg) + { + T1 res = T1(arg); + planck_assert(T2(res)==arg, "safe_cast: value changed during cast"); + return res; + } + }; + +template struct safe_cast_helper__ + { + 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 struct safe_cast_helper__ + { + 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 inline T1 safe_cast(const T2 &arg) + { + return safe_cast_helper__::is_signed, + std::numeric_limits::is_signed>::cast(arg); + } + +#endif diff --git a/external/healpix/cxxsupport/trafos.cc b/external/healpix/cxxsupport/trafos.cc new file mode 100644 index 0000000..8b3569e --- /dev/null +++ b/external/healpix/cxxsupport/trafos.cc @@ -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); + } diff --git a/external/healpix/cxxsupport/trafos.h b/external/healpix/cxxsupport/trafos.h new file mode 100644 index 0000000..67c44db --- /dev/null +++ b/external/healpix/cxxsupport/trafos.h @@ -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 diff --git a/external/healpix/cxxsupport/vec3.h b/external/healpix/cxxsupport/vec3.h new file mode 100644 index 0000000..d01a13f --- /dev/null +++ b/external/healpix/cxxsupport/vec3.h @@ -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 +#include +#include "datatypes.h" + +/*! \defgroup vec3group 3D vectors */ +/*! \{ */ + +/*! Class representing a 3D cartesian vector. */ +templateclass 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 explicit vec3_t (const vec3_t &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 inline T dotprod(const vec3_t &v1, const vec3_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 inline vec3_t crossprod + (const vec3_t &a, const vec3_t &b) + { return vec3_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 inline std::ostream &operator<< + (std::ostream &os, const vec3_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 vec3; +/*! Specialisation of vec3_t for 32-bit floating point components */ +typedef vec3_t vec3f; + +/*! \} */ + +#endif diff --git a/external/healpix/cxxsupport/wigner.cc b/external/healpix/cxxsupport/wigner.cc new file mode 100644 index 0000000..0c507a6 --- /dev/null +++ b/external/healpix/cxxsupport/wigner.cc @@ -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 &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=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 &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 &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 &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 &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(m)); + for (tsize lm=0; lmpi) 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=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 &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 (;leps) 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 (;llmax) 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 &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 +#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 sqt; + arr2 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 &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 sqt; + arr2 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 &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 sqt; + arr2 d,dd; + int n; + + public: + wigner_d_halfpi_risbo_openmp(int lmax); + + const arr2 &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 sqt; + arr2 d, dd; + int n; + + public: + wigner_d_risbo_openmp(int lmax, double ang); + + const arr2 &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 logsum, lc05, ls05; + arr flm1, flm2, cf, costh, xl; + arr thetaflip; + + // members depending on m and m' + int m1, m2, am1, am2, mlo, mhi, cosPow, sinPow; + long double prefactor; + arr fx; + bool preMinus; + + // members depending on theta + arr result; +#ifdef PLANCK_HAVE_SSE2 + arr_align 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 &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 &calc (int nth, int &firstl); + +#ifdef PLANCK_HAVE_SSE2 + const arr_align &calc (int nth1, int nth2, int &firstl); +#endif + }; + +#endif diff --git a/external/healpix/cxxsupport/xcomplex.h b/external/healpix/cxxsupport/xcomplex.h new file mode 100644 index 0000000..14b3fe4 --- /dev/null +++ b/external/healpix/cxxsupport/xcomplex.h @@ -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 +#include + +/*! \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 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 &orig) + : re(orig.real()), im(orig.imag()) {} + /*! Creates a complex number as a copy of \a orig. */ + template explicit xcomplex (const xcomplex &orig) + : re(T(orig.re)), im(T(orig.im)) {} + + /*! Conversion operator to std::complex */ + operator std::complex () const + { return std::complex(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 &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 tmp=*this; + std::complex 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(*this)/std::complex(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 inline xcomplex conj (const xcomplex &num) + { return xcomplex (num.re, -num.im); } +/*! Returns the norm of \a num. + \relates xcomplex */ +template inline T norm (const xcomplex &num) + { return num.re*num.re + num.im*num.im; } +/*! Returns the absolute value of \a num. + \relates xcomplex */ +template inline T abs (const xcomplex &num) + { + using namespace std; + return abs(complex(num)); + } +/*! Returns \a f1*f2. + \relates xcomplex */ +template inline xcomplex operator* + (const T &f1, const xcomplex &f2) + { return xcomplex (f1*f2.re, f1*f2.im); } +/*! Returns \a f1/f2. + \relates xcomplex */ +template inline xcomplex operator/ + (const T &f1, const xcomplex &f2) + { return xcomplex(f1)/f2; } +/*! Writes \a val to \a os. + \relates xcomplex */ +template + inline std::ostream &operator<< (std::ostream &os, const xcomplex &val) + { os << "(" << val.re << "," << val.im << ")"; return os; } + +/*! \} */ + +#endif diff --git a/external/healpix/docsrc/Healpix_cxx.dox b/external/healpix/docsrc/Healpix_cxx.dox new file mode 100644 index 0000000..30a1a00 --- /dev/null +++ b/external/healpix/docsrc/Healpix_cxx.dox @@ -0,0 +1,272 @@ +# Doxyfile 1.7.0 + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +DOXYFILE_ENCODING = UTF-8 +PROJECT_NAME = "Healpix C++" +PROJECT_NUMBER = 0.1 +OUTPUT_DIRECTORY = . +CREATE_SUBDIRS = NO +OUTPUT_LANGUAGE = English +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = NO +STRIP_FROM_PATH = +STRIP_FROM_INC_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = NO +QT_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +INHERIT_DOCS = YES +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 8 +ALIASES = +OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_JAVA = NO +OPTIMIZE_FOR_FORTRAN = NO +OPTIMIZE_OUTPUT_VHDL = NO +EXTENSION_MAPPING = +BUILTIN_STL_SUPPORT = NO +CPP_CLI_SUPPORT = NO +SIP_SUPPORT = NO +IDL_PROPERTY_SUPPORT = YES +DISTRIBUTE_GROUP_DOC = NO +SUBGROUPING = YES +TYPEDEF_HIDES_STRUCT = NO +SYMBOL_CACHE_SIZE = 0 +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = YES +EXTRACT_LOCAL_CLASSES = NO +EXTRACT_LOCAL_METHODS = NO +EXTRACT_ANON_NSPACES = NO +HIDE_UNDOC_MEMBERS = YES +HIDE_UNDOC_CLASSES = YES +HIDE_FRIEND_COMPOUNDS = YES +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = YES +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +FORCE_LOCAL_INCLUDES = NO +INLINE_INFO = YES +SORT_MEMBER_DOCS = NO +SORT_BRIEF_DOCS = NO +SORT_MEMBERS_CTORS_1ST = NO +SORT_GROUP_NAMES = NO +SORT_BY_SCOPE_NAME = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +SHOW_DIRECTORIES = YES +SHOW_FILES = YES +SHOW_NAMESPACES = YES +FILE_VERSION_FILTER = +LAYOUT_FILE = +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = YES +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = NO +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = ../Healpix_cxx +INPUT_ENCODING = UTF-8 +FILE_PATTERNS = *.h \ + *.cc \ + *.dox +RECURSIVE = YES +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXCLUDE_SYMBOLS = +EXAMPLE_PATH = ../Healpix_cxx/ +EXAMPLE_PATTERNS = +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = YES +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = NO +REFERENCED_BY_RELATION = NO +REFERENCES_RELATION = NO +REFERENCES_LINK_SOURCE = YES +USE_HTAGS = NO +VERBATIM_HEADERS = YES +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = YES +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = htmldoc +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = footer.html +HTML_STYLESHEET = +HTML_COLORSTYLE_HUE = 220 +HTML_COLORSTYLE_SAT = 100 +HTML_COLORSTYLE_GAMMA = 80 +HTML_TIMESTAMP = YES +HTML_ALIGN_MEMBERS = YES +HTML_DYNAMIC_SECTIONS = NO +GENERATE_DOCSET = NO +DOCSET_FEEDNAME = "Doxygen generated docs" +DOCSET_BUNDLE_ID = org.doxygen.Project +DOCSET_PUBLISHER_ID = org.doxygen.Publisher +DOCSET_PUBLISHER_NAME = Publisher +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +CHM_INDEX_ENCODING = +BINARY_TOC = NO +TOC_EXPAND = NO +GENERATE_QHP = NO +QCH_FILE = +QHP_NAMESPACE = org.doxygen.Project +QHP_VIRTUAL_FOLDER = doc +QHP_CUST_FILTER_NAME = +QHP_CUST_FILTER_ATTRS = +QHP_SECT_FILTER_ATTRS = +QHG_LOCATION = +GENERATE_ECLIPSEHELP = NO +ECLIPSE_DOC_ID = org.doxygen.Project +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = NO +USE_INLINE_TREES = NO +TREEVIEW_WIDTH = 250 +EXT_LINKS_IN_WINDOW = NO +FORMULA_FONTSIZE = 10 +SEARCHENGINE = NO +SERVER_BASED_SEARCH = NO +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = YES +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = YES +USE_PDFLATEX = YES +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +LATEX_SOURCE_CODE = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = NO +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +XML_PROGRAMLISTING = YES +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- +TAGFILES = libfftpack.tag=../libfftpack \ + cxxsupport.tag=../cxxsupport +GENERATE_TAGFILE = Healpix_cxx.tag +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = YES +MSCGEN_PATH = +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = NO +DOT_NUM_THREADS = 0 +DOT_FONTNAME = FreeSans +DOT_FONTSIZE = 10 +DOT_FONTPATH = +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = NO +TEMPLATE_RELATIONS = YES +INCLUDE_GRAPH = NO +INCLUDED_BY_GRAPH = NO +CALL_GRAPH = NO +CALLER_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = YES +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +DOT_GRAPH_MAX_NODES = 50 +MAX_DOT_GRAPH_DEPTH = 0 +DOT_TRANSPARENT = NO +DOT_MULTI_TARGETS = NO +GENERATE_LEGEND = YES +DOT_CLEANUP = YES diff --git a/external/healpix/docsrc/c_utils.dox b/external/healpix/docsrc/c_utils.dox new file mode 100644 index 0000000..48201c0 --- /dev/null +++ b/external/healpix/docsrc/c_utils.dox @@ -0,0 +1,271 @@ +# Doxyfile 1.7.0 + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +DOXYFILE_ENCODING = UTF-8 +PROJECT_NAME = "LevelS C support library" +PROJECT_NUMBER = 0.1 +OUTPUT_DIRECTORY = . +CREATE_SUBDIRS = NO +OUTPUT_LANGUAGE = English +BRIEF_MEMBER_DESC = NO +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = NO +STRIP_FROM_PATH = +STRIP_FROM_INC_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = NO +QT_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +INHERIT_DOCS = YES +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 8 +ALIASES = +OPTIMIZE_OUTPUT_FOR_C = YES +OPTIMIZE_OUTPUT_JAVA = NO +OPTIMIZE_FOR_FORTRAN = NO +OPTIMIZE_OUTPUT_VHDL = NO +EXTENSION_MAPPING = +BUILTIN_STL_SUPPORT = NO +CPP_CLI_SUPPORT = NO +SIP_SUPPORT = NO +IDL_PROPERTY_SUPPORT = YES +DISTRIBUTE_GROUP_DOC = NO +SUBGROUPING = YES +TYPEDEF_HIDES_STRUCT = NO +SYMBOL_CACHE_SIZE = 0 +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_METHODS = NO +EXTRACT_ANON_NSPACES = NO +HIDE_UNDOC_MEMBERS = YES +HIDE_UNDOC_CLASSES = YES +HIDE_FRIEND_COMPOUNDS = YES +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = YES +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +FORCE_LOCAL_INCLUDES = NO +INLINE_INFO = YES +SORT_MEMBER_DOCS = NO +SORT_BRIEF_DOCS = NO +SORT_MEMBERS_CTORS_1ST = NO +SORT_GROUP_NAMES = NO +SORT_BY_SCOPE_NAME = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +SHOW_DIRECTORIES = YES +SHOW_FILES = YES +SHOW_NAMESPACES = YES +FILE_VERSION_FILTER = +LAYOUT_FILE = +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = YES +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = NO +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = ../c_utils +INPUT_ENCODING = UTF-8 +FILE_PATTERNS = *.h \ + *.c \ + *.dox +RECURSIVE = YES +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXCLUDE_SYMBOLS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = YES +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = NO +REFERENCED_BY_RELATION = NO +REFERENCES_RELATION = NO +REFERENCES_LINK_SOURCE = YES +USE_HTAGS = NO +VERBATIM_HEADERS = YES +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = YES +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = htmldoc +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = footer.html +HTML_STYLESHEET = +HTML_COLORSTYLE_HUE = 220 +HTML_COLORSTYLE_SAT = 100 +HTML_COLORSTYLE_GAMMA = 80 +HTML_TIMESTAMP = YES +HTML_ALIGN_MEMBERS = YES +HTML_DYNAMIC_SECTIONS = NO +GENERATE_DOCSET = NO +DOCSET_FEEDNAME = "Doxygen generated docs" +DOCSET_BUNDLE_ID = org.doxygen.Project +DOCSET_PUBLISHER_ID = org.doxygen.Publisher +DOCSET_PUBLISHER_NAME = Publisher +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +CHM_INDEX_ENCODING = +BINARY_TOC = NO +TOC_EXPAND = NO +GENERATE_QHP = NO +QCH_FILE = +QHP_NAMESPACE = org.doxygen.Project +QHP_VIRTUAL_FOLDER = doc +QHP_CUST_FILTER_NAME = +QHP_CUST_FILTER_ATTRS = +QHP_SECT_FILTER_ATTRS = +QHG_LOCATION = +GENERATE_ECLIPSEHELP = NO +ECLIPSE_DOC_ID = org.doxygen.Project +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = NO +USE_INLINE_TREES = NO +TREEVIEW_WIDTH = 250 +EXT_LINKS_IN_WINDOW = NO +FORMULA_FONTSIZE = 10 +SEARCHENGINE = NO +SERVER_BASED_SEARCH = NO +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = YES +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = YES +USE_PDFLATEX = YES +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +LATEX_SOURCE_CODE = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = NO +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +XML_PROGRAMLISTING = YES +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = c_utils.tag +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = YES +MSCGEN_PATH = +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = NO +DOT_NUM_THREADS = 0 +DOT_FONTNAME = FreeSans +DOT_FONTSIZE = 10 +DOT_FONTPATH = +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = NO +TEMPLATE_RELATIONS = YES +INCLUDE_GRAPH = NO +INCLUDED_BY_GRAPH = NO +CALL_GRAPH = NO +CALLER_GRAPH = NO +GRAPHICAL_HIERARCHY = NO +DIRECTORY_GRAPH = YES +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +DOT_GRAPH_MAX_NODES = 50 +MAX_DOT_GRAPH_DEPTH = 0 +DOT_TRANSPARENT = NO +DOT_MULTI_TARGETS = NO +GENERATE_LEGEND = YES +DOT_CLEANUP = YES diff --git a/external/healpix/docsrc/cxxsupport.dox b/external/healpix/docsrc/cxxsupport.dox new file mode 100644 index 0000000..9683565 --- /dev/null +++ b/external/healpix/docsrc/cxxsupport.dox @@ -0,0 +1,271 @@ +# Doxyfile 1.7.0 + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +DOXYFILE_ENCODING = UTF-8 +PROJECT_NAME = "LevelS C++ support library" +PROJECT_NUMBER = 0.1 +OUTPUT_DIRECTORY = . +CREATE_SUBDIRS = NO +OUTPUT_LANGUAGE = English +BRIEF_MEMBER_DESC = NO +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = NO +STRIP_FROM_PATH = +STRIP_FROM_INC_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = NO +QT_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +INHERIT_DOCS = YES +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 8 +ALIASES = +OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_JAVA = NO +OPTIMIZE_FOR_FORTRAN = NO +OPTIMIZE_OUTPUT_VHDL = NO +EXTENSION_MAPPING = +BUILTIN_STL_SUPPORT = NO +CPP_CLI_SUPPORT = NO +SIP_SUPPORT = NO +IDL_PROPERTY_SUPPORT = YES +DISTRIBUTE_GROUP_DOC = NO +SUBGROUPING = YES +TYPEDEF_HIDES_STRUCT = NO +SYMBOL_CACHE_SIZE = 0 +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_METHODS = NO +EXTRACT_ANON_NSPACES = NO +HIDE_UNDOC_MEMBERS = YES +HIDE_UNDOC_CLASSES = YES +HIDE_FRIEND_COMPOUNDS = YES +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = YES +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +FORCE_LOCAL_INCLUDES = NO +INLINE_INFO = YES +SORT_MEMBER_DOCS = NO +SORT_BRIEF_DOCS = NO +SORT_MEMBERS_CTORS_1ST = NO +SORT_GROUP_NAMES = NO +SORT_BY_SCOPE_NAME = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +SHOW_DIRECTORIES = YES +SHOW_FILES = YES +SHOW_NAMESPACES = YES +FILE_VERSION_FILTER = +LAYOUT_FILE = +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = YES +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = NO +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = ../cxxsupport +INPUT_ENCODING = UTF-8 +FILE_PATTERNS = *.h \ + *.cc \ + *.dox +RECURSIVE = YES +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXCLUDE_SYMBOLS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = YES +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = NO +REFERENCED_BY_RELATION = NO +REFERENCES_RELATION = NO +REFERENCES_LINK_SOURCE = YES +USE_HTAGS = NO +VERBATIM_HEADERS = YES +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = YES +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = htmldoc +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = footer.html +HTML_STYLESHEET = +HTML_COLORSTYLE_HUE = 220 +HTML_COLORSTYLE_SAT = 100 +HTML_COLORSTYLE_GAMMA = 80 +HTML_TIMESTAMP = YES +HTML_ALIGN_MEMBERS = YES +HTML_DYNAMIC_SECTIONS = NO +GENERATE_DOCSET = NO +DOCSET_FEEDNAME = "Doxygen generated docs" +DOCSET_BUNDLE_ID = org.doxygen.Project +DOCSET_PUBLISHER_ID = org.doxygen.Publisher +DOCSET_PUBLISHER_NAME = Publisher +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +CHM_INDEX_ENCODING = +BINARY_TOC = NO +TOC_EXPAND = NO +GENERATE_QHP = NO +QCH_FILE = +QHP_NAMESPACE = org.doxygen.Project +QHP_VIRTUAL_FOLDER = doc +QHP_CUST_FILTER_NAME = +QHP_CUST_FILTER_ATTRS = +QHP_SECT_FILTER_ATTRS = +QHG_LOCATION = +GENERATE_ECLIPSEHELP = NO +ECLIPSE_DOC_ID = org.doxygen.Project +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = NO +USE_INLINE_TREES = NO +TREEVIEW_WIDTH = 250 +EXT_LINKS_IN_WINDOW = NO +FORMULA_FONTSIZE = 10 +SEARCHENGINE = NO +SERVER_BASED_SEARCH = NO +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = YES +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = YES +USE_PDFLATEX = YES +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +LATEX_SOURCE_CODE = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = NO +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +XML_PROGRAMLISTING = YES +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- +TAGFILES = c_utils.tag=../c_utils libfftpack.tag=../libfftpack +GENERATE_TAGFILE = cxxsupport.tag +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = YES +MSCGEN_PATH = +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = NO +DOT_NUM_THREADS = 0 +DOT_FONTNAME = FreeSans +DOT_FONTSIZE = 10 +DOT_FONTPATH = +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = NO +TEMPLATE_RELATIONS = YES +INCLUDE_GRAPH = NO +INCLUDED_BY_GRAPH = NO +CALL_GRAPH = NO +CALLER_GRAPH = NO +GRAPHICAL_HIERARCHY = NO +DIRECTORY_GRAPH = YES +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +DOT_GRAPH_MAX_NODES = 50 +MAX_DOT_GRAPH_DEPTH = 0 +DOT_TRANSPARENT = NO +DOT_MULTI_TARGETS = NO +GENERATE_LEGEND = YES +DOT_CLEANUP = YES diff --git a/external/healpix/docsrc/footer.html b/external/healpix/docsrc/footer.html new file mode 100644 index 0000000..6f5dbf0 --- /dev/null +++ b/external/healpix/docsrc/footer.html @@ -0,0 +1,5 @@ +
    +Generated on $datetime for $projectname +
    + + diff --git a/external/healpix/docsrc/header.html b/external/healpix/docsrc/header.html new file mode 100644 index 0000000..acb2638 --- /dev/null +++ b/external/healpix/docsrc/header.html @@ -0,0 +1,5 @@ + + +$title + + diff --git a/external/healpix/docsrc/index_code.html b/external/healpix/docsrc/index_code.html new file mode 100644 index 0000000..c6cf0b0 --- /dev/null +++ b/external/healpix/docsrc/index_code.html @@ -0,0 +1,22 @@ + + +HEALPix C++ source code documentation + +

    HEALPix C++ source code documentation

    + +

    C interfaces

    + + + +

    C++ interfaces

    + + + + diff --git a/external/healpix/docsrc/libfftpack.dox b/external/healpix/docsrc/libfftpack.dox new file mode 100644 index 0000000..9dc927d --- /dev/null +++ b/external/healpix/docsrc/libfftpack.dox @@ -0,0 +1,271 @@ +# Doxyfile 1.7.0 + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +DOXYFILE_ENCODING = UTF-8 +PROJECT_NAME = "LevelS FFT library" +PROJECT_NUMBER = 0.1 +OUTPUT_DIRECTORY = . +CREATE_SUBDIRS = NO +OUTPUT_LANGUAGE = English +BRIEF_MEMBER_DESC = NO +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = NO +STRIP_FROM_PATH = +STRIP_FROM_INC_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = NO +QT_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +INHERIT_DOCS = YES +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 8 +ALIASES = +OPTIMIZE_OUTPUT_FOR_C = YES +OPTIMIZE_OUTPUT_JAVA = NO +OPTIMIZE_FOR_FORTRAN = NO +OPTIMIZE_OUTPUT_VHDL = NO +EXTENSION_MAPPING = +BUILTIN_STL_SUPPORT = NO +CPP_CLI_SUPPORT = NO +SIP_SUPPORT = NO +IDL_PROPERTY_SUPPORT = YES +DISTRIBUTE_GROUP_DOC = NO +SUBGROUPING = YES +TYPEDEF_HIDES_STRUCT = NO +SYMBOL_CACHE_SIZE = 0 +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_METHODS = NO +EXTRACT_ANON_NSPACES = NO +HIDE_UNDOC_MEMBERS = YES +HIDE_UNDOC_CLASSES = YES +HIDE_FRIEND_COMPOUNDS = YES +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = YES +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +FORCE_LOCAL_INCLUDES = NO +INLINE_INFO = YES +SORT_MEMBER_DOCS = NO +SORT_BRIEF_DOCS = NO +SORT_MEMBERS_CTORS_1ST = NO +SORT_GROUP_NAMES = NO +SORT_BY_SCOPE_NAME = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +SHOW_DIRECTORIES = YES +SHOW_FILES = YES +SHOW_NAMESPACES = YES +FILE_VERSION_FILTER = +LAYOUT_FILE = +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = YES +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = NO +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = ../libfftpack +INPUT_ENCODING = UTF-8 +FILE_PATTERNS = *.h \ + *.c \ + *.dox +RECURSIVE = YES +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXCLUDE_SYMBOLS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = YES +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = NO +REFERENCED_BY_RELATION = NO +REFERENCES_RELATION = NO +REFERENCES_LINK_SOURCE = YES +USE_HTAGS = NO +VERBATIM_HEADERS = YES +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = YES +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = htmldoc +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = footer.html +HTML_STYLESHEET = +HTML_COLORSTYLE_HUE = 220 +HTML_COLORSTYLE_SAT = 100 +HTML_COLORSTYLE_GAMMA = 80 +HTML_TIMESTAMP = YES +HTML_ALIGN_MEMBERS = YES +HTML_DYNAMIC_SECTIONS = NO +GENERATE_DOCSET = NO +DOCSET_FEEDNAME = "Doxygen generated docs" +DOCSET_BUNDLE_ID = org.doxygen.Project +DOCSET_PUBLISHER_ID = org.doxygen.Publisher +DOCSET_PUBLISHER_NAME = Publisher +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +CHM_INDEX_ENCODING = +BINARY_TOC = NO +TOC_EXPAND = NO +GENERATE_QHP = NO +QCH_FILE = +QHP_NAMESPACE = org.doxygen.Project +QHP_VIRTUAL_FOLDER = doc +QHP_CUST_FILTER_NAME = +QHP_CUST_FILTER_ATTRS = +QHP_SECT_FILTER_ATTRS = +QHG_LOCATION = +GENERATE_ECLIPSEHELP = NO +ECLIPSE_DOC_ID = org.doxygen.Project +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = NO +USE_INLINE_TREES = NO +TREEVIEW_WIDTH = 250 +EXT_LINKS_IN_WINDOW = NO +FORMULA_FONTSIZE = 10 +SEARCHENGINE = NO +SERVER_BASED_SEARCH = NO +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = YES +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = YES +USE_PDFLATEX = YES +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +LATEX_SOURCE_CODE = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = NO +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +XML_PROGRAMLISTING = YES +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- +TAGFILES = c_utils.tag=../c_utils +GENERATE_TAGFILE = libfftpack.tag +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = YES +MSCGEN_PATH = +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = NO +DOT_NUM_THREADS = 0 +DOT_FONTNAME = FreeSans +DOT_FONTSIZE = 10 +DOT_FONTPATH = +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = NO +TEMPLATE_RELATIONS = YES +INCLUDE_GRAPH = NO +INCLUDED_BY_GRAPH = NO +CALL_GRAPH = NO +CALLER_GRAPH = NO +GRAPHICAL_HIERARCHY = NO +DIRECTORY_GRAPH = YES +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +DOT_GRAPH_MAX_NODES = 50 +MAX_DOT_GRAPH_DEPTH = 0 +DOT_TRANSPARENT = NO +DOT_MULTI_TARGETS = NO +GENERATE_LEGEND = YES +DOT_CLEANUP = YES diff --git a/external/healpix/docsrc/libpsht.dox b/external/healpix/docsrc/libpsht.dox new file mode 100644 index 0000000..27652e2 --- /dev/null +++ b/external/healpix/docsrc/libpsht.dox @@ -0,0 +1,272 @@ +# Doxyfile 1.7.0 + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +DOXYFILE_ENCODING = UTF-8 +PROJECT_NAME = "LevelS SHT library" +PROJECT_NUMBER = 0.1 +OUTPUT_DIRECTORY = . +CREATE_SUBDIRS = NO +OUTPUT_LANGUAGE = English +BRIEF_MEMBER_DESC = NO +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = NO +STRIP_FROM_PATH = +STRIP_FROM_INC_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = NO +QT_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +INHERIT_DOCS = YES +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 8 +ALIASES = +OPTIMIZE_OUTPUT_FOR_C = YES +OPTIMIZE_OUTPUT_JAVA = NO +OPTIMIZE_FOR_FORTRAN = NO +OPTIMIZE_OUTPUT_VHDL = NO +EXTENSION_MAPPING = +BUILTIN_STL_SUPPORT = NO +CPP_CLI_SUPPORT = NO +SIP_SUPPORT = NO +IDL_PROPERTY_SUPPORT = YES +DISTRIBUTE_GROUP_DOC = NO +SUBGROUPING = YES +TYPEDEF_HIDES_STRUCT = NO +SYMBOL_CACHE_SIZE = 0 +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_METHODS = NO +EXTRACT_ANON_NSPACES = NO +HIDE_UNDOC_MEMBERS = YES +HIDE_UNDOC_CLASSES = YES +HIDE_FRIEND_COMPOUNDS = YES +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = YES +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +FORCE_LOCAL_INCLUDES = NO +INLINE_INFO = YES +SORT_MEMBER_DOCS = NO +SORT_BRIEF_DOCS = NO +SORT_MEMBERS_CTORS_1ST = NO +SORT_GROUP_NAMES = NO +SORT_BY_SCOPE_NAME = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +SHOW_DIRECTORIES = YES +SHOW_FILES = YES +SHOW_NAMESPACES = YES +FILE_VERSION_FILTER = +LAYOUT_FILE = +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = YES +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = NO +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = ../libpsht +INPUT_ENCODING = UTF-8 +FILE_PATTERNS = *.h \ + psht_test.c \ + psht_perftest.c \ + *.dox +RECURSIVE = YES +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXCLUDE_SYMBOLS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = YES +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = NO +REFERENCED_BY_RELATION = NO +REFERENCES_RELATION = NO +REFERENCES_LINK_SOURCE = YES +USE_HTAGS = NO +VERBATIM_HEADERS = YES +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = YES +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = htmldoc +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = footer.html +HTML_STYLESHEET = +HTML_COLORSTYLE_HUE = 220 +HTML_COLORSTYLE_SAT = 100 +HTML_COLORSTYLE_GAMMA = 80 +HTML_TIMESTAMP = YES +HTML_ALIGN_MEMBERS = YES +HTML_DYNAMIC_SECTIONS = NO +GENERATE_DOCSET = NO +DOCSET_FEEDNAME = "Doxygen generated docs" +DOCSET_BUNDLE_ID = org.doxygen.Project +DOCSET_PUBLISHER_ID = org.doxygen.Publisher +DOCSET_PUBLISHER_NAME = Publisher +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +CHM_INDEX_ENCODING = +BINARY_TOC = NO +TOC_EXPAND = NO +GENERATE_QHP = NO +QCH_FILE = +QHP_NAMESPACE = org.doxygen.Project +QHP_VIRTUAL_FOLDER = doc +QHP_CUST_FILTER_NAME = +QHP_CUST_FILTER_ATTRS = +QHP_SECT_FILTER_ATTRS = +QHG_LOCATION = +GENERATE_ECLIPSEHELP = NO +ECLIPSE_DOC_ID = org.doxygen.Project +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = NO +USE_INLINE_TREES = NO +TREEVIEW_WIDTH = 250 +EXT_LINKS_IN_WINDOW = NO +FORMULA_FONTSIZE = 10 +SEARCHENGINE = NO +SERVER_BASED_SEARCH = NO +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = YES +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = YES +USE_PDFLATEX = YES +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +LATEX_SOURCE_CODE = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = NO +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +XML_PROGRAMLISTING = YES +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- +TAGFILES = libfftpack.tag=../libfftpack c_utils.tag=../c_utils +GENERATE_TAGFILE = libpsht.tag +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = YES +MSCGEN_PATH = +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = NO +DOT_NUM_THREADS = 0 +DOT_FONTNAME = FreeSans +DOT_FONTSIZE = 10 +DOT_FONTPATH = +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = NO +TEMPLATE_RELATIONS = YES +INCLUDE_GRAPH = NO +INCLUDED_BY_GRAPH = NO +CALL_GRAPH = NO +CALLER_GRAPH = NO +GRAPHICAL_HIERARCHY = NO +DIRECTORY_GRAPH = YES +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +DOT_GRAPH_MAX_NODES = 50 +MAX_DOT_GRAPH_DEPTH = 0 +DOT_TRANSPARENT = NO +DOT_MULTI_TARGETS = NO +GENERATE_LEGEND = YES +DOT_CLEANUP = YES diff --git a/external/healpix/docsrc/planck.make b/external/healpix/docsrc/planck.make new file mode 100644 index 0000000..c1bc8ec --- /dev/null +++ b/external/healpix/docsrc/planck.make @@ -0,0 +1,18 @@ +PKG:=docsrc + +docsrc_idx: | $(DOCDIR)_mkdir + cp $(SRCROOT)/docsrc/index_code.html $(DOCDIR)/index.html + +docsrc_code_doc: docsrc_idx + cd $(SRCROOT)/docsrc; \ + for i in c_utils libfftpack libpsht cxxsupport Healpix_cxx; do \ + doxygen $${i}.dox; \ + mv htmldoc $(DOCDIR)/$${i}; \ + done; \ + rm *.tag; \ + +docsrc_clean: + cd $(SRCROOT)/docsrc; \ + rm -rf htmldoc + +doc: docsrc_code_doc diff --git a/external/healpix/docsrc/sheet.css b/external/healpix/docsrc/sheet.css new file mode 100644 index 0000000..1d4d631 --- /dev/null +++ b/external/healpix/docsrc/sheet.css @@ -0,0 +1,271 @@ +BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV { + font-family: Geneva, Arial, Helvetica, sans-serif; +} +H1 { + text-align: center; +} +CAPTION { font-weight: bold } +DIV.qindex { + width: 100%; + background-color: #eeeeff; + border: 1px solid #b0b0b0; + text-align: center; + margin: 2px; + padding: 2px; + line-height: 140%; +} +DIV.nav { + width: 100%; + background-color: #eeeeff; + border: 1px solid #b0b0b0; + text-align: center; + margin: 2px; + padding: 2px; + line-height: 140%; +} +A.qindex { + text-decoration: none; + font-weight: bold; + color: #1A419D; +} +A.qindex:visited { + text-decoration: none; + font-weight: bold; + color: #1A419D +} +A.qindex:hover { + text-decoration: none; + background-color: #ddddff; +} +A.qindexHL { + text-decoration: none; + font-weight: bold; + background-color: #6666cc; + color: #ffffff; + border: 1px double #9295C2; +} +A.qindexHL:hover { + text-decoration: none; + background-color: #6666cc; + color: #ffffff; +} +A.qindexHL:visited { text-decoration: none; background-color: #6666cc; color: #ffffff } +A.el { text-decoration: none; font-weight: bold } +A.elRef { font-weight: bold } +A.code:link { text-decoration: none; font-weight: normal; color: #0000FF} +A.code:visited { text-decoration: none; font-weight: normal; color: #0000FF} +A.codeRef:link { font-weight: normal; color: #0000FF} +A.codeRef:visited { font-weight: normal; color: #0000FF} +A:hover { text-decoration: none; background-color: #f2f2ff } +DL.el { margin-left: -1cm } +.fragment { + font-family: monospace +} +PRE.fragment { + border: 1px solid #CCCCCC; + background-color: #f5f5f5; + margin-top: 4px; + margin-bottom: 4px; + margin-left: 2px; + margin-right: 8px; + padding-left: 6px; + padding-right: 6px; + padding-top: 4px; + padding-bottom: 4px; +} +DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px } +TD.md { background-color: #F4F4FB; font-weight: bold; } +TD.mdname1 { background-color: #F4F4FB; font-weight: bold; color: #602020; } +TD.mdname { background-color: #F4F4FB; font-weight: bold; color: #602020; width: 600px; } +DIV.groupHeader { + margin-left: 16px; + margin-top: 12px; + margin-bottom: 6px; + font-weight: bold; +} +DIV.groupText { margin-left: 16px; font-style: italic; font-size: 14px } +BODY { + background: white; + color: black; + margin-right: 20px; + margin-left: 20px; +} +TD.indexkey { + background-color: #eeeeff; + font-weight: bold; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px; + border: 1px solid #CCCCCC; +} +TD.indexvalue { + background-color: #eeeeff; + font-style: italic; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px; + border: 1px solid #CCCCCC; +} +TR.memlist { + background-color: #f0f0f0; +} +P.formulaDsp { text-align: center; } +IMG.formulaDsp { } +IMG.formulaInl { vertical-align: middle; } +SPAN.keyword { color: #008000 } +SPAN.keywordtype { color: #604020 } +SPAN.keywordflow { color: #e08000 } +SPAN.comment { color: #800000 } +SPAN.preprocessor { color: #806020 } +SPAN.stringliteral { color: #002080 } +SPAN.charliteral { color: #008080 } +.mdTable { + border: 1px solid #868686; + background-color: #F4F4FB; +} +.mdRow { + padding: 8px 10px; +} +.mdescLeft { + padding: 0px 8px 4px 8px; + font-size: 12px; + font-style: italic; + background-color: #FAFAFA; + border-top: 1px none #E0E0E0; + border-right: 1px none #E0E0E0; + border-bottom: 1px none #E0E0E0; + border-left: 1px none #E0E0E0; + margin: 0px; +} +.mdescRight { + padding: 0px 8px 4px 8px; + font-size: 12px; + font-style: italic; + background-color: #FAFAFA; + border-top: 1px none #E0E0E0; + border-right: 1px none #E0E0E0; + border-bottom: 1px none #E0E0E0; + border-left: 1px none #E0E0E0; + margin: 0px; +} +.memItemLeft { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 12px; +} +.memItemRight { + padding: 1px 8px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 13px; +} +.memTemplItemLeft { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: none; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 12px; +} +.memTemplItemRight { + padding: 1px 8px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: none; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 13px; +} +.memTemplParams { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + color: #606060; + background-color: #FAFAFA; + font-size: 12px; +} +.search { color: #003399; + font-weight: bold; +} +FORM.search { + margin-bottom: 0px; + margin-top: 0px; +} +INPUT.search { font-size: 75%; + color: #000080; + font-weight: normal; + background-color: #eeeeff; +} +TD.tiny { font-size: 75%; +} +a { + color: #252E78; +} +a:visited { + color: #3D2185; +} diff --git a/external/healpix/libcfitsio/planck.make b/external/healpix/libcfitsio/planck.make new file mode 100644 index 0000000..492d3b3 --- /dev/null +++ b/external/healpix/libcfitsio/planck.make @@ -0,0 +1,32 @@ +PKG:=libcfitsio + +ifeq ($(EXTERNAL_CFITSIO),yes) + +LIB_$(PKG):=$(CFITSIO_EXT_LIB) +FULL_INCLUDE+= -I$(CFITSIO_EXT_INC) + +else + +PACKAGE:=$(SRCROOT)/libcfitsio/cfitsio3260.tar.gz + +SD:=$(SRCROOT)/$(PKG) +OD:=$(BLDROOT)/$(PKG) + +FULL_INCLUDE+= -I$(BLDROOT)/libcfitsio/cfitsio + +HDR_$(PKG):=fitsio.h longnam.h +HDR_$(PKG):=$(HDR_$(PKG):%=$(BLDROOT)/libcfitsio/cfitsio/%) +LIB_$(PKG):=$(LIBDIR)/libcfitsio.a + +$(LIB_$(PKG)): $(SD)/* | $(OD)_mkdir $(LIBDIR)_mkdir + cd $(BLDROOT)/libcfitsio/ && \ + rm -rf cfitsio && \ + gunzip -c $(PACKAGE) | tar xvf - && \ + cd cfitsio && \ + MAKE="$(MAKE)" FC="$(FC)" CC="$(CC)" CFLAGS="$(CCFLAGS_NO_C)" ./configure && \ + $(MAKE) && \ + cp -p libcfitsio.a $(LIBDIR) + +$(HDR_$(PKG)): $(LIB_$(PKG)) + +endif diff --git a/external/healpix/libfftpack/README b/external/healpix/libfftpack/README new file mode 100644 index 0000000..2c7e7cb --- /dev/null +++ b/external/healpix/libfftpack/README @@ -0,0 +1,34 @@ +ls_fft description: + +This package is intended to calculate one-dimensional real or complex FFTs +with high accuracy and good efficiency even for lengths containing large +prime factors. +The code is written in C, but a Fortran wrapper exists as well. + +Before any FFT is executed, a plan must be generated for it. Plan creation +is designed to be fast, so that there is no significant overhead if the +plan is only used once or a few times. + +The main component of the code is based on Paul N. Swarztrauber's FFTPACK in the +double precision incarnation by Hugh C. Pumphrey +(http://www.netlib.org/fftpack/dp.tgz). + +I replaced the iterative sine and cosine calculations in radfg() and radbg() +by an exact calculation, which slightly improves the transform accuracy for +real FFTs with lengths containing large prime factors. + +Since FFTPACK becomes quite slow for FFT lengths with large prime factors +(in the worst case of prime lengths it reaches O(n*n) complexity), I +implemented Bluestein's algorithm, which computes a FFT of length n by +several FFTs of length n2>=2*n-1 and a convolution. Since n2 can be chosen +to be highly composite, this algorithm is more efficient if n has large +prime factors. The longer FFTs themselves are then computed using the FFTPACK +routines. +Bluestein's algorithm was implemented according to the description at +http://en.wikipedia.org/wiki/Bluestein's_FFT_algorithm. + +Thread-safety: +All routines can be called concurrently; all information needed by ls_fft +is stored in the plan variable. However, using the same plan variable on +multiple threads simultaneously is not supported and will lead to data +corruption. diff --git a/external/healpix/libfftpack/bluestein.c b/external/healpix/libfftpack/bluestein.c new file mode 100644 index 0000000..e7f0d96 --- /dev/null +++ b/external/healpix/libfftpack/bluestein.c @@ -0,0 +1,189 @@ +/* + * This file is part of libfftpack. + * + * libfftpack 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. + * + * libfftpack 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 libfftpack; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * libfftpack 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, 2008 Max-Planck-Society + * \author Martin Reinecke + */ + +#include +#include +#include "fftpack.h" +#include "bluestein.h" + +/* returns the sum of all prime factors of n */ +size_t prime_factor_sum (size_t n) + { + size_t result=0,x,limit,tmp; + while (((tmp=(n>>1))<<1)==n) + { result+=2; n=tmp; } + + limit=(size_t)sqrt(n+0.01); + for (x=3; x<=limit; x+=2) + while ((tmp=(n/x))*x==n) + { + result+=x; + n=tmp; + limit=(size_t)sqrt(n+0.01); + } + if (n>1) result+=n; + + return result; + } + +/* returns the smallest composite of 2, 3 and 5 which is >= n */ +static size_t good_size(size_t n) + { + size_t maxfactors=1, i, j, k, f2=1, f3, f5, bestfac, guessfac; + while ((n>>maxfactors)>0) + ++maxfactors; + bestfac=1<bestfac) break; + f5=1; + for (k=0; k=bestfac) break; + if ((guessfac>=n) && (guessfac=2*n) coeff-=2*n; + angle = pibyn*coeff; + bk[2*m] = cos(angle); + bk[2*m+1] = sin(angle); + } + +/* initialize the zero-padded, Fourier transformed b_k. Add normalisation. */ + xn2 = 1./n2; + bkf[0] = bk[0]*xn2; + bkf[1] = bk[1]*xn2; + for (m=2; m<2*n; m+=2) + { + bkf[m] = bkf[2*n2-m] = bk[m] *xn2; + bkf[m+1] = bkf[2*n2-m+1] = bk[m+1] *xn2; + } + for (m=2*n;m<=(2*n2-2*n+1);++m) + bkf[m]=0.; + cffti (n2,work); + cfftf (n2,bkf,work); + } + +void bluestein (size_t n, double *data, double *tstorage, int isign) + { + size_t n2=*((size_t *)tstorage); + size_t m; + double *bk, *bkf, *akf, *work; + bk = tstorage+2; + bkf = tstorage+2+2*n; + work= tstorage+2+2*(n+n2); + akf = tstorage+2+2*n+6*n2+16; + +/* initialize a_k and FFT it */ + if (isign>0) + for (m=0; m<2*n; m+=2) + { + akf[m] = data[m]*bk[m] - data[m+1]*bk[m+1]; + akf[m+1] = data[m]*bk[m+1] + data[m+1]*bk[m]; + } + else + for (m=0; m<2*n; m+=2) + { + akf[m] = data[m]*bk[m] + data[m+1]*bk[m+1]; + akf[m+1] =-data[m]*bk[m+1] + data[m+1]*bk[m]; + } + for (m=2*n; m<2*n2; ++m) + akf[m]=0; + + cfftf (n2,akf,work); + +/* do the convolution */ + if (isign>0) + for (m=0; m<2*n2; m+=2) + { + double im = -akf[m]*bkf[m+1] + akf[m+1]*bkf[m]; + akf[m ] = akf[m]*bkf[m] + akf[m+1]*bkf[m+1]; + akf[m+1] = im; + } + else + for (m=0; m<2*n2; m+=2) + { + double im = akf[m]*bkf[m+1] + akf[m+1]*bkf[m]; + akf[m ] = akf[m]*bkf[m] - akf[m+1]*bkf[m+1]; + akf[m+1] = im; + } + + +/* inverse FFT */ + cfftb (n2,akf,work); + +/* multiply by b_k* */ + if (isign>0) + for (m=0; m<2*n; m+=2) + { + data[m] = bk[m] *akf[m] - bk[m+1]*akf[m+1]; + data[m+1] = bk[m+1]*akf[m] + bk[m] *akf[m+1]; + } + else + for (m=0; m<2*n; m+=2) + { + data[m] = bk[m] *akf[m] + bk[m+1]*akf[m+1]; + data[m+1] =-bk[m+1]*akf[m] + bk[m] *akf[m+1]; + } + } diff --git a/external/healpix/libfftpack/bluestein.h b/external/healpix/libfftpack/bluestein.h new file mode 100644 index 0000000..945e966 --- /dev/null +++ b/external/healpix/libfftpack/bluestein.h @@ -0,0 +1,48 @@ +/* + * This file is part of libfftpack. + * + * libfftpack 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. + * + * libfftpack 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 libfftpack; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * libfftpack 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 Max-Planck-Society + * \author Martin Reinecke + */ + +#ifndef PLANCK_BLUESTEIN_H +#define PLANCK_BLUESTEIN_H + +#include "c_utils.h" + +#ifdef __cplusplus +extern "C" { +#endif + +size_t prime_factor_sum (size_t n); + +void bluestein_i (size_t n, double **tstorage); +void bluestein (size_t n, double *data, double *tstorage, int isign); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/external/healpix/libfftpack/fftpack.c b/external/healpix/libfftpack/fftpack.c new file mode 100644 index 0000000..6d09d06 --- /dev/null +++ b/external/healpix/libfftpack/fftpack.c @@ -0,0 +1,833 @@ +/* + * This file is part of libfftpack. + * + * libfftpack 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. + * + * libfftpack 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 libfftpack; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * libfftpack is being developed at the Max-Planck-Institut fuer Astrophysik + * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt + * (DLR). + */ + +/* + fftpack.c : A set of FFT routines in C. + Algorithmically based on Fortran-77 FFTPACK by Paul N. Swarztrauber + (Version 4, 1985). + + C port by Martin Reinecke (2010) + */ + +#include +#include +#include +#include "fftpack.h" + +#define WA(x,i) wa[(i)+(x)*ido] +#define CH(a,b,c) ch[(a)+ido*((b)+l1*(c))] +#define CC(a,b,c) cc[(a)+ido*((b)+cdim*(c))] +#define PM(a,b,c,d) { a=c+d; b=c-d; } +#define PMC(a,b,c,d) { a.r=c.r+d.r; a.i=c.i+d.i; b.r=c.r-d.r; b.i=c.i-d.i; } +#define ADDC(a,b,c) { a.r=b.r+c.r; a.i=b.i+c.i; } +#define SCALEC(a,b) { a.r*=b; a.i*=b; } +#define CONJFLIPC(a) { double tmp_=a.r; a.r=-a.i; a.i=tmp_; } +/* (a+ib) = conj(c+id) * (e+if) */ +#define MULPM(a,b,c,d,e,f) { a=c*e+d*f; b=c*f-d*e; } + +typedef struct { + double r,i; +} cmplx; + +#define CONCAT(a,b) a ## b + +#define X(arg) CONCAT(passb,arg) +#define BACKWARD +#include "fftpack_inc.c" +#undef BACKWARD +#undef X + +#define X(arg) CONCAT(passf,arg) +#include "fftpack_inc.c" +#undef X + +#undef CC +#undef CH +#define CC(a,b,c) cc[(a)+ido*((b)+l1*(c))] +#define CH(a,b,c) ch[(a)+ido*((b)+cdim*(c))] + +static void radf2 (size_t ido, size_t l1, const double *cc, double *ch, + const double *wa) + { + const size_t cdim=2; + size_t i, k, ic; + double ti2, tr2; + + for (k=0; k=2*ip) aidx-=2*ip; + ar2=csarr[aidx]; + ai2=csarr[aidx+1]; + for(ik=0; ik=2*ip) aidx-=2*ip; + ar2=csarr[aidx]; + ai2=csarr[aidx+1]; + for(ik=0; ik0) ? passb4(ido, l1, p1, p2, wa+iw) + : passf4(ido, l1, p1, p2, wa+iw); + else if(ip==2) + (isign>0) ? passb2(ido, l1, p1, p2, wa+iw) + : passf2(ido, l1, p1, p2, wa+iw); + else if(ip==3) + (isign>0) ? passb3(ido, l1, p1, p2, wa+iw) + : passf3(ido, l1, p1, p2, wa+iw); + else if(ip==5) + (isign>0) ? passb5(ido, l1, p1, p2, wa+iw) + : passf5(ido, l1, p1, p2, wa+iw); + else if(ip==6) + (isign>0) ? passb6(ido, l1, p1, p2, wa+iw) + : passf6(ido, l1, p1, p2, wa+iw); + else + (isign>0) ? passbg(ido, ip, l1, p1, p2, wa+iw) + : passfg(ido, ip, l1, p1, p2, wa+iw); + SWAP(p1,p2,cmplx *); + l1=l2; + iw+=(ip-1)*ido; + } + if (p1!=c) + memcpy (c,p1,n*sizeof(cmplx)); + } + +void cfftf(size_t n, double c[], double wsave[]) + { + if (n!=1) + cfft1(n, (cmplx*)c, (cmplx*)wsave, (cmplx*)(wsave+2*n), + (size_t*)(wsave+4*n),-1); + } + +void cfftb(size_t n, double c[], double wsave[]) + { + if (n!=1) + cfft1(n, (cmplx*)c, (cmplx*)wsave, (cmplx*)(wsave+2*n), + (size_t*)(wsave+4*n),+1); + } + +static void factorize (size_t n, const size_t *pf, size_t npf, size_t *ifac) + { + size_t nl=n, nf=0, ntry=0, j=0, i; + +startloop: + j++; + ntry = (j<=npf) ? pf[j-1] : ntry+2; + do + { + size_t nq=nl / ntry; + size_t nr=nl-ntry*nq; + if (nr!=0) + goto startloop; + nf++; + ifac[nf+1]=ntry; + nl=nq; + if ((ntry==2) && (nf!=1)) + { + for (i=nf+1; i>2; --i) + ifac[i]=ifac[i-1]; + ifac[2]=2; + } + } + while(nl!=1); + ifac[0]=n; + ifac[1]=nf; + } + +static void cffti1(size_t n, double wa[], size_t ifac[]) + { + static const size_t ntryh[5]={4,6,3,2,5}; + static const double twopi=6.28318530717958647692; + size_t j, k, fi; + + double argh=twopi/n; + size_t i=0, l1=1; + factorize (n,ntryh,5,ifac); + for(k=1; k<=ifac[1]; k++) + { + size_t ip=ifac[k+1]; + size_t ido=n/(l1*ip); + for(j=1; j6) + { + wa[is ]=wa[i ]; + wa[is+1]=wa[i+1]; + } + } + l1*=ip; + } + } + +void cffti(size_t n, double wsave[]) + { if (n!=1) cffti1(n, wsave+2*n,(size_t*)(wsave+4*n)); } + + +/*---------------------------------------------------------------------- + rfftf1, rfftb1, rfftf, rfftb, rffti1, rffti. Real FFTs. + ----------------------------------------------------------------------*/ + +static void rfftf1(size_t n, double c[], double ch[], const double wa[], + const size_t ifac[]) + { + size_t k1, l1=n, nf=ifac[1], iw=n-1; + double *p1=ch, *p2=c; + + for(k1=1; k1<=nf;++k1) + { + size_t ip=ifac[nf-k1+2]; + size_t ido=n / l1; + l1 /= ip; + iw-=(ip-1)*ido; + SWAP (p1,p2,double *); + if(ip==4) + radf4(ido, l1, p1, p2, wa+iw); + else if(ip==2) + radf2(ido, l1, p1, p2, wa+iw); + else if(ip==3) + radf3(ido, l1, p1, p2, wa+iw); + else if(ip==5) + radf5(ido, l1, p1, p2, wa+iw); + else + { + if (ido==1) + SWAP (p1,p2,double *); + radfg(ido, ip, l1, ido*l1, p1, p2, wa+iw); + SWAP (p1,p2,double *); + } + } + if (p1==c) + memcpy (c,ch,n*sizeof(double)); + } + +static void rfftb1(size_t n, double c[], double ch[], const double wa[], + const size_t ifac[]) + { + size_t k1, l1=1, nf=ifac[1], iw=0; + double *p1=c, *p2=ch; + + for(k1=1; k1<=nf; k1++) + { + size_t ip = ifac[k1+1], + ido= n/(ip*l1); + if(ip==4) + radb4(ido, l1, p1, p2, wa+iw); + else if(ip==2) + radb2(ido, l1, p1, p2, wa+iw); + else if(ip==3) + radb3(ido, l1, p1, p2, wa+iw); + else if(ip==5) + radb5(ido, l1, p1, p2, wa+iw); + else + { + radbg(ido, ip, l1, ido*l1, p1, p2, wa+iw); + if (ido!=1) + SWAP (p1,p2,double *); + } + SWAP (p1,p2,double *); + l1*=ip; + iw+=(ip-1)*ido; + } + if (p1!=c) + memcpy (c,ch,n*sizeof(double)); + } + +void rfftf(size_t n, double r[], double wsave[]) + { if(n!=1) rfftf1(n, r, wsave, wsave+n,(size_t*)(wsave+2*n)); } + +void rfftb(size_t n, double r[], double wsave[]) + { if(n!=1) rfftb1(n, r, wsave, wsave+n,(size_t*)(wsave+2*n)); } + +static void rffti1(size_t n, double wa[], size_t ifac[]) + { + static const size_t ntryh[4]={4,2,3,5}; + static const double twopi=6.28318530717958647692; + size_t i, j, k, fi; + + double argh=twopi/n; + size_t is=0, l1=1; + factorize (n,ntryh,4,ifac); + for (k=1; kip) iang-=ip; + abr.r += ccl[l ].r*wal[iang].r; + abr.i += ccl[l ].i*wal[iang].r; + abi.r += ccl[lc].r*wal[iang].i; + abi.i += ccl[lc].i*wal[iang].i; + } +#ifndef BACKWARD + { abi.i=-abi.i; abi.r=-abi.r; } +#endif + CONJFLIPC(abi) + PMC(CH(i,k,j),CH(i,k,jc),abr,abi) + } + } + + DEALLOC(tarr); + + if (ido==1) return; + + for (j=1; j +
  • \ref fftgroup "Programming interface" +
+ */ diff --git a/external/healpix/libfftpack/ls_fft.c b/external/healpix/libfftpack/ls_fft.c new file mode 100644 index 0000000..cf448ef --- /dev/null +++ b/external/healpix/libfftpack/ls_fft.c @@ -0,0 +1,265 @@ +/* + * This file is part of libfftpack. + * + * libfftpack 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. + * + * libfftpack 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 libfftpack; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * libfftpack 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 Max-Planck-Society + * \author Martin Reinecke + */ + +#include +#include +#include +#include "bluestein.h" +#include "fftpack.h" +#include "ls_fft.h" + +complex_plan make_complex_plan (size_t length) + { + complex_plan plan = RALLOC(complex_plan_i,1); + size_t pfsum = prime_factor_sum(length); + double comp1 = (double)(length*pfsum); + double comp2 = 2*3*length*log(3.*length); + comp2*=3.; /* fudge factor that appears to give good overall performance */ + plan->length=length; + plan->bluestein = (comp2bluestein) + bluestein_i (length,&(plan->work)); + else + { + plan->work=RALLOC(double,4*length+15); + cffti(length, plan->work); + } + return plan; + } + +void kill_complex_plan (complex_plan plan) + { + DEALLOC(plan->work); + DEALLOC(plan); + } + +void complex_plan_forward (complex_plan plan, double *data) + { + if (plan->bluestein) + bluestein (plan->length, data, plan->work, -1); + else + cfftf (plan->length, data, plan->work); + } + +void complex_plan_backward (complex_plan plan, double *data) + { + if (plan->bluestein) + bluestein (plan->length, data, plan->work, 1); + else + cfftb (plan->length, data, plan->work); + } + + +real_plan make_real_plan (size_t length) + { + real_plan plan = RALLOC(real_plan_i,1); + size_t pfsum = prime_factor_sum(length); + double comp1 = .5*length*pfsum; + double comp2 = 2*3*length*log(3.*length); + comp2*=3; /* fudge factor that appears to give good overall performance */ + plan->length=length; + plan->bluestein = (comp2bluestein) + bluestein_i (length,&(plan->work)); + else + { + plan->work=RALLOC(double,2*length+15); + rffti(length, plan->work); + } + return plan; + } + +void kill_real_plan (real_plan plan) + { + DEALLOC(plan->work); + DEALLOC(plan); + } + +void real_plan_forward_fftpack (real_plan plan, double *data) + { + if (plan->bluestein) + { + size_t m; + size_t n=plan->length; + double *tmp = RALLOC(double,2*n); + for (m=0; mwork,-1); + data[0] = tmp[0]; + memcpy (data+1, tmp+2, (n-1)*sizeof(double)); + DEALLOC(tmp); + } + else + rfftf (plan->length, data, plan->work); + } + +static void fftpack2halfcomplex (double *data, size_t n) + { + size_t m; + double *tmp = RALLOC(double,n); + tmp[0]=data[0]; + for (m=1; m<(n+1)/2; ++m) + { + tmp[m]=data[2*m-1]; + tmp[n-m]=data[2*m]; + } + if (!(n&1)) + tmp[n/2]=data[n-1]; + memcpy (data,tmp,n*sizeof(double)); + DEALLOC(tmp); + } + +static void halfcomplex2fftpack (double *data, size_t n) + { + size_t m; + double *tmp = RALLOC(double,n); + tmp[0]=data[0]; + for (m=1; m<(n+1)/2; ++m) + { + tmp[2*m-1]=data[m]; + tmp[2*m]=data[n-m]; + } + if (!(n&1)) + tmp[n-1]=data[n/2]; + memcpy (data,tmp,n*sizeof(double)); + DEALLOC(tmp); + } + +void real_plan_forward_fftw (real_plan plan, double *data) + { + real_plan_forward_fftpack (plan, data); + fftpack2halfcomplex (data,plan->length); + } + +void real_plan_backward_fftpack (real_plan plan, double *data) + { + if (plan->bluestein) + { + size_t m; + size_t n=plan->length; + double *tmp = RALLOC(double,2*n); + tmp[0]=data[0]; + tmp[1]=0.; + memcpy (tmp+2,data+1, (n-1)*sizeof(double)); + if ((n&1)==0) tmp[n+1]=0.; + for (m=2; mwork, 1); + for (m=0; mlength, data, plan->work); + } + +void real_plan_backward_fftw (real_plan plan, double *data) + { + halfcomplex2fftpack (data,plan->length); + real_plan_backward_fftpack (plan, data); + } + +void real_plan_forward_c (real_plan plan, double *data) + { + size_t m; + size_t n=plan->length; + + if (plan->bluestein) + { + for (m=1; m<2*n; m+=2) + data[m]=0; + bluestein (plan->length, data, plan->work, -1); + data[1]=0; + for (m=2; mwork); + data[0] = data[1]; + data[1] = 0; + for (m=2; mlength; + + if (plan->bluestein) + { + size_t m; + data[1]=0; + for (m=2; mlength, data, plan->work, 1); + for (m=1; m<2*n; m+=2) + data[m]=0; + } + else + { + ptrdiff_t m; + data[1] = data[0]; + rfftb (n, data+1, plan->work); + for (m=n-1; m>=0; --m) + { + data[2*m] = data[m+1]; + data[2*m+1] = 0.; + } + } + } diff --git a/external/healpix/libfftpack/ls_fft.h b/external/healpix/libfftpack/ls_fft.h new file mode 100644 index 0000000..3460d2f --- /dev/null +++ b/external/healpix/libfftpack/ls_fft.h @@ -0,0 +1,158 @@ +/* + * This file is part of libfftpack. + * + * libfftpack 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. + * + * libfftpack 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 libfftpack; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * libfftpack is being developed at the Max-Planck-Institut fuer Astrophysik + * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt + * (DLR). + */ + +/*! \file ls_fft.h + * Interface for the LevelS FFT package. + * + * Copyright (C) 2004 Max-Planck-Society + * \author Martin Reinecke + */ + +#ifndef PLANCK_LS_FFT_H +#define PLANCK_LS_FFT_H + +#include "c_utils.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*!\defgroup fftgroup FFT interface +This package is intended to calculate one-dimensional real or complex FFTs +with high accuracy and good efficiency even for lengths containing large +prime factors. +The code is written in C, but a Fortran wrapper exists as well. + +Before any FFT is executed, a plan must be generated for it. Plan creation +is designed to be fast, so that there is no significant overhead if the +plan is only used once or a few times. + +The main component of the code is based on Paul N. Swarztrauber's FFTPACK in the +double precision incarnation by Hugh C. Pumphrey +(http://www.netlib.org/fftpack/dp.tgz). + +I replaced the iterative sine and cosine calculations in radfg() and radbg() +by an exact calculation, which slightly improves the transform accuracy for +real FFTs with lengths containing large prime factors. + +Since FFTPACK becomes quite slow for FFT lengths with large prime factors +(in the worst case of prime lengths it reaches \f$\mathcal{O}(n^2)\f$ +complexity), I implemented Bluestein's algorithm, which computes a FFT of length +\f$n\f$ by several FFTs of length \f$n_2\ge 2n-1\f$ and a convolution. Since +\f$n_2\f$ can be chosen to be highly composite, this algorithm is more efficient +if \f$n\f$ has large prime factors. The longer FFTs themselves are then computed +using the FFTPACK routines. +Bluestein's algorithm was implemented according to the description on Wikipedia +( +http://en.wikipedia.org/wiki/Bluestein%27s_FFT_algorithm). + +\b Thread-safety: +All routines can be called concurrently; all information needed by +ls_fft is stored in the plan variable. However, using the same plan +variable on multiple threads simultaneously is not supported and will lead to +data corruption. +*/ +/*! \{ */ + +typedef struct + { + double *work; + size_t length; + int bluestein; + } complex_plan_i; + +/*! The opaque handle type for complex-FFT plans. */ +typedef complex_plan_i * complex_plan; + +/*! Returns a plan for a complex FFT with \a length elements. */ +complex_plan make_complex_plan (size_t length); +/*! Destroys a plan for a complex FFT. */ +void kill_complex_plan (complex_plan plan); +/*! Computes a complex forward FFT on \a data, using \a plan. + \a Data has the form r0, i0, r1, i1, ..., + r[length-1], i[length-1]. */ +void complex_plan_forward (complex_plan plan, double *data); +/*! Computes a complex backward FFT on \a data, using \a plan. + \a Data has the form r0, i0, r1, i1, ..., + r[length-1], i[length-1]. */ +void complex_plan_backward (complex_plan plan, double *data); + +typedef struct + { + double *work; + size_t length; + int bluestein; + } real_plan_i; + +/*! The opaque handle type for real-FFT plans. */ +typedef real_plan_i * real_plan; + +/*! Returns a plan for a real FFT with \a length elements. */ +real_plan make_real_plan (size_t length); +/*! Destroys a plan for a real FFT. */ +void kill_real_plan (real_plan plan); +/*! Computes a real forward FFT on \a data, using \a plan + and assuming the FFTPACK storage scheme: + - on entry, \a data has the form r0, r1, ..., r[length-1]; + - on exit, it has the form r0, r1, i1, r2, i2, ... + (a total of \a length values). */ +void real_plan_forward_fftpack (real_plan plan, double *data); +/*! Computes a real forward FFT on \a data, using \a plan + and assuming the FFTPACK storage scheme: + - on entry, \a data has the form r0, r1, i1, r2, i2, ... + (a total of \a length values); + - on exit, it has the form r0, r1, ..., r[length-1]. */ +void real_plan_backward_fftpack (real_plan plan, double *data); +/*! Computes a real forward FFT on \a data, using \a plan + and assuming the FFTW halfcomplex storage scheme: + - on entry, \a data has the form r0, r1, ..., r[length-1]; + - on exit, it has the form r0, r1, r2, ..., i2, i1. */ +void real_plan_forward_fftw (real_plan plan, double *data); +/*! Computes a real backward FFT on \a data, using \a plan + and assuming the FFTW halfcomplex storage scheme: + - on entry, \a data has the form r0, r1, r2, ..., i2, i1. + - on exit, it has the form r0, r1, ..., r[length-1]. */ +void real_plan_backward_fftw (real_plan plan, double *data); +/*! Computes a real forward FFT on \a data, using \a plan + and assuming a full-complex storage scheme: + - on entry, \a data has the form r0, [ignored], r1, [ignored], ..., + r[length-1], [ignored]; + - on exit, it has the form r0, i0, r1, i1, ..., + r[length-1], i[length-1]. + */ +void real_plan_forward_c (real_plan plan, double *data); +/*! Computes a real backward FFT on \a data, using \a plan + and assuming a full-complex storage scheme: + - on entry, \a data has the form r0, i0, r1, i1, ..., + r[length-1], i[length-1]; + - on exit, it has the form r0, 0, r1, 0, ..., r[length-1], 0. */ +void real_plan_backward_c (real_plan plan, double *data); + +/*! \} */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/external/healpix/libfftpack/planck.make b/external/healpix/libfftpack/planck.make new file mode 100644 index 0000000..c171367 --- /dev/null +++ b/external/healpix/libfftpack/planck.make @@ -0,0 +1,21 @@ +PKG:=libfftpack + +SD:=$(SRCROOT)/$(PKG) +OD:=$(BLDROOT)/$(PKG) + +FULL_INCLUDE+= -I$(SD) + +HDR_$(PKG):=$(SD)/*.h +LIB_$(PKG):=$(LIBDIR)/libfftpack.a +OBJ:=fftpack.o bluestein.o ls_fft.o +OBJ:=$(OBJ:%=$(OD)/%) + +ODEP:=$(HDR_$(PKG)) $(HDR_c_utils) + +$(OD)/fftpack.o: $(SD)/fftpack_inc.c + +$(OBJ): $(ODEP) | $(OD)_mkdir +$(LIB_$(PKG)): $(OBJ) + +all_hdr+=$(HDR_$(PKG)) +all_lib+=$(LIB_$(PKG)) diff --git a/external/healpix/libpsht/libpsht.dox b/external/healpix/libpsht/libpsht.dox new file mode 100644 index 0000000..3ccda20 --- /dev/null +++ b/external/healpix/libpsht/libpsht.dox @@ -0,0 +1,103 @@ +/*! \mainpage libpsht documentation + + */ + +/*! \page introduction Introduction to libpsht + + "PSHT" is an acronym for Performant Spherical Harmonic Transforms. + All user-visible data types and functions in this library start with + the prefix "psht_", or with "pshts_" and "pshtd_" for single- and + double precision variants, respectively. + + libpsht's main functionality is the conversion between maps + on the sphere and spherical harmonic coefficients (or a_lm). + A map is defined as a set of rings, which in turn consist of + individual pixels that +
    +
  • all have the same colatitude and
  • +
  • are uniformly spaced in azimuthal direction.
  • +
+ Consequently, a ring is completely defined by +
    +
  • its colatitute (in radians)
  • +
  • the number of pixels it contains
  • +
  • the azimuth (in radians) of the first pixel in the ring
  • +
  • the weight that must be multiplied to every pixel during a map + analysis (typically the solid angle of a pixel in the ring)
  • +
  • the offset of the first ring pixel in the map array
  • +
  • the stride between consecutive pixels in the ring.
  • +
+ The map array is a one-dimensional array of type float or + double, which contains the values of all map pixels. It is assumed + that the pixels of every ring are stored inside this array in order of + increasing azimuth and with the specified stride. Note however that the rings + themselves can be stored in any order inside the array. + + The a_lm array is a one-dimensional array of type pshts_cmplx or + pshtd_cmplx, which contains all spherical harmonic coefficients + for 0<=m<=mmax and m<=l<=lmax. There is only one constraint on the + internal structure of the array, which is: + + Index[a_l+1,m] = Index[a_l,m] + stride + + That means that coefficients with identical m but different l + can be interpreted as a one-dimensional array in l with a unique + stride. + + Several functions are provided for efficient index computation in this array; + they are documented \ref almgroup "here". + + Information about a pixelisation of the sphere is stored in objects of + type psht_geom_info. It is possible to create such an object for any + supported pixelisation by using the function psht_make_geometry_info(); + however, several easier-to-use functions are \ref geominfogroup "supplied" + for generating often-used pixelisations like ECP grids, Gaussian grids, + and Healpix grids. + + A distinctive feature of PSHT is the ability to execute several transforms + simultaneously (as long as they have the same geometry information and + a_lm structure); this has the advantage that the spherical + harmonics only have to be evaluated once for all of the transforms, saving + a substantial amount of CPU time. The set of functions dealing with such + job lists is implemented twice, both for \ref sjoblistgroup "single" + and \ref djoblistgroup "double" precision transforms. + + Currently, PSHT supports the following kinds of transforms: +
    +
  • scalar a_lm to map
  • +
  • scalar map to a_lm
  • +
  • polarised a_lm to map
  • +
  • polarised map to a_lm
  • +
  • spin(1-100) a_lm to map
  • +
  • spin(1-100) map to a_lm
  • +
  • scalar a_lm to maps of first derivatives
  • +
+ + All these different kinds can be mixed freely within a job list; i.e., it is + possible to perform an a_lm->map and a map->a_lm transform simultaneously. + + PSHT supports shared-memory parallelisation via OpenMP; this feature will + be automatically enabled if the compiler supports it. + + PSHT will also make use of SSE2 instructions when compiled for a platform + known to support them (basically all Intel/AMD processors running a 64bit + operating system). + + The spherical harmonic transforms can ce executed on double-precision and + single-precision maps and a_lm, but for accuracy reasons the computations + will always be performed in double precision. As a consequence, + single-precision transforms will most likely not be faster than their + double-precision counterparts, but they will require significantly less + memory. + + Two example and benchmark programs are distributed with PSHT: +
    +
  • psht_test.c checks the accuracy of the (iterative) map analysis + algorithm
  • +
  • psht_perftest.c checks the performance of single or multiple + transforms
  • +
+*/ diff --git a/external/healpix/libpsht/planck.make b/external/healpix/libpsht/planck.make new file mode 100644 index 0000000..90f44cb --- /dev/null +++ b/external/healpix/libpsht/planck.make @@ -0,0 +1,27 @@ +PKG:=libpsht + +SD:=$(SRCROOT)/$(PKG) +OD:=$(BLDROOT)/$(PKG) + +FULL_INCLUDE+= -I$(SD) + +HDR_$(PKG):=$(SD)/*.h +LIB_$(PKG):=$(LIBDIR)/libpsht.a +BIN:=psht_test psht_perftest +LIBOBJ:=ylmgen_c.o psht.o psht_geomhelpers.o psht_almhelpers.o +ALLOBJ:=$(LIBOBJ) psht_test.o psht_perftest.o +LIBOBJ:=$(LIBOBJ:%=$(OD)/%) +ALLOBJ:=$(ALLOBJ:%=$(OD)/%) + +ODEP:=$(HDR_$(PKG)) $(HDR_libfftpack) $(HDR_c_utils) $(SD)/psht_inc.c +BDEP:=$(LIB_$(PKG)) $(LIB_libfftpack) $(LIB_c_utils) + +$(LIB_$(PKG)): $(LIBOBJ) + +$(ALLOBJ): $(ODEP) | $(OD)_mkdir +BIN:=$(BIN:%=$(BINDIR)/%) +$(BIN): $(BINDIR)/% : $(OD)/%.o $(BDEP) + +all_hdr+=$(HDR_$(PKG)) +all_lib+=$(LIB_$(PKG)) +all_cbin+=$(BIN) diff --git a/external/healpix/libpsht/psht.c b/external/healpix/libpsht/psht.c new file mode 100644 index 0000000..3c52351 --- /dev/null +++ b/external/healpix/libpsht/psht.c @@ -0,0 +1,216 @@ +/* + * This file is part of libpsht. + * + * libpsht 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. + * + * libpsht 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 libpsht; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * libpsht is being developed at the Max-Planck-Institut fuer Astrophysik + * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt + * (DLR). + */ + +/*! \file psht.c + * Spherical transform library + * + * Copyright (C) 2006-2010 Max-Planck-Society + * \author Martin Reinecke + */ + +#include +#include "ls_fft.h" +#include "sse_utils.h" +#include "ylmgen_c.h" +#include "psht.h" +#include "c_utils.h" + +const pshts_cmplx pshts_cmplx_null={0,0}; +const pshtd_cmplx pshtd_cmplx_null={0,0}; + +static void get_chunk_info (int ndata, int *nchunks, int *chunksize) + { + static const int chunksize_min=100; + static const int nchunks_max=10; + *chunksize = IMAX(chunksize_min,(ndata+nchunks_max-1)/nchunks_max); + if ((*chunksize)&1) ++(*chunksize); + *nchunks = (ndata+*chunksize-1) / *chunksize; + } + +typedef struct + { + double phi0_; + pshtd_cmplx *shiftarr, *work; + int s_shift, s_work; + real_plan plan; + int norot; + } ringhelper; + +static void ringhelper_init (ringhelper *self) + { + static ringhelper rh_null = { 0, NULL, NULL, 0, 0, NULL, 0 }; + *self = rh_null; + } + +static void ringhelper_destroy (ringhelper *self) + { + if (self->plan) kill_real_plan(self->plan); + DEALLOC(self->shiftarr); + DEALLOC(self->work); + ringhelper_init(self); + } + +static void ringhelper_update (ringhelper *self, int nph, int mmax, double phi0) + { + int m; + self->norot = (fabs(phi0)<1e-14); + if (!(self->norot)) + if ((mmax!=self->s_shift-1) || (!FAPPROX(phi0,self->phi0_,1e-12))) + { + RESIZE (self->shiftarr,pshtd_cmplx,mmax+1); + self->s_shift = mmax+1; + self->phi0_ = phi0; + for (m=0; m<=mmax; ++m) + { + self->shiftarr[m].re = cos(m*phi0); + self->shiftarr[m].im = sin(m*phi0); + } + } + if (!self->plan) self->plan=make_real_plan(nph); + if (nph!=(int)self->plan->length) + { + kill_real_plan(self->plan); + self->plan=make_real_plan(nph); + } + GROW(self->work,pshtd_cmplx,self->s_work,nph); + } + +static int ringinfo_compare (const void *xa, const void *xb) + { + const psht_ringinfo *a = xa, *b=xb; + if (a->sth < b->sth) return -1; + if (a->sth > b->sth) return 1; + return 0; + } +static int ringpair_compare (const void *xa, const void *xb) + { + const psht_ringpair *a = xa, *b=xb; + if (a->r1.nph==b->r1.nph) + { + if (a->r1.phi0r1.phi0) return -1; + if (a->r1.phi0>b->r1.phi0) return 1; + return 0; + } + if (a->r1.nphr1.nph) return -1; + if (a->r1.nph>b->r1.nph) return 1; + return 0; + } + +static void assert_jobspace (int njobs_now) + { + UTIL_ASSERT (njobs_nowlmax = lmax; + info->mmax = mmax; + info->mstart = RALLOC(ptrdiff_t,mmax+1); + info->stride = stride; + for (m=0; m<=mmax; ++m) + info->mstart[m] = mstart[m]; + *alm_info = info; + } + +ptrdiff_t psht_alm_index (const psht_alm_info *self, int l, int m) + { return self->mstart[m]+self->stride*l; } + +void psht_destroy_alm_info (psht_alm_info *info) + { + DEALLOC (info->mstart); + DEALLOC (info); + } + +void psht_make_geom_info (int nrings, const int *nph, const ptrdiff_t *ofs, + const int *stride, const double *phi0, const double *theta, + const double *weight, psht_geom_info **geom_info) + { + psht_geom_info *info = RALLOC(psht_geom_info,1); + psht_ringinfo *infos = RALLOC(psht_ringinfo,nrings); + + int pos=0; + int m; + info->pair=RALLOC(psht_ringpair,nrings); + info->npairs=0; + *geom_info = info; + + for (m=0; mpair[info->npairs].r1=infos[pos]; + info->pair[info->npairs].r2=infos[pos+1]; + pos+=2; + ++info->npairs; + } + else + { + info->pair[info->npairs].r1=infos[pos]; + info->pair[info->npairs].r2.nph=-1; + ++pos; + ++info->npairs; + } + } + DEALLOC(infos); + + qsort(info->pair,info->npairs,sizeof(psht_ringpair),ringpair_compare); + } + +void psht_destroy_geom_info (psht_geom_info *geom_info) + { + DEALLOC (geom_info->pair); + DEALLOC (geom_info); + } + +#define CONCAT(a,b) a ## b + +#define FLT double +#define X(arg) CONCAT(pshtd_,arg) +#include "psht_inc.c" +#undef FLT +#undef X + +#define FLT float +#define X(arg) CONCAT(pshts_,arg) +#include "psht_inc.c" +#undef FLT +#undef X + +#undef CONCAT diff --git a/external/healpix/libpsht/psht.h b/external/healpix/libpsht/psht.h new file mode 100644 index 0000000..42000b6 --- /dev/null +++ b/external/healpix/libpsht/psht.h @@ -0,0 +1,363 @@ +/* + * This file is part of libpsht. + * + * libpsht 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. + * + * libpsht 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 libpsht; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * libpsht is being developed at the Max-Planck-Institut fuer Astrophysik + * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt + * (DLR). + */ + +/*! \file psht.h + * Interface for the spherical transform library. + * + * Copyright (C) 2006-2010 Max-Planck-Society + * \author Martin Reinecke + */ + +#ifndef PLANCK_PSHT_H +#define PLANCK_PSHT_H + +#include +#include "sse_utils.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*! PSHT type for storing single-precision complex values */ +typedef struct + { + float re,im; + } pshts_cmplx; + +/*! PSHT type for storing double-precision complex values */ +typedef struct + { + double re,im; + } pshtd_cmplx; + +extern const pshts_cmplx pshts_cmplx_null; +extern const pshtd_cmplx pshtd_cmplx_null; + +/*! Helper type containing information about a single ring. + \note No user serviceable parts inside! */ +typedef struct + { + double theta, phi0, weight, cth, sth; + ptrdiff_t ofs; + int nph, stride; + } psht_ringinfo; + +/*! Helper type containing information about a pair of rings with colatitudes + symmetric around the equator. + \note No user serviceable parts inside! */ +typedef struct + { + psht_ringinfo r1,r2; + } psht_ringpair; + +/*! Enumeration of PSHT job types. + \note No user serviceable parts inside! */ +typedef enum { MAP2ALM, ALM2MAP, ALM2MAP_DERIV1 } psht_jobtype; + +/*! Type holding all required information about a map geometry. + \note No user serviceable parts inside! */ +typedef struct + { + psht_ringpair *pair; + int npairs; + } psht_geom_info; + +/*! Type holding all required information about a double precision SHT. + \note No user serviceable parts inside! */ +typedef struct + { + psht_jobtype type; + int spin; + int add_output; + int nmaps, nalm; + double *map[3]; + pshtd_cmplx *alm[3]; + pshtd_cmplx *phas1[3], *phas2[3]; + double *norm_l; + union { +#ifdef PLANCK_HAVE_SSE2 + v2df *v[3]; + v2df2 *v2[3]; +#else + pshtd_cmplx *c[3]; +#endif + } alm_tmp; + } pshtd_job; + +enum { psht_maxjobs=10 }; + +/*! Type holding a list of simultaneous double precision SHT jobs. + \note No user serviceable parts inside! */ +typedef struct + { + pshtd_job job[psht_maxjobs]; + int njobs; + } pshtd_joblist; + +/*! Type holding all required information about a single precision SHT. + \note No user serviceable parts inside! */ +typedef struct + { + psht_jobtype type; + int spin; + int add_output; + int nmaps, nalm; + float *map[3]; + pshts_cmplx *alm[3]; + pshtd_cmplx *phas1[3], *phas2[3]; + double *norm_l; + union { +#ifdef PLANCK_HAVE_SSE2 + v2df *v[3]; + v2df2 *v2[3]; +#else + pshtd_cmplx *c[3]; +#endif + } alm_tmp; + } pshts_job; + +/*! Type holding a list of simultaneous single precision SHT jobs. + \note No user serviceable parts inside! */ +typedef struct + { + pshts_job job[psht_maxjobs]; + int njobs; + } pshts_joblist; + +/*! \defgroup almgroup Helpers for calculation of a_lm indices */ +/*! \{ */ + +/*! Helper type for index calculation in a_lm arrays. */ +typedef struct + { + /*! Maximum \a l index of the array */ + int lmax; + /*! Maximum \a m index of the array */ + int mmax; + /*! Array containing the (hypothetical) indices of the coefficient + with quantum numbers 0,\a m */ + ptrdiff_t *mstart; + /*! Stride between a_lm and a_(l+1),m */ + ptrdiff_t stride; + } psht_alm_info; + +/*! Creates an Alm data structure information from the following parameters: + \param lmax maximum \a l quantum number (>=0) + \param mmax maximum \a m quantum number (0<= \a mmax <= \a lmax) + \param stride the stride between consecutive a_lm entries + \param mstart the index of the (hypothetical) coefficient with the + quantum numbers 0,\a m. Must have \a mmax+1 entries. + \param alm_info will hold a pointer to the newly created data structure + */ +void psht_make_alm_info (int lmax, int mmax, int stride, + const ptrdiff_t *mstart, psht_alm_info **alm_info); +/*! Returns the index of the coefficient with quantum numbers \a l,\a m. */ +ptrdiff_t psht_alm_index (const psht_alm_info *self, int l, int m); +/*! Deallocates the a_lm info object. */ +void psht_destroy_alm_info (psht_alm_info *info); + +/* \} */ + +/*! \defgroup geominfogroup Functions for dealing with geometry information */ +/*! \{ */ + +/*! Creates a geometry information from a set of ring descriptions. + All arrays passed to this function must have \a nrings elements. + \param nrings the number of rings in the map + \param nph the number of pixels in each ring + \param ofs the index of the first pixel in each ring in the map array + \param stride the stride between consecutive pixels + \param phi0 the azimuth (in radians) of the first pixel in each ring + \param theta the colatitude (in radians) of each ring + \param weight the pixel weight to be used for the ring + \param geom_info will hold a pointer to the newly created data structure + */ +void psht_make_geom_info (int nrings, const int *nph, const ptrdiff_t *ofs, + const int *stride, const double *phi0, const double *theta, + const double *weight, psht_geom_info **geom_info); + +/*! Deallocates the geometry information in \a info. */ +void psht_destroy_geom_info (psht_geom_info *info); + +/* \} */ + +/*! \defgroup sjoblistgroup Functions for dealing with single precision job lists +\note All pointers to maps or a_lm that are passed to the job-adding functions +must not be de-allocated until after the last call of execute_jobs() for +a particular job list! This is because PSHT does not copy the input data, +but only stores the pointers to the supplied maps and a_lm. + */ +/*! \{ */ + +/*! Creates a new joblist object. */ +void pshts_make_joblist (pshts_joblist **joblist); +/*! Removes all jobs in \a joblist. */ +void pshts_clear_joblist (pshts_joblist *joblist); +/*! Deallocates the given joblist object. */ +void pshts_destroy_joblist (pshts_joblist *joblist); + +/*! Adds a new scalar alm2map job to \a joblist, which reads data from \a alm + and writes data to \a map. If \a add_output is 0, \a map will be + overwritten, else the result will be added to \a map. */ +void pshts_add_job_alm2map (pshts_joblist *joblist, const pshts_cmplx *alm, + float *map, int add_output); +/*! Adds a new scalar map2alm job to \a joblist, which reads data from \a map + and writes data to \a alm. If \a add_output is 0, \a alm will be + overwritten, else the result will be added to \a alm. */ +void pshts_add_job_map2alm (pshts_joblist *joblist, const float *map, + pshts_cmplx *alm, int add_output); +/*! Adds a new polarised alm2map job to \a joblist, which reads data from + \a almT, \a almG and \a almC and writes data to \a mapT, \a mapQ and + \a mapU. If \a add_output is 0, the output maps will be + overwritten, else the result will be added to the output maps. */ +void pshts_add_job_alm2map_pol (pshts_joblist *joblist, + const pshts_cmplx *almT, const pshts_cmplx *almG, const pshts_cmplx *almC, + float *mapT, float *mapQ, float *mapU, int add_output); +/*! Adds a new polarised map2alm job to \a joblist, which reads data from + \a mapT, \a mapQ and \a mapU and writes data to \a almT, \a almG and + \a almC. If \a add_output is 0, the output a_lm will be + overwritten, else the result will be added to the output a_lm. */ +void pshts_add_job_map2alm_pol (pshts_joblist *joblist, + const float *mapT, const float *mapQ, const float *mapU, + pshts_cmplx *almT, pshts_cmplx *almG, pshts_cmplx *almC, int add_output); +/*! Adds a new spin alm2map job to \a joblist, which reads data from + \a alm1 and \a alm2 and writes data to \a map1 and map2. + \a spin must be 1, 2, or 3. If \a add_output is 0, + the output maps will be overwritten, else the result will be + added to the output maps. */ +void pshts_add_job_alm2map_spin (pshts_joblist *joblist, + const pshts_cmplx *alm1, const pshts_cmplx *alm2, float *map1, float *map2, + int spin, int add_output); +/*! Adds a new spin map2alm job to \a joblist, which reads data from + \a map1 and \a map2 and writes data to \a alm1 and \a alm2. + \a spin must be 1, 2, or 3. If \a add_output is 0, + the output a_lm will be overwritten, else the result will be added + to the output a_lm. */ +void pshts_add_job_map2alm_spin (pshts_joblist *joblist, const float *map1, + const float *map2, pshts_cmplx *alm1, pshts_cmplx *alm2, int spin, + int add_output); +/*! Adds a new job to \a joblist, which reads data from + \a alm and writes maps of the first derivatives to \a mapdtheta and + \a mapdphi, respectively. If \a add_output is 0, + the output maps will be overwritten, else the result will be added + to the output maps. */ +void pshts_add_job_alm2map_deriv1 (pshts_joblist *joblist, + const pshts_cmplx *alm, float *mapdtheta, float *mapdphi, int add_output); + +/*! Executes the jobs in \a joblist, using \a geom_info as map geometry + and \a alm_info as structure of the a_lm coefficients. + \note The map geometry and the a_lm structure have to be supplied to this + function only, since this information is not needed by PSHT anywhere else. + However, it is the user's responsibility to ensure that the input arrays + (specified by calls to the job-adding functions) are consistent with the + specified geometry and a_lm structure, and that the output arrays are + large enough to hold the produced results. + */ +void pshts_execute_jobs (pshts_joblist *joblist, + const psht_geom_info *geom_info, const psht_alm_info *alm_info); + +/* \} */ + +/*! \defgroup djoblistgroup Functions for dealing with double precision job lists +\note All pointers to maps or a_lm that are passed to the job-adding functions +must not be de-allocated until after the last call of execute_jobs() for +a particular job list! This is because PSHT does not copy the input data, +but only stores the pointers to the supplied maps and a_lm. +*/ +/*! \{ */ + +/*! Creates a new joblist object. */ +void pshtd_make_joblist (pshtd_joblist **joblist); +/*! Removes all jobs in \a joblist. */ +void pshtd_clear_joblist (pshtd_joblist *joblist); +/*! Deallocates the given joblist object. */ +void pshtd_destroy_joblist (pshtd_joblist *joblist); + +/*! Adds a new scalar alm2map job to \a joblist, which reads data from \a alm + and writes data to \a map. If \a add_output is 0, \a map will be + overwritten, else the result will be added to \a map. */ +void pshtd_add_job_alm2map (pshtd_joblist *joblist, const pshtd_cmplx *alm, + double *map, int add_output); +/*! Adds a new scalar map2alm job to \a joblist, which reads data from \a map + and writes data to \a alm. If \a add_output is 0, \a alm will be + overwritten, else the result will be added to \a alm. */ +void pshtd_add_job_map2alm (pshtd_joblist *joblist, const double *map, + pshtd_cmplx *alm, int add_output); +/*! Adds a new polarised alm2map job to \a joblist, which reads data from + \a almT, \a almG and \a almC and writes data to \a mapT, \a mapQ and + \a mapU. If \a add_output is 0, the output maps will be + overwritten, else the result will be added to the output maps. */ +void pshtd_add_job_alm2map_pol (pshtd_joblist *joblist, + const pshtd_cmplx *almT, const pshtd_cmplx *almG, const pshtd_cmplx *almC, + double *mapT, double *mapQ, double *mapU, int add_output); +/*! Adds a new polarised map2alm job to \a joblist, which reads data from + \a mapT, \a mapQ and \a mapU and writes data to \a almT, \a almG and + \a almC. If \a add_output is 0, the output a_lm will be + overwritten, else the result will be added to the output a_lm. */ +void pshtd_add_job_map2alm_pol (pshtd_joblist *joblist, + const double *mapT, const double *mapQ, const double *mapU, + pshtd_cmplx *almT, pshtd_cmplx *almG, pshtd_cmplx *almC, int add_output); +/*! Adds a new spin alm2map job to \a joblist, which reads data from + \a alm1 and \a alm2 and writes data to \a map1 and map2. + \a spin must be 1, 2, or 3. If \a add_output is 0, + the output maps will be overwritten, else the result will be + added to the output maps. */ +void pshtd_add_job_alm2map_spin (pshtd_joblist *joblist, + const pshtd_cmplx *alm1, const pshtd_cmplx *alm2, double *map1, double *map2, + int spin, int add_output); +/*! Adds a new spin map2alm job to \a joblist, which reads data from + \a map1 and \a map2 and writes data to \a alm1 and \a alm2. + \a spin must be 1, 2, or 3. If \a add_output is 0, + the output a_lm will be overwritten, else the result will be added + to the output a_lm. */ +void pshtd_add_job_map2alm_spin (pshtd_joblist *joblist, const double *map1, + const double *map2, pshtd_cmplx *alm1, pshtd_cmplx *alm2, int spin, + int add_output); +/*! Adds a new job to \a joblist, which reads data from + \a alm and writes maps of the first derivatives to \a mapdtheta and + \a mapdphi, respectively. If \a add_output is 0, + the output maps will be overwritten, else the result will be added + to the output maps. */ +void pshtd_add_job_alm2map_deriv1 (pshtd_joblist *joblist, + const pshtd_cmplx *alm, double *mapdtheta, double *mapdphi, int add_output); + +/*! Executes the jobs in \a joblist, using \a geom_info as map geometry + and \a alm_info as structure of the a_lm coefficients. + \note The map geometry and the a_lm structure have to be supplied to this + function only, since this information is not needed by PSHT anywhere else. + However, it is the user's responsibility to ensure that the input arrays + (specified by calls to the job-adding functions) are consistent with the + specified geometry and a_lm structure, and that the output arrays are + large enough to hold the produced results. + */ +void pshtd_execute_jobs (pshtd_joblist *joblist, + const psht_geom_info *geom_info, const psht_alm_info *alm_info); + +/* \} */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/external/healpix/libpsht/psht_almhelpers.c b/external/healpix/libpsht/psht_almhelpers.c new file mode 100644 index 0000000..c0b8c81 --- /dev/null +++ b/external/healpix/libpsht/psht_almhelpers.c @@ -0,0 +1,63 @@ +/* + * This file is part of libpsht. + * + * libpsht 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. + * + * libpsht 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 libpsht; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * libpsht is being developed at the Max-Planck-Institut fuer Astrophysik + * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt + * (DLR). + */ + +/*! \file psht_almhelpers.c + * Spherical transform library + * + * Copyright (C) 2008, 2009, 2010 Max-Planck-Society + * \author Martin Reinecke + */ + +#include "psht_almhelpers.h" +#include "c_utils.h" + +void psht_make_triangular_alm_info (int lmax, int mmax, int stride, + psht_alm_info **alm_info) + { + ptrdiff_t m; + int tval; + psht_alm_info *info = RALLOC(psht_alm_info,1); + info->lmax = lmax; + info->mmax = mmax; + info->mstart = RALLOC(ptrdiff_t,mmax+1); + info->stride = stride; + tval = 2*lmax+1; + for (m=0; m<=mmax; ++m) + info->mstart[m] = stride*((m*(tval-m))>>1); + *alm_info = info; + } + +void psht_make_rectangular_alm_info (int lmax, int mmax, int stride, + psht_alm_info **alm_info) + { + ptrdiff_t m; + psht_alm_info *info = RALLOC(psht_alm_info,1); + info->lmax = lmax; + info->mmax = mmax; + info->mstart = RALLOC(ptrdiff_t,mmax+1); + info->stride = stride; + for (m=0; m<=mmax; ++m) + info->mstart[m] = stride*m*(lmax+1); + *alm_info = info; + } diff --git a/external/healpix/libpsht/psht_almhelpers.h b/external/healpix/libpsht/psht_almhelpers.h new file mode 100644 index 0000000..eeed903 --- /dev/null +++ b/external/healpix/libpsht/psht_almhelpers.h @@ -0,0 +1,57 @@ +/* + * This file is part of libpsht. + * + * libpsht 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. + * + * libpsht 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 libpsht; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * libpsht is being developed at the Max-Planck-Institut fuer Astrophysik + * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt + * (DLR). + */ + +/*! \file psht_almhelpers.h + * PSHT helper function for the creation of a_lm data structures + * + * Copyright (C) 2008 Max-Planck-Society + * \author Martin Reinecke + */ + +#ifndef PLANCK_PSHT_ALMHELPERS_H +#define PLANCK_PSHT_ALMHELPERS_H + +#include "psht.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*! Initialises an a_lm data structure according to the scheme used by + Healpix_cxx. + \ingroup almgroup */ +void psht_make_triangular_alm_info (int lmax, int mmax, int stride, + psht_alm_info **alm_info); + +/*! Initialises an a_lm data structure according to the scheme used by + Fortran Healpix + \ingroup almgroup */ +void psht_make_rectangular_alm_info (int lmax, int mmax, int stride, + psht_alm_info **alm_info); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/external/healpix/libpsht/psht_cxx.h b/external/healpix/libpsht/psht_cxx.h new file mode 100644 index 0000000..434dc31 --- /dev/null +++ b/external/healpix/libpsht/psht_cxx.h @@ -0,0 +1,198 @@ +/* + * This file is part of libpsht. + * + * libpsht 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. + * + * libpsht 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 libpsht; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * libpsht is being developed at the Max-Planck-Institut fuer Astrophysik + * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt + * (DLR). + */ + +/*! \file psht_cxx.h + * Spherical transform library + * + * Copyright (C) 2008, 2009 Max-Planck-Society + * \author Martin Reinecke + */ + +#ifndef PLANCK_PSHT_CXX_H +#define PLANCK_PSHT_CXX_H + +#include "psht.h" +#include "psht_geomhelpers.h" +#include "psht_almhelpers.h" +#include "xcomplex.h" + +class psht_base + { + protected: + psht_geom_info *ginfo; + psht_alm_info *ainfo; + + public: + psht_base() + : ginfo(0), ainfo(0) {} + ~psht_base() + { + psht_destroy_geom_info(ginfo); + psht_destroy_alm_info(ainfo); + } + + void set_general_geometry (int nrings, const int *nph, const ptrdiff_t *ofs, + const int *stride, const double *phi0, const double *theta, + const double *weight) + { + psht_make_geom_info (nrings, nph, ofs, stride, phi0, theta, weight, + &ginfo); + } + + void set_ECP_geometry (int nrings, int nphi) + { psht_make_ecp_geom_info (nrings, nphi, 0., 1, &ginfo); } + + void set_Healpix_geometry (int nside) + { psht_make_healpix_geom_info (nside, 1, &ginfo); } + + void set_weighted_Healpix_geometry (int nside, const double *weight) + { psht_make_weighted_healpix_geom_info (nside, 1, weight, &ginfo); } + + void set_triangular_alm_info (int lmax, int mmax) + { psht_make_triangular_alm_info (lmax, mmax, 1, &ainfo); } + }; + +template class psht_joblist + {}; + +template<> class psht_joblist: public psht_base + { + private: + pshts_joblist *jobs; + + static pshts_cmplx *conv (xcomplex *ptr) + { return reinterpret_cast(ptr); } + static const pshts_cmplx *conv (const xcomplex *ptr) + { return reinterpret_cast(ptr); } + + public: + psht_joblist() + { pshts_make_joblist (&jobs); } + ~psht_joblist() + { pshts_destroy_joblist (jobs); } + + void clear_jobs() + { pshts_clear_joblist (jobs); } + + void add_alm2map (const xcomplex *alm, float *map, bool add) + { pshts_add_job_alm2map (jobs, conv(alm), map, add); } + void add_map2alm (const float *map, xcomplex *alm, bool add) + { pshts_add_job_map2alm (jobs, map, conv(alm), add); } + void add_alm2map_pol (const xcomplex *almT, + const xcomplex *almG, const xcomplex *almC, + float *mapT, float *mapQ, float *mapU, bool add) + { + pshts_add_job_alm2map_pol (jobs, conv(almT), conv(almG), conv(almC), + mapT, mapQ, mapU, add); + } + void add_map2alm_pol (const float *mapT, const float *mapQ, + const float *mapU, xcomplex *almT, xcomplex *almG, + xcomplex *almC, bool add) + { + pshts_add_job_map2alm_pol (jobs, mapT, mapQ, mapU, conv(almT), + conv(almG), conv(almC), add); + } + void add_alm2map_spin (const xcomplex *alm1, + const xcomplex *alm2, float *map1, float *map2, int spin, bool add) + { + pshts_add_job_alm2map_spin (jobs, conv(alm1), conv(alm2), map1, map2, + spin, add); + } + void add_map2alm_spin (const float *map1, const float *map2, + xcomplex *alm1, xcomplex *alm2, int spin, bool add) + { + pshts_add_job_map2alm_spin (jobs, map1, map2, conv(alm1), conv(alm2), + spin, add); + } + void add_alm2map_der1 (const xcomplex *alm, float *mapdth, + float *mapdph, bool add) + { + pshts_add_job_alm2map_deriv1 (jobs, conv(alm), mapdth, mapdph, add); + } + + void execute() + { pshts_execute_jobs (jobs,ginfo,ainfo); } + }; + +template<> class psht_joblist: public psht_base + { + private: + pshtd_joblist *jobs; + + static pshtd_cmplx *conv (xcomplex *ptr) + { return reinterpret_cast(ptr); } + static const pshtd_cmplx *conv (const xcomplex *ptr) + { return reinterpret_cast(ptr); } + + public: + psht_joblist() + { pshtd_make_joblist (&jobs); } + ~psht_joblist() + { pshtd_destroy_joblist (jobs); } + + void clear_jobs() + { pshtd_clear_joblist (jobs); } + + void add_alm2map (const xcomplex *alm, double *map, bool add) + { pshtd_add_job_alm2map (jobs, conv(alm), map, add); } + void add_map2alm (const double *map, xcomplex *alm, bool add) + { pshtd_add_job_map2alm (jobs, map, conv(alm), add); } + void add_alm2map_pol (const xcomplex *almT, + const xcomplex *almG, const xcomplex *almC, + double *mapT, double *mapQ, double *mapU, bool add) + { + pshtd_add_job_alm2map_pol (jobs, conv(almT), conv(almG), conv(almC), + mapT, mapQ, mapU, add); + } + void add_map2alm_pol (const double *mapT, const double *mapQ, + const double *mapU, xcomplex *almT, xcomplex *almG, + xcomplex *almC, bool add) + { + pshtd_add_job_map2alm_pol (jobs, mapT, mapQ, mapU, conv(almT), + conv(almG), conv(almC), add); + } + void add_alm2map_spin (const xcomplex *alm1, + const xcomplex *alm2, double *map1, double *map2, int spin, + bool add) + { + pshtd_add_job_alm2map_spin (jobs, conv(alm1), conv(alm2), map1, map2, + spin, add); + } + void add_map2alm_spin (const double *map1, const double *map2, + xcomplex *alm1, xcomplex *alm2, int spin, bool add) + { + pshtd_add_job_map2alm_spin (jobs, map1, map2, conv(alm1), conv(alm2), + spin, add); + } + void add_alm2map_der1 (const xcomplex *alm, double *mapdth, + double *mapdph, bool add) + { + pshtd_add_job_alm2map_deriv1 (jobs, conv(alm), mapdth, mapdph, add); + } + + void execute() + { pshtd_execute_jobs (jobs,ginfo,ainfo); } + }; + +#endif diff --git a/external/healpix/libpsht/psht_geomhelpers.c b/external/healpix/libpsht/psht_geomhelpers.c new file mode 100644 index 0000000..d6ab6d6 --- /dev/null +++ b/external/healpix/libpsht/psht_geomhelpers.c @@ -0,0 +1,229 @@ +/* + * This file is part of libpsht. + * + * libpsht 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. + * + * libpsht 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 libpsht; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * libpsht is being developed at the Max-Planck-Institut fuer Astrophysik + * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt + * (DLR). + */ + +/*! \file psht_geomhelpers.c + * Spherical transform library + * + * Copyright (C) 2006-2010 Max-Planck-Society + * \author Martin Reinecke + */ + +#include +#include "psht_geomhelpers.h" +#include "c_utils.h" + +void psht_make_healpix_geom_info (int nside, int stride, + psht_geom_info **geom_info) + { + double *weight=RALLOC(double,2*nside); + SET_ARRAY(weight,0,2*nside,1); + psht_make_weighted_healpix_geom_info (nside, stride, weight, geom_info); + DEALLOC(weight); + } + +void psht_make_weighted_healpix_geom_info (int nside, int stride, + const double *weight, psht_geom_info **geom_info) + { + const double pi=3.141592653589793238462643383279502884197; + ptrdiff_t npix=(ptrdiff_t)nside*nside*12; + ptrdiff_t ncap=2*(ptrdiff_t)nside*(nside-1); + int nrings=4*nside-1; + + double *theta=RALLOC(double,nrings); + double *weight_=RALLOC(double,nrings); + int *nph=RALLOC(int,nrings); + double *phi0=RALLOC(double,nrings); + ptrdiff_t *ofs=RALLOC(ptrdiff_t,nrings); + int *stride_=RALLOC(int,nrings); + int m; + for (m=0; m2*nside) ? 4*nside-ring : ring; + stride_[m] = stride; + if (northring < nside) + { + theta[m] = 2*asin(northring/(sqrt(6.)*nside)); + nph[m] = 4*northring; + phi0[m] = pi/nph[m]; + ofs[m] = 2*northring*(northring-1); + } + else + { + double fact1 = (8.*nside)/npix; + double costheta = (2*nside-northring)*fact1; + theta[m] = acos(costheta); + nph[m] = 4*nside; + if ((northring-nside) & 1) + phi0[m] = 0; + else + phi0[m] = pi/nph[m]; + ofs[m] = ncap + (northring-nside)*nph[m]; + } + if (northring != ring) /* southern hemisphere */ + { + theta[m] = pi-theta[m]; + ofs[m] = npix - nph[m] - ofs[m]; + } + weight_[m]=4.*pi/npix*weight[northring-1]; + } + + psht_make_geom_info (nrings, nph, ofs, stride_, phi0, theta, weight_, + geom_info); + + DEALLOC(theta); + DEALLOC(weight_); + DEALLOC(nph); + DEALLOC(phi0); + DEALLOC(ofs); + DEALLOC(stride_); + } + +static void gauleg (double x1, double x2, double *x, double *w, int n) + { + const double pi = 3.141592653589793238462643383279502884197; + const double eps = 3.0E-14; + + int m = (n+1)/2; + double xm = 0.5*(x2+x1); + double xl = 0.5*(x2-x1); + int i; + for(i=1; i<=m; ++i) + { + double z = cos(pi*(i-0.25)/(n+0.5)); + double pp; + int dobreak=0; + while(1) + { + double p1 = 1.0, p2 = 0.0; + double z1 = z; + int j; + for(j=1; j<=n; ++j) + { + double p3 = p2; + p2 = p1; + p1 = ((2*j-1)*z*p2-(j-1)*p3)/j; + } + pp = n*(z*p1-p2)/(z*z-1); + z = z1 - p1/pp; + if (dobreak) break; + if (fabs(z-z1) <= eps) dobreak=1; + } + x[i-1] = xm - xl*z; + x[n-i] = xm + xl*z; + w[i-1] = w[n-i] = 2*xl/((1-z*z)*pp*pp); + } + } + +static void makeweights (int bw, double *weights) + { + const double pi = 3.141592653589793238462643383279502884197; + const double fudge = pi/(4*bw); + int j; + for (j=0; j<2*bw; ++j) + { + double tmpsum = 0; + int k; + for (k=0; knph; + FLT *ring = data + info->ofs; + int stride = info->stride; + + ringhelper_update (self, nph, mmax, info->phi0); + self->work[0]=phase[0]; + SET_ARRAY(self->work,1,nph,pshtd_cmplx_null); + + if (self->norot) + for (m=1; m<=mmax; ++m) + { + int idx1 = m%nph; + int idx2 = nph-1-((m-1)%nph); + self->work[idx1].re += phase[m].re; self->work[idx1].im += phase[m].im; + self->work[idx2].re += phase[m].re; self->work[idx2].im -= phase[m].im; + } + else + for (m=1; m<=mmax; ++m) + { + int idx1 = m%nph; + int idx2 = nph-1-((m-1)%nph); + pshtd_cmplx tmp; + COMPMUL_(tmp,phase[m],self->shiftarr[m]); + self->work[idx1].re += tmp.re; self->work[idx1].im += tmp.im; + self->work[idx2].re += tmp.re; self->work[idx2].im -= tmp.im; + } + real_plan_backward_c (self->plan, &self->work[0].re); + for (m=0; mwork[m].re; + } + +static void X(ringhelper_ring2phase) (ringhelper *self, + const psht_ringinfo *info, const FLT *data, int mmax, pshtd_cmplx *phase) + { + int m; + int nph = info->nph; + int maxidx = IMIN(nph-1,mmax); +/* Enable this for traditional Healpix compatibility */ +#if 1 + maxidx = mmax; +#endif + + ringhelper_update (self, nph, mmax, -info->phi0); + for (m=0; mwork[m].re = data[info->ofs+m*info->stride]*info->weight; + self->work[m].im = 0; + } + + real_plan_forward_c (self->plan, &self->work[0].re); + + if (self->norot) + for (m=0; m<=maxidx; ++m) + phase[m] = self->work[m%nph]; + else + for (m=0; m<=maxidx; ++m) + COMPMUL_(phase[m],self->work[m%nph],self->shiftarr[m]); + + SET_ARRAY(phase,maxidx+1,mmax+1,pshtd_cmplx_null); + } + +static void X(ringhelper_pair2phase) (ringhelper *self, int mmax, + const psht_ringpair *pair, const FLT *data, + pshtd_cmplx *phase1, pshtd_cmplx *phase2) + { + if (pair->r1.nph>0) + X(ringhelper_ring2phase) (self, &(pair->r1), data, mmax, phase1); + if (pair->r2.nph>0) + X(ringhelper_ring2phase) (self, &(pair->r2), data, mmax, phase2); + } + +static void X(ringhelper_phase2pair) (ringhelper *self, int mmax, + const pshtd_cmplx *phase1, const pshtd_cmplx *phase2, + const psht_ringpair *pair, FLT *data) + { + if (pair->r1.nph>0) + X(ringhelper_phase2ring) (self, &(pair->r1), data, mmax, phase1); + if (pair->r2.nph>0) + X(ringhelper_phase2ring) (self, &(pair->r2), data, mmax, phase2); + } + + +static void X(fill_map) (const psht_geom_info *ginfo, FLT *map, double value) + { + int i,j; + for (j=0;jnpairs;++j) + { + for (i=0;ipair[j].r1.nph;++i) + map[ginfo->pair[j].r1.ofs+i*ginfo->pair[j].r1.stride]=(FLT)value; + for (i=0;ipair[j].r2.nph;++i) + map[ginfo->pair[j].r2.ofs+i*ginfo->pair[j].r2.stride]=(FLT)value; + } + } + +static void X(fill_alm) (const psht_alm_info *ainfo, X(cmplx) *alm, + X(cmplx) value) + { + int l,m; + for (m=0;m<=ainfo->mmax;++m) + for (l=m;l<=ainfo->lmax;++l) + alm[ainfo->mstart[m]+l*ainfo->stride] = value; + } + +static void X(init_output) (X(joblist) *jobs, const psht_geom_info *ginfo, + const psht_alm_info *alm) + { + int ijob,i; + for (ijob=0; ijobnjobs; ++ijob) + { + X(job) *curjob = &jobs->job[ijob]; + if (!curjob->add_output) + switch (curjob->type) + { + case MAP2ALM: + for (i=0; inalm; ++i) + X(fill_alm) (alm,curjob->alm[i],X(cmplx_null)); + break; + case ALM2MAP: + case ALM2MAP_DERIV1: + for (i=0; inmaps; ++i) + X(fill_map) (ginfo,curjob->map[i],0); + break; + default: + break; + } + } + } + +static void X(alloc_phase) (X(joblist) *jobs, int mmax, int chunksize) + { + int ijob,i; + for (ijob=0; ijobnjobs; ++ijob) + { + X(job) *curjob = &jobs->job[ijob]; + for (i=0; inmaps; ++i) + { + curjob->phas1[i]=RALLOC(pshtd_cmplx,(mmax+1)*chunksize); + curjob->phas2[i]=RALLOC(pshtd_cmplx,(mmax+1)*chunksize); + } + } + } + +static void X(dealloc_phase) (X(joblist) *jobs) + { + int ijob,i; + for (ijob=0; ijobnjobs; ++ijob) + { + X(job) *curjob = &jobs->job[ijob]; + for (i=0; inmaps; ++i) + { DEALLOC(curjob->phas1[i]); DEALLOC(curjob->phas2[i]); } + } + } + +static void X(map2phase) (X(joblist) *jobs, const psht_geom_info *ginfo, + int mmax, int llim, int ulim) + { +#pragma omp parallel +{ + ringhelper helper; + int ith; + ringhelper_init(&helper); +#pragma omp for schedule(dynamic,1) + for (ith=llim; ithnjobs; ++ijob) + { + X(job) *curjob = &jobs->job[ijob]; + switch (curjob->type) + { + case MAP2ALM: + for (i=0; inmaps; ++i) + X(ringhelper_pair2phase)(&helper,mmax,&ginfo->pair[ith], + curjob->map[i], &curjob->phas1[i][dim2], &curjob->phas2[i][dim2]); + break; + default: + break; + } + } + } + ringhelper_destroy(&helper); +} /* end of parallel region */ + } + +static void X(alloc_almtmp) (X(joblist) *jobs, int lmax) + { + int ijob,i; + for (ijob=0; ijobnjobs; ++ijob) + { + X(job) *curjob = &jobs->job[ijob]; + for (i=0; inalm; ++i) +#ifdef PLANCK_HAVE_SSE2 + if (curjob->spin==0) + curjob->alm_tmp.v[i]=RALLOC(v2df,lmax+1); + else + curjob->alm_tmp.v2[i]=RALLOC(v2df2,lmax+1); +#else + curjob->alm_tmp.c[i]=RALLOC(pshtd_cmplx,lmax+1); +#endif + } + } + +static void X(dealloc_almtmp) (X(joblist) *jobs) + { + int ijob,i; + for (ijob=0; ijobnjobs; ++ijob) + { + X(job) *curjob = &jobs->job[ijob]; + for (i=0; inalm; ++i) +#ifdef PLANCK_HAVE_SSE2 + if (curjob->spin==0) + DEALLOC(curjob->alm_tmp.v[i]); + else + DEALLOC(curjob->alm_tmp.v2[i]); +#else + DEALLOC(curjob->alm_tmp.c[i]); +#endif + } + } + +static void X(alm2almtmp) (X(joblist) *jobs, int lmax, int m, + const psht_alm_info *alm) + { + int ijob,i,l; + for (ijob=0; ijobnjobs; ++ijob) + { + X(job) *curjob = &jobs->job[ijob]; + switch (curjob->type) + { + case ALM2MAP: + { + const double *norm_l = curjob->norm_l; + for (i=0; inalm; ++i) + { + X(cmplx) *curalm = curjob->alm[i]; + for (l=m; l<=lmax; ++l) + { + ptrdiff_t aidx = psht_alm_index(alm,l,m); +#ifdef PLANCK_HAVE_SSE2 + if (curjob->spin==0) + curjob->alm_tmp.v[i][l] = build_v2df(curalm[aidx].re*norm_l[l], + curalm[aidx].im*norm_l[l]); + else + { + curjob->alm_tmp.v2[i][l].a = _mm_set1_pd(curalm[aidx].re*norm_l[l]); + curjob->alm_tmp.v2[i][l].b = _mm_set1_pd(curalm[aidx].im*norm_l[l]); + } +#else + curjob->alm_tmp.c[i][l].re = curalm[aidx].re*norm_l[l]; + curjob->alm_tmp.c[i][l].im = curalm[aidx].im*norm_l[l]; +#endif + } + } + break; + } + case ALM2MAP_DERIV1: + { + const double *norm_l = curjob->norm_l; + for (i=0; inalm; ++i) + { + X(cmplx) *curalm = curjob->alm[i]; + for (l=m; l<=lmax; ++l) + { + ptrdiff_t aidx = psht_alm_index(alm,l,m); + double fct = fabs(norm_l[l])*sqrt(l*(l+1.)); +#ifdef PLANCK_HAVE_SSE2 + curjob->alm_tmp.v2[i][l].a = _mm_set1_pd(-curalm[aidx].re*fct); + curjob->alm_tmp.v2[i][l].b = _mm_set1_pd(-curalm[aidx].im*fct); +#else + curjob->alm_tmp.c[i][l].re = -curalm[aidx].re*fct; + curjob->alm_tmp.c[i][l].im = -curalm[aidx].im*fct; +#endif + } + } + break; + } + case MAP2ALM: + for (i=0; inalm; ++i) + { +#ifdef PLANCK_HAVE_SSE2 + if (curjob->spin==0) + SET_ARRAY(curjob->alm_tmp.v[i],m,lmax+1,_mm_setzero_pd()); + else + SET_ARRAY(curjob->alm_tmp.v2[i],m,lmax+1,zero_v2df2()); +#else + SET_ARRAY(curjob->alm_tmp.c[i],m,lmax+1,pshtd_cmplx_null); +#endif + } + break; + default: + break; + } + } + } + + +#ifdef PLANCK_HAVE_SSE2 + +#define ALM2MAP_MACRO(px) \ + { \ + v2df ar=_mm_shuffle_pd(almtmp[l],almtmp[l],_MM_SHUFFLE2(0,0)), \ + ai=_mm_shuffle_pd(almtmp[l],almtmp[l],_MM_SHUFFLE2(1,1)); \ + px.a=_mm_add_pd(px.a,_mm_mul_pd(ar,Ylm[l])); \ + px.b=_mm_add_pd(px.b,_mm_mul_pd(ai,Ylm[l])); \ + ++l; \ + } + +#define ALM2MAP_SPIN_MACRO(Qx,Qy,Ux,Uy) \ + { \ + const v2df lw = lwx[l].a, lx = lwx[l].b; \ + Qx.a=_mm_add_pd(Qx.a,_mm_mul_pd(almtmpG[l].a,lw)); \ + Uy.b=_mm_sub_pd(Uy.b,_mm_mul_pd(almtmpG[l].a,lx)); \ + Qx.b=_mm_add_pd(Qx.b,_mm_mul_pd(almtmpG[l].b,lw)); \ + Uy.a=_mm_add_pd(Uy.a,_mm_mul_pd(almtmpG[l].b,lx)); \ + Ux.a=_mm_add_pd(Ux.a,_mm_mul_pd(almtmpC[l].a,lw)); \ + Qy.b=_mm_add_pd(Qy.b,_mm_mul_pd(almtmpC[l].a,lx)); \ + Ux.b=_mm_add_pd(Ux.b,_mm_mul_pd(almtmpC[l].b,lw)); \ + Qy.a=_mm_sub_pd(Qy.a,_mm_mul_pd(almtmpC[l].b,lx)); \ + ++l; \ + } + +#define ALM2MAP_DERIV1_MACRO(Qx,Uy) \ + { \ + const v2df lw = lwx[l].a, lx = lwx[l].b; \ + Qx.a = _mm_add_pd(Qx.a,_mm_mul_pd(almtmp[l].a,lw)); \ + Uy.b = _mm_sub_pd(Uy.b,_mm_mul_pd(almtmp[l].a,lx)); \ + Qx.b = _mm_add_pd(Qx.b,_mm_mul_pd(almtmp[l].b,lw)); \ + Uy.a = _mm_add_pd(Uy.a,_mm_mul_pd(almtmp[l].b,lx)); \ + ++l; \ + } + +#ifdef PLANCK_HAVE_SSE3 +#define MAP2ALM_MACRO(px) \ + { \ + const v2df t1_ = _mm_mul_pd(px.a,Ylm[l]), t2_ = _mm_mul_pd(px.b,Ylm[l]); \ + const v2df t5_=_mm_hadd_pd(t1_,t2_);\ + almtmp[l] = _mm_add_pd(almtmp[l],t5_); \ + ++l; \ + } +#else +#define MAP2ALM_MACRO(px) \ + { \ + const v2df t1_ = _mm_mul_pd(px.a,Ylm[l]), t2_ = _mm_mul_pd(px.b,Ylm[l]); \ + const v2df t3_ = _mm_shuffle_pd(t1_,t2_,_MM_SHUFFLE2(0,0)), \ + t4_ = _mm_shuffle_pd(t1_,t2_,_MM_SHUFFLE2(1,1)); \ + const v2df t5_=_mm_add_pd(t3_,t4_);\ + almtmp[l] = _mm_add_pd(almtmp[l],t5_); \ + ++l; \ + } +#endif + +#define MAP2ALM_SPIN_MACRO(Qx,Qy,Ux,Uy) \ + { \ + const v2df lw = lwx[l].a, lx = lwx[l].b; \ + almtmpG[l].a=_mm_add_pd(almtmpG[l].a, \ + _mm_sub_pd(_mm_mul_pd(Qx.a,lw),_mm_mul_pd(Uy.b,lx))); \ + almtmpG[l].b=_mm_add_pd(almtmpG[l].b, \ + _mm_add_pd(_mm_mul_pd(Qx.b,lw),_mm_mul_pd(Uy.a,lx))); \ + almtmpC[l].a=_mm_add_pd(almtmpC[l].a, \ + _mm_add_pd(_mm_mul_pd(Ux.a,lw),_mm_mul_pd(Qy.b,lx))); \ + almtmpC[l].b=_mm_add_pd(almtmpC[l].b, \ + _mm_sub_pd(_mm_mul_pd(Ux.b,lw),_mm_mul_pd(Qy.a,lx))); \ + ++l; \ + } + +#define EXTRACT(pa,pb,pha,phb,phc,phd) \ + { \ + read_v2df (_mm_add_pd(pa.a,pb.a), &pha->re, &phc->re); \ + read_v2df (_mm_sub_pd(pa.a,pb.a), &phb->re, &phd->re); \ + read_v2df (_mm_add_pd(pa.b,pb.b), &pha->im, &phc->im); \ + read_v2df (_mm_sub_pd(pa.b,pb.b), &phb->im, &phd->im); \ + } + +#define COMPOSE(pa,pb,pha,phb,phc,phd) \ + { \ + pa.a = build_v2df(pha.re+phb.re,phc.re+phd.re); \ + pa.b = build_v2df(pha.im+phb.im,phc.im+phd.im); \ + pb.a = build_v2df(pha.re-phb.re,phc.re-phd.re); \ + pb.b = build_v2df(pha.im-phb.im,phc.im-phd.im); \ + } + +static void X(inner_loop) (X(joblist) *jobs, const psht_geom_info *ginfo, + int lmax, int mmax, int llim, int ulim, Ylmgen_C *generator, int m) + { + const v2df2 v2df2_zero = zero_v2df2(); + int ith,ijob; + for (ith=0; ithpair[ith+llim].r2.nph>0, + rpair2 = dual && (ginfo->pair[ith+1+llim].r2.nph>0); + int phas_idx1 = ith *(mmax+1)+m, + phas_idx2 = (ith+1)*(mmax+1)+m; + Ylmgen_prepare_sse2(generator,ith,dual?(ith+1):ith,m); + + for (ijob=0; ijobnjobs; ++ijob) + { + X(job) *curjob = &jobs->job[ijob]; + switch (curjob->type) + { + case ALM2MAP: + { + switch (curjob->spin) + { + case 0: + { + pshtd_cmplx *ph1 = &curjob->phas1[0][phas_idx1], + *ph2 = rpair1 ? &curjob->phas2[0][phas_idx1] : &dum, + *ph3 = dual ? &curjob->phas1[0][phas_idx2] : &dum, + *ph4 = rpair2 ? &curjob->phas2[0][phas_idx2] : &dum; + *ph1 = *ph2 = *ph3 = *ph4 = pshtd_cmplx_null; + Ylmgen_recalc_Ylm_sse2 (generator); + if (generator->firstl[0]<=lmax) + { + int l = generator->firstl[0]; + v2df2 p1=v2df2_zero, p2=v2df2_zero; + const v2df *Ylm = generator->ylm_sse2; + const v2df *almtmp = curjob->alm_tmp.v[0]; + + if ((l-m)&1) + ALM2MAP_MACRO(p2) + for (;lphas1[0][phas_idx1], + *ph1U = &curjob->phas1[1][phas_idx1], + *ph2Q = rpair1 ? &curjob->phas2[0][phas_idx1] : &dum, + *ph2U = rpair1 ? &curjob->phas2[1][phas_idx1] : &dum, + *ph3Q = dual ? &curjob->phas1[0][phas_idx2] : &dum, + *ph3U = dual ? &curjob->phas1[1][phas_idx2] : &dum, + *ph4Q = rpair2 ? &curjob->phas2[0][phas_idx2] : &dum, + *ph4U = rpair2 ? &curjob->phas2[1][phas_idx2] : &dum; + *ph1Q = *ph2Q = *ph1U = *ph2U = *ph3Q = *ph4Q = *ph3U = *ph4U + = pshtd_cmplx_null; + Ylmgen_recalc_lambda_wx_sse2 (generator,curjob->spin); + if (generator->firstl[curjob->spin]<=lmax) + { + int l = generator->firstl[curjob->spin]; + v2df2 p1Q=v2df2_zero, p2Q=v2df2_zero, + p1U=v2df2_zero, p2U=v2df2_zero; + const v2df2 *lwx = generator->lambda_wx_sse2[curjob->spin]; + const v2df2 *almtmpG = curjob->alm_tmp.v2[0], + *almtmpC = curjob->alm_tmp.v2[1]; + + if ((l-m+curjob->spin)&1) + ALM2MAP_SPIN_MACRO(p2Q,p1Q,p2U,p1U) + for (;lphas1[0][phas_idx1], + *ph1U = &curjob->phas1[1][phas_idx1], + *ph2Q = rpair1 ? &curjob->phas2[0][phas_idx1] : &dum, + *ph2U = rpair1 ? &curjob->phas2[1][phas_idx1] : &dum, + *ph3Q = dual ? &curjob->phas1[0][phas_idx2] : &dum, + *ph3U = dual ? &curjob->phas1[1][phas_idx2] : &dum, + *ph4Q = rpair2 ? &curjob->phas2[0][phas_idx2] : &dum, + *ph4U = rpair2 ? &curjob->phas2[1][phas_idx2] : &dum; + *ph1Q = *ph2Q = *ph1U = *ph2U = *ph3Q = *ph4Q = *ph3U = *ph4U + = pshtd_cmplx_null; + Ylmgen_recalc_lambda_wx_sse2 (generator,1); + if (generator->firstl[1]<=lmax) + { + int l = generator->firstl[1]; + v2df2 p1Q=v2df2_zero, p2Q=v2df2_zero, + p1U=v2df2_zero, p2U=v2df2_zero; + const v2df2 *lwx = generator->lambda_wx_sse2[1]; + const v2df2 *almtmp = curjob->alm_tmp.v2[0]; + + if ((l-m+1)&1) + ALM2MAP_DERIV1_MACRO(p2Q,p1U) + for (;lspin) + { + case 0: + { + Ylmgen_recalc_Ylm_sse2 (generator); + if (generator->firstl[0]<=lmax) + { + int l = generator->firstl[0]; + const v2df *Ylm = generator->ylm_sse2; + v2df *almtmp = curjob->alm_tmp.v[0]; + pshtd_cmplx + ph1 = curjob->phas1[0][phas_idx1], + ph2 = rpair1 ? curjob->phas2[0][phas_idx1] : pshtd_cmplx_null, + ph3 = dual ? curjob->phas1[0][phas_idx2] : pshtd_cmplx_null, + ph4 = rpair2 ? curjob->phas2[0][phas_idx2] : pshtd_cmplx_null; + v2df2 p1,p2; + COMPOSE (p1,p2,ph1,ph2,ph3,ph4) + + if ((l-m)&1) + MAP2ALM_MACRO(p2) + for (;lspin); + if (generator->firstl[curjob->spin]<=lmax) + { + int l = generator->firstl[curjob->spin]; + const v2df2 *lwx = generator->lambda_wx_sse2[curjob->spin]; + v2df2 *almtmpG = curjob->alm_tmp.v2[0], + *almtmpC = curjob->alm_tmp.v2[1]; + pshtd_cmplx + ph1Q = curjob->phas1[0][phas_idx1], + ph1U = curjob->phas1[1][phas_idx1], + ph2Q = rpair1 ? curjob->phas2[0][phas_idx1] :pshtd_cmplx_null, + ph2U = rpair1 ? curjob->phas2[1][phas_idx1] :pshtd_cmplx_null, + ph3Q = dual ? curjob->phas1[0][phas_idx2] :pshtd_cmplx_null, + ph3U = dual ? curjob->phas1[1][phas_idx2] :pshtd_cmplx_null, + ph4Q = rpair2 ? curjob->phas2[0][phas_idx2] :pshtd_cmplx_null, + ph4U = rpair2 ? curjob->phas2[1][phas_idx2] :pshtd_cmplx_null; + v2df2 p1Q, p2Q, p1U, p2U; + COMPOSE (p1Q,p2Q,ph1Q,ph2Q,ph3Q,ph4Q) + COMPOSE (p1U,p2U,ph1U,ph2U,ph3U,ph4U) + + if ((l-m+curjob->spin)&1) + MAP2ALM_SPIN_MACRO(p2Q,p1Q,p2U,p1U) + for (;lpair[ith+llim].r2.nph>0; + int phas_idx = ith*(mmax+1)+m; + Ylmgen_prepare(generator,ith,m); + + for (ijob=0; ijobnjobs; ++ijob) + { + X(job) *curjob = &jobs->job[ijob]; + switch (curjob->type) + { + case ALM2MAP: + { + switch (curjob->spin) + { + case 0: + { + pshtd_cmplx *ph1 = &curjob->phas1[0][phas_idx], + *ph2 = rpair ? &curjob->phas2[0][phas_idx] : &dum; + *ph1 = *ph2 = pshtd_cmplx_null; + Ylmgen_recalc_Ylm (generator); + if (generator->firstl[0]<=lmax) + { + int l = generator->firstl[0]; + pshtd_cmplx p1=pshtd_cmplx_null,p2=pshtd_cmplx_null; + const double *Ylm = generator->ylm; + const pshtd_cmplx *almtmp = curjob->alm_tmp.c[0]; + + if ((l-m)&1) + ALM2MAP_MACRO(p2) + for (;lre = p1.re+p2.re; ph1->im = p1.im+p2.im; + ph2->re = p1.re-p2.re; ph2->im = p1.im-p2.im; + } + break; + } + + default: + { + pshtd_cmplx *ph1Q = &curjob->phas1[0][phas_idx], + *ph1U = &curjob->phas1[1][phas_idx], + *ph2Q = rpair ? &curjob->phas2[0][phas_idx] : &dum, + *ph2U = rpair ? &curjob->phas2[1][phas_idx] : &dum; + *ph1Q = *ph2Q = *ph1U = *ph2U = pshtd_cmplx_null; + Ylmgen_recalc_lambda_wx (generator,curjob->spin); + if (generator->firstl[curjob->spin]<=lmax) + { + int l = generator->firstl[curjob->spin]; + pshtd_cmplx p1Q=pshtd_cmplx_null,p2Q=pshtd_cmplx_null, + p1U=pshtd_cmplx_null,p2U=pshtd_cmplx_null; + ylmgen_dbl2 *lwx = generator->lambda_wx[curjob->spin]; + const pshtd_cmplx *almtmpG = curjob->alm_tmp.c[0], + *almtmpC = curjob->alm_tmp.c[1]; + + if ((l-m+curjob->spin)&1) + ALM2MAP_SPIN_MACRO(p2Q,p1Q,p2U,p1U) + for (;lre = p1Q.re+p2Q.re; ph1Q->im = p1Q.im+p2Q.im; + ph1U->re = p1U.re+p2U.re; ph1U->im = p1U.im+p2U.im; + ph2Q->re = p1Q.re-p2Q.re; ph2Q->im = p1Q.im-p2Q.im; + ph2U->re = p1U.re-p2U.re; ph2U->im = p1U.im-p2U.im; + } + break; + } + } + break; + } + case ALM2MAP_DERIV1: + { + pshtd_cmplx *ph1Q = &curjob->phas1[0][phas_idx], + *ph1U = &curjob->phas1[1][phas_idx], + *ph2Q = rpair ? &curjob->phas2[0][phas_idx] : &dum, + *ph2U = rpair ? &curjob->phas2[1][phas_idx] : &dum; + *ph1Q = *ph2Q = *ph1U = *ph2U = pshtd_cmplx_null; + Ylmgen_recalc_lambda_wx (generator,1); + if (generator->firstl[1]<=lmax) + { + int l = generator->firstl[1]; + pshtd_cmplx p1Q=pshtd_cmplx_null,p2Q=pshtd_cmplx_null, + p1U=pshtd_cmplx_null,p2U=pshtd_cmplx_null; + ylmgen_dbl2 *lwx = generator->lambda_wx[1]; + const pshtd_cmplx *almtmp = curjob->alm_tmp.c[0]; + + if ((l-m+1)&1) + ALM2MAP_DERIV1_MACRO(p2Q,p1U) + for (;lre = p1Q.re+p2Q.re; ph1Q->im = p1Q.im+p2Q.im; + ph1U->re = p1U.re+p2U.re; ph1U->im = p1U.im+p2U.im; + ph2Q->re = p1Q.re-p2Q.re; ph2Q->im = p1Q.im-p2Q.im; + ph2U->re = p1U.re-p2U.re; ph2U->im = p1U.im-p2U.im; + } + break; + } + case MAP2ALM: + { + switch (curjob->spin) + { + case 0: + { + Ylmgen_recalc_Ylm (generator); + if (generator->firstl[0]<=lmax) + { + int l = generator->firstl[0]; + const double *Ylm = generator->ylm; + pshtd_cmplx *almtmp = curjob->alm_tmp.c[0]; + const pshtd_cmplx + ph1 = curjob->phas1[0][phas_idx], + ph2 = rpair ? curjob->phas2[0][phas_idx] : pshtd_cmplx_null; + pshtd_cmplx p1,p2; + p1.re = ph1.re+ph2.re; p1.im = ph1.im+ph2.im; + p2.re = ph1.re-ph2.re; p2.im = ph1.im-ph2.im; + + if ((l-m)&1) + MAP2ALM_MACRO(p2) + for (;lspin); + if (generator->firstl[curjob->spin]<=lmax) + { + int l = generator->firstl[curjob->spin]; + ylmgen_dbl2 *lwx = generator->lambda_wx[curjob->spin]; + pshtd_cmplx *almtmpG = curjob->alm_tmp.c[0], + *almtmpC = curjob->alm_tmp.c[1]; + const pshtd_cmplx + ph1Q = curjob->phas1[0][phas_idx], + ph1U = curjob->phas1[1][phas_idx], + ph2Q = rpair ? curjob->phas2[0][phas_idx] : pshtd_cmplx_null, + ph2U = rpair ? curjob->phas2[1][phas_idx] : pshtd_cmplx_null; + pshtd_cmplx p1Q,p2Q,p1U,p2U; + p1Q.re = ph1Q.re+ph2Q.re; p1Q.im = ph1Q.im+ph2Q.im; + p2Q.re = ph1Q.re-ph2Q.re; p2Q.im = ph1Q.im-ph2Q.im; + p1U.re = ph1U.re+ph2U.re; p1U.im = ph1U.im+ph2U.im; + p2U.re = ph1U.re-ph2U.re; p2U.im = ph1U.im-ph2U.im; + + if ((l-m+curjob->spin)&1) + MAP2ALM_SPIN_MACRO(p2Q,p1Q,p2U,p1U) + for (;lnjobs; ++ijob) + { + X(job) *curjob = &jobs->job[ijob]; + switch (curjob->type) + { + case MAP2ALM: + { + const double *norm_l = curjob->norm_l; + for (i=0;inalm;++i) + { + X(cmplx) *curalm = curjob->alm[i]; + for (l=m; l<=lmax; ++l) + { + ptrdiff_t aidx = psht_alm_index(alm,l,m); +#ifdef PLANCK_HAVE_SSE2 + if (curjob->spin==0) + { + V2DF t; t.v = curjob->alm_tmp.v[i][l]; + curalm[aidx].re += (FLT)(t.d[0]*norm_l[l]); + curalm[aidx].im += (FLT)(t.d[1]*norm_l[l]); + } + else + { + V2DF2 t = to_V2DF2(curjob->alm_tmp.v2[i][l]); + curalm[aidx].re += (FLT)((t.a.d[0]+t.a.d[1])*norm_l[l]); + curalm[aidx].im += (FLT)((t.b.d[0]+t.b.d[1])*norm_l[l]); + } +#else + curalm[aidx].re += (FLT)(curjob->alm_tmp.c[i][l].re*norm_l[l]); + curalm[aidx].im += (FLT)(curjob->alm_tmp.c[i][l].im*norm_l[l]); +#endif + } + } + break; + } + default: + break; + } + } + } + +static void X(phase2map) (X(joblist) *jobs, const psht_geom_info *ginfo, + int mmax, int llim, int ulim) + { +#pragma omp parallel +{ + ringhelper helper; + int ith; + ringhelper_init(&helper); +#pragma omp for schedule(dynamic,1) + for (ith=llim; ithnjobs; ++ijob) + { + X(job) *curjob = &jobs->job[ijob]; + switch (curjob->type) + { + case ALM2MAP: + case ALM2MAP_DERIV1: + for (i=0; inmaps; ++i) + X(ringhelper_phase2pair)(&helper,mmax,&curjob->phas1[i][dim2], + &curjob->phas2[i][dim2],&ginfo->pair[ith],curjob->map[i]); + break; + default: + break; + } + } + } + ringhelper_destroy(&helper); +} /* end of parallel region */ + } + +void X(execute_jobs) (X(joblist) *joblist, const psht_geom_info *geom_info, + const psht_alm_info *alm_info) + { + int lmax = alm_info->lmax, mmax = alm_info->mmax; + int nchunks, chunksize, chunk, spinrec=0, ijob; + + for (ijob=0; ijobnjobs; ++ijob) + if (joblist->job[ijob].spin<=1) { spinrec=1; break; } + + for (ijob=0; ijobnjobs; ++ijob) + joblist->job[ijob].norm_l = + Ylmgen_get_norm (lmax, joblist->job[ijob].spin, spinrec); + +/* clear output arrays if requested */ + X(init_output) (joblist, geom_info, alm_info); + + get_chunk_info(geom_info->npairs,&nchunks,&chunksize); + X(alloc_phase) (joblist,mmax,chunksize); + +/* chunk loop */ + for (chunk=0; chunknpairs); + +/* map->phase where necessary */ + X(map2phase) (joblist, geom_info, mmax, llim, ulim); + +#pragma omp parallel +{ + int m; + X(joblist) ljobs = *joblist; + Ylmgen_C generator; + double *theta = RALLOC(double,ulim-llim); + for (m=0; mpair[m+llim].r1.theta; + Ylmgen_init (&generator,lmax,mmax,spinrec,1e-30); + Ylmgen_set_theta (&generator,theta,ulim-llim); + DEALLOC(theta); + X(alloc_almtmp)(&ljobs,lmax); + +#pragma omp for schedule(dynamic,1) + for (m=0; m<=mmax; ++m) + { +/* alm->alm_tmp where necessary */ + X(alm2almtmp) (&ljobs, lmax, m, alm_info); + +/* inner conversion loop */ + X(inner_loop) (&ljobs, geom_info, lmax, mmax, llim, ulim, &generator, m); + +/* alm_tmp->alm where necessary */ + X(almtmp2alm) (&ljobs, lmax, m, alm_info); + } + + Ylmgen_destroy(&generator); + X(dealloc_almtmp)(&ljobs); +} /* end of parallel region */ + +/* phase->map where necessary */ + X(phase2map) (joblist, geom_info, mmax, llim, ulim); + } /* end of chunk loop */ + + for (ijob=0; ijobnjobs; ++ijob) + DEALLOC(joblist->job[ijob].norm_l); + X(dealloc_phase) (joblist); + } + +void X(make_joblist) (X(joblist) **joblist) + { + *joblist = RALLOC(X(joblist),1); + (*joblist)->njobs=0; + } + +void X(clear_joblist) (X(joblist) *joblist) + { joblist->njobs=0; } + +void X(destroy_joblist) (X(joblist) *joblist) + { DEALLOC(joblist); } + +static void X(addjob) (X(joblist) *joblist, psht_jobtype type, int spin, + int add_output, int nalm, int nmaps, X(cmplx) *alm0, X(cmplx) *alm1, + X(cmplx) *alm2, FLT *map0, FLT *map1, FLT *map2) + { + assert_jobspace(joblist->njobs); + joblist->job[joblist->njobs].type = type; + joblist->job[joblist->njobs].spin = spin; + joblist->job[joblist->njobs].norm_l = NULL; + joblist->job[joblist->njobs].alm[0] = alm0; + joblist->job[joblist->njobs].alm[1] = alm1; + joblist->job[joblist->njobs].alm[2] = alm2; + joblist->job[joblist->njobs].map[0] = map0; + joblist->job[joblist->njobs].map[1] = map1; + joblist->job[joblist->njobs].map[2] = map2; + joblist->job[joblist->njobs].add_output = add_output; + joblist->job[joblist->njobs].nmaps = nmaps; + joblist->job[joblist->njobs].nalm = nalm; + ++joblist->njobs; + } + +void X(add_job_alm2map) (X(joblist) *joblist, const X(cmplx) *alm, FLT *map, + int add_output) + { + X(addjob) (joblist, ALM2MAP, 0, add_output, 1, 1, + (X(cmplx) *)alm, NULL, NULL, map, NULL, NULL); + } +void X(add_job_map2alm) (X(joblist) *joblist, const FLT *map, X(cmplx) *alm, + int add_output) + { + X(addjob) (joblist, MAP2ALM, 0, add_output, 1, 1, + alm, NULL, NULL, (FLT *)map, NULL, NULL); + } +void X(add_job_alm2map_spin) (X(joblist) *joblist, const X(cmplx) *alm1, + const X(cmplx) *alm2, FLT *map1, FLT *map2, int spin, int add_output) + { + UTIL_ASSERT((spin>0)&&(spin<=Ylmgen_maxspin()), + "bad spin in add_job_alm2map_spin()"); + X(addjob) (joblist, ALM2MAP, spin, add_output, 2, 2, + (X(cmplx) *)alm1, (X(cmplx) *)alm2, NULL, map1, map2, NULL); + } +void X(add_job_alm2map_pol) (X(joblist) *joblist, const X(cmplx) *almT, + const X(cmplx) *almG, const X(cmplx) *almC, FLT *mapT, FLT *mapQ, FLT *mapU, + int add_output) + { + X(add_job_alm2map) (joblist, almT, mapT, add_output); + X(add_job_alm2map_spin) (joblist, almG, almC, mapQ, mapU, 2, add_output); + } +void X(add_job_map2alm_spin) (X(joblist) *joblist, const FLT *map1, + const FLT *map2, X(cmplx) *alm1, X(cmplx) *alm2, int spin, int add_output) + { + UTIL_ASSERT((spin>0)&&(spin<=Ylmgen_maxspin()), + "bad spin in add_job_map2alm_spin()"); + X(addjob) (joblist, MAP2ALM, spin, add_output, 2, 2, + alm1, alm2, NULL, (FLT *)map1, (FLT *)map2, NULL); + } +void X(add_job_map2alm_pol) (X(joblist) *joblist, const FLT *mapT, + const FLT *mapQ, const FLT *mapU, X(cmplx) *almT, X(cmplx) *almG, + X(cmplx) *almC, int add_output) + { + X(add_job_map2alm) (joblist, mapT, almT, add_output); + X(add_job_map2alm_spin) (joblist, mapQ, mapU, almG, almC, 2, add_output); + } +void X(add_job_alm2map_deriv1) (X(joblist) *joblist, const X(cmplx) *alm, + FLT *mapdtheta, FLT *mapdphi, int add_output) + { + X(addjob) (joblist, ALM2MAP_DERIV1, 1, add_output, 1, 2, + (X(cmplx) *)alm, NULL, NULL, mapdtheta, mapdphi, NULL); + } diff --git a/external/healpix/libpsht/psht_perftest.c b/external/healpix/libpsht/psht_perftest.c new file mode 100644 index 0000000..8b31e21 --- /dev/null +++ b/external/healpix/libpsht/psht_perftest.c @@ -0,0 +1,223 @@ +/* + * This file is part of libpsht. + * + * libpsht 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. + * + * libpsht 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 libpsht; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * libpsht is being developed at the Max-Planck-Institut fuer Astrophysik + * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt + * (DLR). + */ + +/*! \file psht_perftest.c + Performance test of libpsht's map synthesis and analysis algorithms. + + This program creates a list of transform jobs with a user-specified + maximum multipole lmax that operate on a HEALPix, ECP or Gaussian grid. + Depending on the geometry type, the user has to specify the Nside parameter + (for HEALPix) or the number of pixels per ring. + The individual job types are also given by the user + and can be "alm2map", "map2alm", "alm2map_pol", "map2alm_pol", + "alm2map_spin[1-3]", "map2alm_spin[1-3]", and "alm2map_deriv1". + Any combination of job types is allowed. + + All requested jobs are executed simultaneously. + + Copyright (C) 2006-2010 Max-Planck-Society + \author Martin Reinecke +*/ + +#include +#include +#include +#include "psht.h" +#include "psht_geomhelpers.h" +#include "psht_almhelpers.h" +#include "c_utils.h" +#include "walltime_c.h" + +static void get_map(float **map, ptrdiff_t npix) + { + *map=RALLOC(float,npix); + SET_ARRAY(*map,0,npix,1); + } +static void get_alm(pshts_cmplx **alm, ptrdiff_t nalm) + { + static const pshts_cmplx pshts_cmplx_one={1,1}; + *alm=RALLOC(pshts_cmplx,nalm); + SET_ARRAY(*alm,0,nalm,pshts_cmplx_one); + } + +static void prepare_job (const char *jobname, float **map, + pshts_cmplx **alm, ptrdiff_t npix, ptrdiff_t nalm, int ofs_m, int ofs_a, + int num_m, int num_a) + { + int m; + printf("adding job: %s\n", jobname); + for (m=0; m=5, + "usage: psht_perftest +\n" + " where can be 'alm2map', 'map2alm', 'alm2map_pol',\n" + " 'map2alm_pol', 'alm2map_spin[1-3]', 'map2alm_spin[1-3]',\n" + " or 'alm2map_deriv1'"); + lmax=atoi(argv[2]); + + if (strcmp(argv[1],"gauss")==0) + { + int nrings=lmax+1; + int ppring=atoi(argv[3]); + npix=(ptrdiff_t)nrings*ppring; + printf("\nTesting Gaussian grid (%d rings, %d pixels/ring, %ld pixels)\n", + nrings,ppring,(long)npix); + psht_make_gauss_geom_info (nrings, ppring, 1, &tinfo); + } + else if (strcmp(argv[1],"ecp")==0) + { + int nrings=2*lmax+2; + int ppring=atoi(argv[3]); + npix=(ptrdiff_t)nrings*ppring; + printf("\nTesting ECP grid (%d rings, %d pixels/ring, %ld pixels)\n", + nrings,ppring,(long)npix); + psht_make_ecp_geom_info (nrings, ppring, 0., 1, &tinfo); + } + else if (strcmp(argv[1],"healpix")==0) + { + int nside=atoi(argv[3]); + if (nside<1) nside=1; + npix=12*(ptrdiff_t)nside*nside; + printf("\nTesting Healpix grid (nside=%d, %ld pixels)\n", + nside,(long)npix); + psht_make_healpix_geom_info (nside, 1, &tinfo); + } + else + UTIL_FAIL("unknown command"); + + psht_make_triangular_alm_info(lmax,lmax,1,&alms); + nalm = ((ptrdiff_t)(lmax+1)*(lmax+2))/2; + pshts_make_joblist (&joblist); + + ofs_m=ofs_a=0; + for (m=4; m +#include +#include "psht.h" +#include "psht_geomhelpers.h" +#include "psht_almhelpers.h" +#include "c_utils.h" +#include "walltime_c.h" + +static double drand (double min, double max) + { + return min + (max-min)*rand()/(RAND_MAX+1.0); + } + +static void random_alm (pshtd_cmplx *alm, psht_alm_info *helper, int spin) + { + int l,m; + for (m=0;m<=helper->mmax; ++m) + for (l=m;l<=helper->lmax; ++l) + { + if ((lmaxdiff) maxdiff=fabs(x); + if (fabs(y)>maxdiff) maxdiff=fabs(y); + } + sum=sqrt(sum/nalms); + sum2=sqrt(sum2/nalms); + printf("component %i: rms %e, maxerr %e\n",i, sum/sum2, maxdiff); + } + } + +static void map2alm_iter (psht_geom_info *tinfo, double **map, + pshtd_cmplx **alm_orig, pshtd_cmplx **alm, int lmax, int mmax, + ptrdiff_t npix, ptrdiff_t nalms, int spin, int niter) + { + psht_alm_info *alms; + pshtd_joblist *joblist; + int ncomp = (spin==0) ? 1 : 2; + int iter,i; + ptrdiff_t m; + double timer; + + psht_make_triangular_alm_info(lmax,mmax,1,&alms); + pshtd_make_joblist (&joblist); + + if (spin==0) + pshtd_add_job_map2alm(joblist,map[0],alm[0],0); + else + pshtd_add_job_map2alm_spin(joblist,map[0],map[1],alm[0],alm[1],spin,0); + timer=wallTime(); + pshtd_execute_jobs (joblist, tinfo, alms); + printf("wall time for map2alm: %fs\n",wallTime()-timer); + pshtd_clear_joblist (joblist); + measure_errors(alm_orig,alm,nalms,ncomp); + + for (iter=0; iter0) + random_alm(alm[1],alms,spin); + + ALLOC2D(alm2,pshtd_cmplx,ncomp,nalms); + + printf ("\niteration 0:\n"); + if (spin==0) + pshtd_add_job_alm2map(joblist,alm[0],map[0],0); + else + pshtd_add_job_alm2map_spin(joblist,alm[0],alm[1],map[0],map[1],spin,0); + timer=wallTime(); + pshtd_execute_jobs (joblist, tinfo, alms); + printf("wall time for alm2map: %fs\n",wallTime()-timer); + pshtd_clear_joblist (joblist); + + map2alm_iter(tinfo, map, alm, alm2, lmax, mmax, npix, nalms, spin, niter); + + DEALLOC2D(map); + DEALLOC2D(alm); + DEALLOC2D(alm2); + + psht_destroy_alm_info(alms); + pshtd_destroy_joblist(joblist); + } + +int main(int argc, char **argv) + { + int lmax; + int spin; + int niter; + psht_geom_info *tinfo; + + UTIL_ASSERT (argc==6, + "usage: psht_test "); + lmax=atoi(argv[2]); + niter=atoi(argv[4]); + spin=atoi(argv[5]); + + printf("Testing map analysis accuracy.\n"); + printf("lmax=%d, %d iterations, spin=%d\n", lmax, niter, spin); + + if (strcmp(argv[1],"gauss")==0) + { + int nrings=lmax+1; + int ppring=atoi(argv[3]); + ptrdiff_t npix=(ptrdiff_t)nrings*ppring; + printf("\nTesting Gaussian grid (%d rings, %d pixels/ring, %ld pixels)\n", + nrings,ppring,(long)npix); + psht_make_gauss_geom_info (nrings, ppring, 1, &tinfo); + check_accuracy(tinfo,lmax,lmax,npix,spin,niter); + psht_destroy_geom_info(tinfo); + } + else if (strcmp(argv[1],"ecp")==0) + { + int nrings=2*lmax+2; + int ppring=atoi(argv[3]); + ptrdiff_t npix=(ptrdiff_t)nrings*ppring; + printf("\nTesting ECP grid (%d rings, %d pixels/ring, %ld pixels)\n", + nrings,ppring,(long)npix); + psht_make_ecp_geom_info (nrings, ppring, 0., 1, &tinfo); + check_accuracy(tinfo,lmax,lmax,npix,spin,niter); + psht_destroy_geom_info(tinfo); + } + else if (strcmp(argv[1],"healpix")==0) + { + int nside=atoi(argv[3]); + ptrdiff_t npix; + if (nside<1) nside=1; + npix=12*(ptrdiff_t)nside*nside; + printf("\nTesting Healpix grid (nside=%d, %ld pixels)\n", + nside,(long)npix); + psht_make_healpix_geom_info (nside, 1, &tinfo); + check_accuracy(tinfo,lmax,lmax,npix,spin,niter); + psht_destroy_geom_info(tinfo); + } + else + UTIL_FAIL("unknown grid geometry"); + + return 0; + } diff --git a/external/healpix/libpsht/ylmgen_c.c b/external/healpix/libpsht/ylmgen_c.c new file mode 100644 index 0000000..02e578d --- /dev/null +++ b/external/healpix/libpsht/ylmgen_c.c @@ -0,0 +1,1151 @@ +/* + * This file is part of libpsht. + * + * libpsht 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. + * + * libpsht 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 libpsht; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * libpsht is being developed at the Max-Planck-Institut fuer Astrophysik + * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt + * (DLR). + */ + +/* + * Code for efficient calculation of Y_lm(theta,phi=0) + * + * Copyright (C) 2005-2011 Max-Planck-Society + * Author: Martin Reinecke + */ + +#include +#include +#include "ylmgen_c.h" +#include "c_utils.h" + +enum { large_exponent2=90, minscale=-4, maxscale=11, max_spin=100 }; + +static void sylmgen_init (sylmgen_d *gen, const Ylmgen_C *ygen, int spin) + { + int i; + UTIL_ASSERT(spin>=1,"incorrect spin"); + gen->s=spin; + gen->m=gen->mlo=gen->mhi=-1234567890; + ALLOC(gen->fx,ylmgen_dbl3,ygen->lmax+2); + + for (i=0; ilmax+2; ++i) + gen->fx[i][0]=gen->fx[i][1]=gen->fx[i][2]=0.; + + gen->cth_crit = 2.; + gen->mdist_crit = ygen->lmax+1; + } + +static void sylmgen_destroy (sylmgen_d *gen) + { DEALLOC(gen->fx); } + +static void sylmgen_prepare (sylmgen_d *gen, const Ylmgen_C *ygen, int m_) + { + int mlo_, mhi_, ms_similar, l; + + if (m_==gen->m) return; + UTIL_ASSERT(m_>=0,"incorrect m"); + + mlo_=m_; mhi_=gen->s; + if (mhi_mhi==mhi_) && (gen->mlo==mlo_)); + + gen->m=m_; + gen->mlo = mlo_; gen->mhi = mhi_; + + if (!ms_similar) + { + for (l=gen->mhi; llmax; ++l) + { + double t = ygen->flm1[l+gen->m]*ygen->flm1[l-gen->m] + *ygen->flm1[l+gen->s]*ygen->flm1[l-gen->s]; + double lt = 2*l+1; + double l1 = l+1; + gen->fx[l+1][0]=l1*lt*t; + gen->fx[l+1][1]=gen->m*gen->s*ygen->xl[l]*ygen->xl[l+1]; + t = ygen->flm2[l+gen->m]*ygen->flm2[l-gen->m] + *ygen->flm2[l+gen->s]*ygen->flm2[l-gen->s]; + gen->fx[l+1][2]=t*l1*ygen->xl[l]; + } + gen->prefactor = 0.5L*(ygen->logsum[2*gen->mhi] + -ygen->logsum[gen->mhi+gen->mlo]-ygen->logsum[gen->mhi-gen->mlo]); + } + + gen->preMinus_p = gen->preMinus_m = 0; + if (gen->mhi==gen->m) + { + gen->cosPow = gen->mhi+gen->s; gen->sinPow = gen->mhi-gen->s; + gen->preMinus_p = gen->preMinus_m = ((gen->mhi-gen->s)&1); + } + else + { + gen->cosPow = gen->mhi+gen->m; gen->sinPow = gen->mhi-gen->m; + gen->preMinus_m = ((gen->mhi+gen->m)&1); + } + } + +static void sylmgen_recalc (sylmgen_d *gen, const Ylmgen_C *ygen, int ith, + ylmgen_dbl2 *res, int *firstl) + { + const double ln2 = 0.6931471805599453094172321214581766; + const double inv_ln2 = 1.4426950408889634073599246810018921; + int l=gen->mhi; + int lmax = ygen->lmax; + ylmgen_dbl3 *fy = gen->fx; + const double fsmall = ygen->fsmall, fbig = ygen->fbig, eps = ygen->eps; + const double cth = ygen->cth[ith]; + long double logvalp = inv_ln2*(gen->prefactor + + ygen->lc05[ith]*gen->cosPow + ygen->ls05[ith]*gen->sinPow); + long double logvalm = inv_ln2*(gen->prefactor + + ygen->lc05[ith]*gen->sinPow + ygen->ls05[ith]*gen->cosPow); + int scalep = (int)(logvalp/large_exponent2)-minscale; + int scalem = (int)(logvalm/large_exponent2)-minscale; + double rec1p=0., rec1m=0.; + double rec2p = exp(ln2*(double)(logvalp-(scalep+minscale)*large_exponent2)); + double rec2m = exp(ln2*(double)(logvalm-(scalem+minscale)*large_exponent2)); + double corfacp,corfacm; + double tp,tm; + + if ((abs(gen->m-gen->s)>=gen->mdist_crit)&&(fabs(cth)>=gen->cth_crit)) + { *firstl=ygen->lmax+1; return; } + + if (gen->preMinus_p) + rec2p=-rec2p; + if (gen->preMinus_m) + rec2m=-rec2m; + if (gen->s&1) + rec2p=-rec2p; + + /* iterate until we reach the realm of IEEE numbers */ + while((scalem<0)&&(scalep<0)) + { + if (++l>lmax) break; + rec1p = (cth - fy[l][1])*fy[l][0]*rec2p - fy[l][2]*rec1p; + rec1m = (cth + fy[l][1])*fy[l][0]*rec2m - fy[l][2]*rec1m; + if (++l>lmax) break; + rec2p = (cth - fy[l][1])*fy[l][0]*rec1p - fy[l][2]*rec2p; + rec2m = (cth + fy[l][1])*fy[l][0]*rec1m - fy[l][2]*rec2m; + + while (fabs(rec2p)>fbig) + { rec1p *= fsmall; rec2p *= fsmall; ++scalep; } + while (fabs(rec2m)>fbig) + { rec1m *= fsmall; rec2m *= fsmall; ++scalem; } + } + + corfacp = (scalep<0) ? 0. : ygen->cf[scalep]; + corfacm = (scalem<0) ? 0. : ygen->cf[scalem]; + + if (l<=lmax) + { + while (1) + { + if ((fabs(rec2p*corfacp)>eps) || (fabs(rec2m*corfacm)>eps)) + break; + if (++l>lmax) break; + rec1p = (cth - fy[l][1])*fy[l][0]*rec2p - fy[l][2]*rec1p; + rec1m = (cth + fy[l][1])*fy[l][0]*rec2m - fy[l][2]*rec1m; + if ((fabs(rec1p*corfacp)>eps) || (fabs(rec1m*corfacm)>eps)) + { SWAP(rec1p,rec2p,double); SWAP(rec1m,rec2m,double); break; } + if (++l>lmax) break; + rec2p = (cth - fy[l][1])*fy[l][0]*rec1p - fy[l][2]*rec2p; + rec2m = (cth + fy[l][1])*fy[l][0]*rec1m - fy[l][2]*rec2m; + + if ((fabs(rec2p)>fbig) || (fabs(rec2m)>fbig)) + { + while (fabs(rec2p)>fbig) + { rec1p *= fsmall; rec2p *= fsmall; ++scalep; } + while (fabs(rec2m)>fbig) + { rec1m *= fsmall; rec2m *= fsmall; ++scalem; } + corfacp = (scalep<0) ? 0. : ygen->cf[scalep]; + corfacm = (scalem<0) ? 0. : ygen->cf[scalem]; + } + } + } + + *firstl=l; + if (l>lmax) + { + gen->mdist_crit=abs(gen->m-gen->s); + gen->cth_crit= fabs(cth); + return; + } + + tp = rec2p*corfacp; tm = rec2m*corfacm; + res[l][0]=tp+tm; + res[l][1]=tm-tp; + + while (1) + { + if ((fabs(tp)>eps) && (fabs(tm)>eps)) + break; + if (++l>lmax) break; + rec1p = (cth - fy[l][1])*fy[l][0]*rec2p - fy[l][2]*rec1p; + rec1m = (cth + fy[l][1])*fy[l][0]*rec2m - fy[l][2]*rec1m; + tp=rec1p*corfacp; tm=rec1m*corfacm; + res[l][0]=tp+tm; res[l][1]=tm-tp; + if ((fabs(tp)>eps) && (fabs(tm)>eps)) + { SWAP(rec1p,rec2p,double); SWAP(rec1m,rec2m,double); break; } + if (++l>lmax) break; + rec2p = (cth - fy[l][1])*fy[l][0]*rec1p - fy[l][2]*rec2p; + rec2m = (cth + fy[l][1])*fy[l][0]*rec1m - fy[l][2]*rec2m; + tp=rec2p*corfacp; tm=rec2m*corfacm; + res[l][0]=tp+tm; res[l][1]=tm-tp; + + if ((fabs(rec2p)>fbig) || (fabs(rec2m)>fbig)) + { + while (fabs(rec2p)>fbig) + { rec1p *= fsmall; rec2p *= fsmall; ++scalep; } + while (fabs(rec2m)>fbig) + { rec1m *= fsmall; rec2m *= fsmall; ++scalem; } + corfacp = (scalep<0) ? 0. : ygen->cf[scalep]; + corfacm = (scalem<0) ? 0. : ygen->cf[scalem]; + } + } + + rec1p *= corfacp; rec2p *= corfacp; + rec1m *= corfacm; rec2m *= corfacm; + + for (;llmax) break; + rec1p = (cth - fy[l][1])*fy[l][0]*rec2p - fy[l][2]*rec1p; + rec1m = (cth + fy[l][1])*fy[l][0]*rec2m - fy[l][2]*rec1m; + res[l][0] = rec1p+rec1m; res[l][1] = rec1m-rec1p; + if (++l>lmax) break; + rec2p = (cth - fy[l][1])*fy[l][0]*rec1p - fy[l][2]*rec2p; + rec2m = (cth + fy[l][1])*fy[l][0]*rec1m - fy[l][2]*rec2m; + res[l][0] = rec2p+rec2m; res[l][1] = rec2m-rec2p; + } + } + +#ifdef PLANCK_HAVE_SSE2 + +#define ADVANCE(L,ap,am,bp,bm) \ + { \ + v2df f0=_mm_set1_pd(fy[L][0]), \ + f1=_mm_set1_pd(fy[L][1]), \ + f2=_mm_set1_pd(fy[L][2]); \ + ap = _mm_sub_pd( \ + _mm_mul_pd(_mm_sub_pd(cth,f1),_mm_mul_pd(f0,bp)), \ + _mm_mul_pd(f2,ap)); \ + am = _mm_sub_pd( \ + _mm_mul_pd(_mm_add_pd(cth,f1),_mm_mul_pd(f0,bm)), \ + _mm_mul_pd(f2,am)); \ + } + +#define RENORMX(r1,r2,corf,sca,scb) \ + do \ + { \ + double rec1a, rec1b, rec2a, rec2b, corfaca, corfacb; \ + read_v2df (r1, &rec1a, &rec1b); read_v2df (r2, &rec2a, &rec2b); \ + read_v2df (corf, &corfaca, &corfacb); \ + while (fabs(rec2a)>fbig) \ + { \ + rec1a*=fsmall; rec2a*=fsmall; ++sca; \ + corfaca = (sca<0) ? 0. : ygen->cf[sca]; \ + } \ + while (fabs(rec2b)>fbig) \ + { \ + rec1b*=fsmall; rec2b*=fsmall; ++scb; \ + corfacb = (scb<0) ? 0. : ygen->cf[scb]; \ + } \ + r1=build_v2df(rec1a,rec1b); r2=build_v2df(rec2a,rec2b); \ + corf=build_v2df(corfaca,corfacb); \ + } \ + while(0) + +#define RENORM \ + RENORMX(rec1p,rec2p,corfacp,scale1p,scale2p); \ + RENORMX(rec1m,rec2m,corfacm,scale1m,scale2m) + +static void sylmgen_recalc_sse2 (sylmgen_d *gen, const Ylmgen_C *ygen, + int ith1, int ith2, v2df2 *res, int *firstl) + { + const double ln2 = 0.6931471805599453094172321214581766; + const double inv_ln2 = 1.4426950408889634073599246810018921; + int l=gen->mhi; + int lmax = ygen->lmax; + ylmgen_dbl3 *fy = gen->fx; + const double fbig=ygen->fbig, fsmall=ygen->fsmall; + v2df eps2 = build_v2df(ygen->eps,ygen->eps); + const double cth1=ygen->cth[ith1], cth2=ygen->cth[ith2]; + v2df cth = build_v2df(cth1,cth2); + long double + logval1p = inv_ln2*(gen->prefactor + + ygen->lc05[ith1]*gen->cosPow + ygen->ls05[ith1]*gen->sinPow), + logval2p = inv_ln2*(gen->prefactor + + ygen->lc05[ith2]*gen->cosPow + ygen->ls05[ith2]*gen->sinPow), + logval1m = inv_ln2*(gen->prefactor + + ygen->lc05[ith1]*gen->sinPow + ygen->ls05[ith1]*gen->cosPow), + logval2m = inv_ln2*(gen->prefactor + + ygen->lc05[ith2]*gen->sinPow + ygen->ls05[ith2]*gen->cosPow); + + int scale1p = (int)(logval1p/large_exponent2)-minscale, + scale2p = (int)(logval2p/large_exponent2)-minscale, + scale1m = (int)(logval1m/large_exponent2)-minscale, + scale2m = (int)(logval2m/large_exponent2)-minscale; + + v2df rec1p =_mm_setzero_pd(), rec1m=_mm_setzero_pd(); + v2df rec2p = build_v2df( + exp(ln2*(double)(logval1p-(scale1p+minscale)*large_exponent2)), + exp(ln2*(double)(logval2p-(scale2p+minscale)*large_exponent2))); + v2df rec2m = build_v2df( + exp(ln2*(double)(logval1m-(scale1m+minscale)*large_exponent2)), + exp(ln2*(double)(logval2m-(scale2m+minscale)*large_exponent2))); + v2df corfacp=build_v2df((scale1p<0) ? 0. : ygen->cf[scale1p], + (scale2p<0) ? 0. : ygen->cf[scale2p]), + corfacm=build_v2df((scale1m<0) ? 0. : ygen->cf[scale1m], + (scale2m<0) ? 0. : ygen->cf[scale2m]); + v2df tp,tm; + + if ((abs(gen->m-gen->s)>=gen->mdist_crit) + &&(fabs(ygen->cth[ith1])>=gen->cth_crit) + &&(fabs(ygen->cth[ith2])>=gen->cth_crit)) + { *firstl=ygen->lmax+1; return; } + + if (gen->preMinus_p) + rec2p = _mm_xor_pd (rec2p,V2DF_SIGNMASK); /* negate */ + if (gen->preMinus_m) + rec2m = _mm_xor_pd (rec2m,V2DF_SIGNMASK); /* negate */ + if (gen->s&1) + rec2p = _mm_xor_pd (rec2p,V2DF_SIGNMASK); /* negate */ + + /* iterate until we reach the realm of IEEE numbers */ + while((scale1m<0)&&(scale1p<0)&&(scale2m<0)&&(scale2p<0)) + { + if (++l>lmax) break; + ADVANCE (l,rec1p,rec1m,rec2p,rec2m) + if (++l>lmax) break; + ADVANCE (l,rec2p,rec2m,rec1p,rec1m) + + RENORM; + } + + if (l<=lmax) + { + while (1) + { + if (v2df_any_gt(_mm_mul_pd(rec2p,corfacp),eps2) || + v2df_any_gt(_mm_mul_pd(rec2m,corfacm),eps2)) + break; + if (++l>lmax) break; + ADVANCE (l,rec1p,rec1m,rec2p,rec2m) + if (v2df_any_gt(_mm_mul_pd(rec1p,corfacp),eps2) || + v2df_any_gt(_mm_mul_pd(rec1m,corfacm),eps2)) + { SWAP(rec1p,rec2p,v2df); SWAP(rec1m,rec2m,v2df); break; } + if (++l>lmax) break; + ADVANCE (l,rec2p,rec2m,rec1p,rec1m) + + RENORM; + } + } + + *firstl=l; + if (l>lmax) + { + gen->mdist_crit=abs(gen->m-gen->s); + gen->cth_crit= (fabs(cth1)lmax) break; + ADVANCE(l,rec1p,rec1m,rec2p,rec2m) + tp=_mm_mul_pd(rec1p,corfacp); tm=_mm_mul_pd(rec1m,corfacm); + res[l].a=_mm_add_pd(tp,tm); res[l].b=_mm_sub_pd(tm,tp); + if (v2df_all_ge(tp,eps2) && v2df_all_ge(tm,eps2)) + { SWAP(rec1p,rec2p,v2df); SWAP(rec1m,rec2m,v2df); break; } + if (++l>lmax) break; + ADVANCE (l,rec2p,rec2m,rec1p,rec1m) + tp=_mm_mul_pd(rec2p,corfacp); tm=_mm_mul_pd(rec2m,corfacm); + res[l].a=_mm_add_pd(tp,tm); res[l].b=_mm_sub_pd(tm,tp); + + RENORM; + } + + rec1p = _mm_mul_pd(rec1p,corfacp); rec2p = _mm_mul_pd(rec2p,corfacp); + rec1m = _mm_mul_pd(rec1m,corfacm); rec2m = _mm_mul_pd(rec2m,corfacm); + + for (;llmax) break; + ADVANCE(l,rec1p,rec1m,rec2p,rec2m) + res[l].a=_mm_add_pd(rec1p,rec1m); res[l].b=_mm_sub_pd(rec1m,rec1p); + if (++l>lmax) break; + ADVANCE(l,rec2p,rec2m,rec1p,rec1m) + res[l].a=_mm_add_pd(rec2p,rec2m); res[l].b=_mm_sub_pd(rec2m,rec2p); + } + } + +#endif + +void Ylmgen_init (Ylmgen_C *gen, int l_max, int m_max, int spinrec, + double epsilon) + { + int m; + const double inv_sqrt4pi = 0.2820947917738781434740397257803862929220; + const double inv_ln2 = 1.4426950408889634073599246810018921; + + gen->fsmall = ldexp(1.,-large_exponent2); + gen->fbig = ldexp(1., large_exponent2); + gen->eps = epsilon; + gen->cth_crit = 2.; + gen->ith = -1; + gen->nth = 0; + gen->lmax = l_max; + gen->mmax = m_max; + gen->spinrec = spinrec; + gen->m_cur = -1; + gen->m_crit = gen->mmax+1; + gen->firstl = RALLOC(int,max_spin+1); + for (m=0; m<=max_spin; ++m) gen->firstl[m]=-1; + gen->cf = RALLOC(double,maxscale-minscale+1); + for (m=0; m<(maxscale-minscale+1); ++m) + gen->cf[m] = ldexp(1.,(m+minscale)*large_exponent2); + gen->recfac = RALLOC(ylmgen_dbl2,gen->lmax+1); + gen->mfac = RALLOC(double,gen->mmax+1); + gen->mfac[0] = 1; + for (m=1; m<=gen->mmax; ++m) + gen->mfac[m] = gen->mfac[m-1]*sqrt((2*m+1.)/(2*m)); + for (m=0; m<=gen->mmax; ++m) + gen->mfac[m] = inv_ln2*log(inv_sqrt4pi*gen->mfac[m]); + + gen->t1fac = RALLOC(double,gen->lmax+1); + for (m=0; m<=gen->lmax; ++m) + gen->t1fac[m] = sqrt(4.*(m+1)*(m+1)-1.); + gen->t2fac = RALLOC(double,gen->lmax+gen->mmax+1); + for (m=0; m<=gen->lmax+gen->mmax; ++m) + gen->t2fac[m] = 1./sqrt(m+1.); + + gen->lamfact = RALLOC(double,gen->lmax+1); + gen->ylm = RALLOC(double,gen->lmax+1); + ALLOC(gen->lambda_wx,ylmgen_dbl2 *,max_spin+1); + for (m=0; m<=max_spin; ++m) + gen->lambda_wx[m]=NULL; + + gen->sylm = RALLOC(sylmgen_d *,max_spin+1); + for (m=0; m<=max_spin; ++m) + gen->sylm[m]=NULL; + + gen->ylm_uptodate = 0; + gen->lwx_uptodate = RALLOC(int,max_spin+1); + SET_ARRAY(gen->lwx_uptodate,0,max_spin+1,0); + gen->recfac_uptodate = 0; + gen->lamfact_uptodate = 0; + + gen->th = gen->cth = gen->sth = gen->logsth = NULL; + +#ifdef PLANCK_HAVE_SSE2 + gen->ith1 = gen->ith2 = -1; + gen->ylm_sse2 = RALLOC(v2df,gen->lmax+1); + ALLOC(gen->lambda_wx_sse2,v2df2 *,max_spin+1); + for (m=0; m<=max_spin; ++m) + gen->lambda_wx_sse2[m]=NULL; + gen->ylm_uptodate_sse2 = 0; + gen->lwx_uptodate_sse2 = RALLOC(int,max_spin+1); + SET_ARRAY(gen->lwx_uptodate_sse2,0,max_spin+1,0); +#endif + + ALLOC(gen->logsum,long double,2*gen->lmax+1); + gen->lc05 = gen->ls05 = NULL; + ALLOC(gen->flm1,double,2*gen->lmax+1); + ALLOC(gen->flm2,double,2*gen->lmax+1); + ALLOC(gen->xl,double,gen->lmax+1); + + gen->logsum[0] = 0.; + for (m=1; m<2*gen->lmax+1; ++m) + gen->logsum[m] = gen->logsum[m-1]+logl((long double)m); + for (m=0; m<2*gen->lmax+1; ++m) + { + gen->flm1[m] = sqrt(1./(m+1.)); + gen->flm2[m] = sqrt(m/(m+1.)); + } + + gen->xl[0]=0; + for (m=1; mlmax+1; ++m) gen->xl[m]=1./m; + } + +void Ylmgen_destroy (Ylmgen_C *gen) + { + int m; + + DEALLOC(gen->firstl); + DEALLOC(gen->cf); + DEALLOC(gen->recfac); + DEALLOC(gen->mfac); + DEALLOC(gen->t1fac); + DEALLOC(gen->t2fac); + DEALLOC(gen->lamfact); + DEALLOC(gen->ylm); + DEALLOC(gen->lwx_uptodate); + for (m=0; m<=max_spin; ++m) + DEALLOC(gen->lambda_wx[m]); + DEALLOC(gen->lambda_wx); + for (m=0; m<=max_spin; ++m) + if (gen->sylm[m]) + { + sylmgen_destroy (gen->sylm[m]); + DEALLOC(gen->sylm[m]); + } + DEALLOC(gen->sylm); + DEALLOC(gen->th); + DEALLOC(gen->cth); + DEALLOC(gen->sth); + DEALLOC(gen->logsth); + DEALLOC(gen->logsum); + DEALLOC(gen->lc05); + DEALLOC(gen->ls05); + DEALLOC(gen->flm1); + DEALLOC(gen->flm2); + DEALLOC(gen->xl); +#ifdef PLANCK_HAVE_SSE2 + DEALLOC(gen->ylm_sse2); + for (m=0; m<=max_spin; ++m) + DEALLOC(gen->lambda_wx_sse2[m]); + DEALLOC(gen->lambda_wx_sse2); + DEALLOC(gen->lwx_uptodate_sse2); +#endif + } + +void Ylmgen_set_theta (Ylmgen_C *gen, const double *theta, int nth) + { + const double inv_ln2 = 1.4426950408889634073599246810018921; + int m; + DEALLOC(gen->th); + DEALLOC(gen->cth); + DEALLOC(gen->sth); + DEALLOC(gen->logsth); + DEALLOC(gen->lc05); + DEALLOC(gen->ls05); + gen->th = RALLOC(double,nth); + gen->cth = RALLOC(double,nth); + gen->sth = RALLOC(double,nth); + gen->logsth = RALLOC(double,nth); + gen->lc05 = RALLOC(long double,nth); + gen->ls05 = RALLOC(long double,nth); + for (m=0; m=0.)&&(th<=pi),"bad theta angle specified"); + /* tiny adjustments to make sure cos and sin (theta/2) are positive */ + if (th==0.) th=1e-16; + if (ABSAPPROX(th,pi,1e-15)) th=pi-1e-15; + gen->th[m] = th; + gen->cth[m] = cos(th); + gen->sth[m] = sin(th); + gen->logsth[m] = inv_ln2*log(gen->sth[m]); + gen->lc05[m]=logl(cosl(0.5L*th)); + gen->ls05[m]=logl(sinl(0.5L*th)); + } + + gen->nth = nth; + gen->ith = -1; +#ifdef PLANCK_HAVE_SSE2 + gen->ith1 = gen->ith2 = -1; +#endif + } + +void Ylmgen_prepare (Ylmgen_C *gen, int ith, int m) + { + if ((ith==gen->ith) && (m==gen->m_cur)) return; + + gen->ylm_uptodate = 0; + SET_ARRAY(gen->lwx_uptodate,0,max_spin+1,0); + + gen->ith = ith; + + if (m!=gen->m_cur) + { + gen->recfac_uptodate = 0; + gen->lamfact_uptodate = 0; + gen->m_cur = m; + } + } + +static void Ylmgen_recalc_recfac (Ylmgen_C *gen) + { + double f_old=1; + int l, m; + + if (gen->recfac_uptodate) return; + gen->recfac_uptodate = 1; + + m = gen->m_cur; + for (l=m; l<=gen->lmax; ++l) + { + gen->recfac[l][0] = gen->t1fac[l]*gen->t2fac[l+m]*gen->t2fac[l-m]; + gen->recfac[l][1] = gen->recfac[l][0]/f_old; + f_old = gen->recfac[l][0]; + } + } + +static void Ylmgen_recalc_lamfact (Ylmgen_C *gen) + { + int l, m; + + if (gen->lamfact_uptodate) return; + gen->lamfact_uptodate = 1; + + m = gen->m_cur; + gen->lamfact[m] = 0; + for (l=m+1; l<=gen->lmax; ++l) + gen->lamfact[l] = sqrt((2*l+1.)/(2*l-1.) * (l*l-m*m)); + } + +#define RENORMALIZE_SCALAR \ + do \ + { \ + while (fabs(lam_2)>fbig) \ + { lam_1*=fsmall; lam_2*=fsmall; ++scale; } \ + corfac = (scale<0) ? 0. : gen->cf[scale]; \ + } \ + while(0) + +void Ylmgen_recalc_Ylm (Ylmgen_C *gen) + { + const double ln2 = 0.6931471805599453094172321214581766; + + double logval,lam_1,lam_2,corfac; + double eps=gen->eps, fbig=gen->fbig, fsmall=gen->fsmall; + ylmgen_dbl2 *recfac = gen->recfac; + int lmax=gen->lmax; + int scale,l; + int m = gen->m_cur; + double cth=gen->cth[gen->ith], sth=gen->sth[gen->ith]; + double *result = gen->ylm; + + if (gen->ylm_uptodate) return; + gen->ylm_uptodate=1; + + if (((m>=gen->m_crit)&&(fabs(cth)>=gen->cth_crit)) || ((m>0)&&(sth==0))) + { gen->firstl[0]=gen->lmax+1; return; } + + Ylmgen_recalc_recfac(gen); + + logval = gen->mfac[m]; + if (m>0) logval += m*gen->logsth[gen->ith]; + scale = (int) (logval/large_exponent2)-minscale; + corfac = (scale<0) ? 0. : gen->cf[scale]; + + lam_1 = 0; + lam_2 = exp(ln2*(logval-(scale+minscale)*large_exponent2)); + if (m&1) lam_2 = -lam_2; + + l=m; + if (scale<0) + { + while (1) + { + if (++l>lmax) break; + lam_1 = cth*lam_2*recfac[l-1][0] - lam_1*recfac[l-1][1]; + if (++l>lmax) break; + lam_2 = cth*lam_1*recfac[l-1][0] - lam_2*recfac[l-1][1]; + if (fabs(lam_2)>fbig) + { + RENORMALIZE_SCALAR; + if (scale>=0) break; + } + } + } + + lam_1*=corfac; + lam_2*=corfac; + + if (l<=lmax) + { + while (1) + { + if (fabs(lam_2)>eps) break; + if (++l>lmax) break; + lam_1 = cth*lam_2*recfac[l-1][0] - lam_1*recfac[l-1][1]; + if (fabs(lam_1)>eps) + { double x=lam_1; lam_1=lam_2; lam_2=x; break; } + if (++l>lmax) break; + lam_2 = cth*lam_1*recfac[l-1][0] - lam_2*recfac[l-1][1]; + } + } + + gen->firstl[0]=l; + if (l>lmax) + { gen->m_crit=m; gen->cth_crit=fabs(cth); return; } + + for(;llmax) break; + lam_1 = cth*lam_2*recfac[l-1][0] - lam_1*recfac[l-1][1]; + result[l] = lam_1; + if (++l>lmax) break; + lam_2 = cth*lam_1*recfac[l-1][0] - lam_2*recfac[l-1][1]; + } + } + +static void Ylmgen_recalc_lambda_wx1 (Ylmgen_C *gen) + { + if (gen->lwx_uptodate[1]) return; + Ylmgen_recalc_Ylm(gen); + gen->firstl[1] = gen->firstl[0]; + if (gen->firstl[1]>gen->lmax) return; + Ylmgen_recalc_lamfact(gen); + gen->lwx_uptodate[1] = 1; + + { + double cth=gen->cth[gen->ith]; + double xsth=1./(gen->sth[gen->ith]); + double m=gen->m_cur; + double m_on_sth = m*xsth; + double lam_lm=0; + ylmgen_dbl2 *lambda_wx = gen->lambda_wx[1]; + int l; + double ell; + for (ell=l=gen->firstl[1]; l<=gen->lmax; ++l, ell+=1.) + { + double lam_lm1m=lam_lm; + lam_lm=gen->ylm[l]; + lambda_wx[l][0] = xsth*(gen->lamfact[l]*lam_lm1m - ell*cth*lam_lm); + lambda_wx[l][1] = m_on_sth*lam_lm; + } + } + } + +static void Ylmgen_recalc_lambda_wx2 (Ylmgen_C *gen) + { + if (gen->lwx_uptodate[2]) return; + Ylmgen_recalc_Ylm(gen); + gen->firstl[2] = gen->firstl[0]; + if (gen->firstl[2]>gen->lmax) return; + Ylmgen_recalc_lamfact(gen); + gen->lwx_uptodate[2] = 1; + + { + double cth=gen->cth[gen->ith]; + double sth=gen->sth[gen->ith]; + double m=gen->m_cur; + double one_on_s2 = 1./(sth*sth); + double two_on_s2 = 2*one_on_s2; + double two_c_on_s2 = cth * two_on_s2; + double m2 = m*m; + double two_m_on_s2 = m*two_on_s2; + double lam_lm=0; + ylmgen_dbl2 *lambda_wx = gen->lambda_wx[2]; + int l; + double ell; + for (ell=l=gen->firstl[2]; l<=gen->lmax; ++l, ell+=1.) + { + double lam_lm1m=lam_lm; + lam_lm=gen->ylm[l]; + { + const double t1 = lam_lm1m*gen->lamfact[l]; + const double a_w = (m2-ell)*two_on_s2 - ell*(ell-1.); + const double a_x = cth*(ell-1.)*lam_lm; + lambda_wx[l][0] = a_w*lam_lm + t1*two_c_on_s2; + lambda_wx[l][1] = two_m_on_s2 * (t1-a_x); + } + } + } + } + +void Ylmgen_recalc_lambda_wx (Ylmgen_C *gen, int spin) + { + UTIL_ASSERT ((spin>0) && (spin<=max_spin), + "invalid spin in Ylmgen_recalc_lambda_wx"); + + if (!gen->lambda_wx[spin]) + gen->lambda_wx[spin]=RALLOC(ylmgen_dbl2,gen->lmax+1); + + if (gen->spinrec && spin==1) { Ylmgen_recalc_lambda_wx1(gen); return; } + if (gen->spinrec && spin==2) { Ylmgen_recalc_lambda_wx2(gen); return; } + + if (!gen->sylm[spin]) + { + gen->sylm[spin]=RALLOC(sylmgen_d,1); + sylmgen_init(gen->sylm[spin],gen,spin); + } + if (gen->lwx_uptodate[spin]) return; + sylmgen_prepare(gen->sylm[spin],gen,gen->m_cur); + sylmgen_recalc(gen->sylm[spin],gen,gen->ith,gen->lambda_wx[spin], + &gen->firstl[spin]); + gen->lwx_uptodate[spin] = 1; + } + +#ifdef PLANCK_HAVE_SSE2 + +void Ylmgen_prepare_sse2 (Ylmgen_C *gen, int ith1, int ith2, int m) + { + if ((ith1==gen->ith1) && (ith2==gen->ith2) && (m==gen->m_cur)) return; + + gen->ylm_uptodate_sse2 = 0; + SET_ARRAY(gen->lwx_uptodate_sse2,0,max_spin+1,0); + + gen->ith1 = ith1; gen->ith2 = ith2; + + if (m!=gen->m_cur) + { + gen->recfac_uptodate = gen->lamfact_uptodate = 0; + gen->m_cur = m; + } + } + + +#define RENORMALIZE \ + do \ + { \ + double lam1a, lam1b, lam2a, lam2b, corfaca, corfacb; \ + read_v2df (lam_1, &lam1a, &lam1b); read_v2df (lam_2, &lam2a, &lam2b); \ + read_v2df (corfac, &corfaca, &corfacb); \ + while (fabs(lam2a)>fbig) \ + { \ + lam1a*=fsmall; lam2a*=fsmall; ++scale1; \ + corfaca = (scale1<0) ? 0. : gen->cf[scale1]; \ + } \ + while (fabs(lam2b)>fbig) \ + { \ + lam1b*=fsmall; lam2b*=fsmall; ++scale2; \ + corfacb = (scale2<0) ? 0. : gen->cf[scale2]; \ + } \ + lam_1=build_v2df(lam1a,lam1b); lam_2=build_v2df(lam2a,lam2b); \ + corfac=build_v2df(corfaca,corfacb); \ + } \ + while(0) +#define GETPRE(prea,preb,lv) \ + { \ + prea=_mm_mul_pd(_mm_set1_pd(recfac[lv][0]),cth); \ + preb=_mm_set1_pd(recfac[lv][1]); \ + } +#define NEXTSTEP(prea,preb,prec,pred,reca,recb,lv) \ + { \ + preb = _mm_mul_pd(preb,reca); \ + prea = _mm_mul_pd(prea,recb); \ + prec = _mm_set1_pd(recfac[lv][0]); \ + pred = _mm_set1_pd(recfac[lv][1]); \ + reca = _mm_sub_pd(prea,preb); \ + prec = _mm_mul_pd(cth,prec); \ + } + +void Ylmgen_recalc_Ylm_sse2 (Ylmgen_C *gen) + { + const double ln2 = 0.6931471805599453094172321214581766; + + v2df lam_1,lam_2,corfac; + double logval1,logval2; + double eps=gen->eps, fbig=gen->fbig, fsmall=gen->fsmall; + v2df eps2=build_v2df(eps,eps); + v2df fbig2=build_v2df(fbig,fbig); + ylmgen_dbl2 *recfac = gen->recfac; + int lmax=gen->lmax; + int scale1,scale2,l; + int m = gen->m_cur; + double cth1=gen->cth[gen->ith1], cth2=gen->cth[gen->ith2]; + v2df cth=build_v2df(cth1,cth2); + v2df *result = gen->ylm_sse2; + v2df pre0,pre1,pre2,pre3; + + if (gen->ylm_uptodate_sse2) return; + gen->ylm_uptodate_sse2=1; + + if ((m>=gen->m_crit)&&(fabs(cth1)>=gen->cth_crit)&&(fabs(cth2)>=gen->cth_crit)) + { gen->firstl[0]=gen->lmax+1; return; } + + Ylmgen_recalc_recfac(gen); + + logval1 = logval2 = gen->mfac[m]; + if (m>0) logval1 += m*gen->logsth[gen->ith1]; + if (m>0) logval2 += m*gen->logsth[gen->ith2]; + scale1 = (int) (logval1/large_exponent2)-minscale; + scale2 = (int) (logval2/large_exponent2)-minscale; + corfac = build_v2df((scale1<0) ? 0. : gen->cf[scale1], + (scale2<0) ? 0. : gen->cf[scale2]); + + lam_1 = _mm_setzero_pd(); + lam_2 = build_v2df(exp(ln2*(logval1-(scale1+minscale)*large_exponent2)), + exp(ln2*(logval2-(scale2+minscale)*large_exponent2))); + if (m&1) lam_2 = _mm_xor_pd (lam_2,V2DF_SIGNMASK); /* negate */ + + l=m; + if ((scale1<0) && (scale2<0)) + { + GETPRE(pre0,pre1,l) + while (1) + { + if (++l>lmax) break; + NEXTSTEP(pre0,pre1,pre2,pre3,lam_1,lam_2,l) + if (++l>lmax) break; + NEXTSTEP(pre2,pre3,pre0,pre1,lam_2,lam_1,l) + if (v2df_any_gt(lam_2,fbig2)) + { + RENORMALIZE; + if ((scale1>=0) || (scale2>=0)) break; + } + } + } + + if (l<=lmax) + { + GETPRE(pre0,pre1,l) + while (1) + { + v2df t1; + result[l]=t1=_mm_mul_pd(lam_2,corfac); + if (v2df_any_gt(t1,eps2)) + break; + if (++l>lmax) break; + NEXTSTEP(pre0,pre1,pre2,pre3,lam_1,lam_2,l) + + result[l]=t1=_mm_mul_pd(lam_1,corfac); + if (v2df_any_gt(t1,eps2)) + { v2df tmp=lam_1;lam_1=lam_2;lam_2=tmp; break; } + if (++l>lmax) break; + NEXTSTEP(pre2,pre3,pre0,pre1,lam_2,lam_1,l) + + if (v2df_any_gt(lam_2,fbig2)) + RENORMALIZE; + } + } + + gen->firstl[0]=l; + if (l>lmax) + { + gen->m_crit=m; + gen->cth_crit= (fabs(cth1)lmax) return; + NEXTSTEP(pre0,pre1,pre2,pre3,lam_1,lam_2,l) + + result[l]=t1=_mm_mul_pd(lam_1,corfac); + if (v2df_all_ge(t1,eps2)) + { v2df tmp=lam_1;lam_1=lam_2;lam_2=tmp; break; } + if (++l>lmax) return; + NEXTSTEP(pre2,pre3,pre0,pre1,lam_2,lam_1,l) + + if (v2df_any_gt(lam_2,fbig2)) + RENORMALIZE; + } + + lam_1 = _mm_mul_pd (lam_1,corfac); + lam_2 = _mm_mul_pd (lam_2,corfac); + + GETPRE(pre0,pre1,l) + for(;llmax) break; + NEXTSTEP(pre0,pre1,pre2,pre3,lam_1,lam_2,l) + result[l] = lam_1; + if (++l>lmax) break; + NEXTSTEP(pre2,pre3,pre0,pre1,lam_2,lam_1,l) + } + } + +static void Ylmgen_recalc_lambda_wx1_sse2 (Ylmgen_C *gen) + { + if (gen->lwx_uptodate_sse2[1]) return; + Ylmgen_recalc_Ylm_sse2(gen); + gen->firstl[1] = gen->firstl[0]; + if (gen->firstl[1]>gen->lmax) return; + Ylmgen_recalc_lamfact(gen); + gen->lwx_uptodate_sse2[1] = 1; + + { + v2df cth=build_v2df(gen->cth[gen->ith1],gen->cth[gen->ith2]); + v2df xsth=build_v2df(1./gen->sth[gen->ith1],1./gen->sth[gen->ith2]); + v2df m=build_v2df(gen->m_cur,gen->m_cur); + v2df m_on_sth = _mm_mul_pd(m,xsth); + v2df lam_lm=_mm_setzero_pd(); + v2df2 *lambda_wx = gen->lambda_wx_sse2[1]; + int l; + v2df ell=build_v2df(gen->firstl[1],gen->firstl[1]); + v2df uno=_mm_set1_pd(1.); + for (l=gen->firstl[1]; l<=gen->lmax; ++l, ell=_mm_add_pd(ell,uno)) + { + v2df lamfact=_mm_load1_pd(&gen->lamfact[l]); + v2df lam_lm1m=lam_lm; + lam_lm=gen->ylm_sse2[l]; + lambda_wx[l].a = _mm_mul_pd(xsth,_mm_sub_pd(_mm_mul_pd(lamfact,lam_lm1m), + _mm_mul_pd(_mm_mul_pd(ell,cth),lam_lm))); + lambda_wx[l].b = _mm_mul_pd(m_on_sth,lam_lm); + } + } + } + +static void Ylmgen_recalc_lambda_wx2_sse2 (Ylmgen_C *gen) + { + if (gen->lwx_uptodate_sse2[2]) return; + Ylmgen_recalc_Ylm_sse2(gen); + gen->firstl[2] = gen->firstl[0]; + if (gen->firstl[2]>gen->lmax) return; + Ylmgen_recalc_lamfact(gen); + gen->lwx_uptodate_sse2[2] = 1; + + { + v2df cth=build_v2df(gen->cth[gen->ith1],gen->cth[gen->ith2]); + v2df sth=build_v2df(gen->sth[gen->ith1],gen->sth[gen->ith2]); + v2df m=build_v2df(gen->m_cur,gen->m_cur); + v2df uno=_mm_set1_pd(1.); + v2df one_on_s2 = _mm_div_pd(uno,_mm_mul_pd(sth,sth)); + v2df two_on_s2 = _mm_mul_pd(_mm_set1_pd(2.),one_on_s2); + v2df two_c_on_s2 = _mm_mul_pd(cth,two_on_s2); + v2df m2 = _mm_mul_pd(m,m); + v2df two_m_on_s2 = _mm_mul_pd(m,two_on_s2); + v2df lam_lm=_mm_setzero_pd(); + v2df2 *lambda_wx = gen->lambda_wx_sse2[2]; + int l; + v2df ell=build_v2df(gen->firstl[2],gen->firstl[2]); + for (l=gen->firstl[2]; l<=gen->lmax; ++l, ell=_mm_add_pd(ell,uno)) + { + v2df lamfact=_mm_load1_pd(&gen->lamfact[l]); + v2df lam_lm1m=lam_lm; + lam_lm=gen->ylm_sse2[l]; + { + const v2df t1 = _mm_mul_pd(lam_lm1m,lamfact); + const v2df ellm1 = _mm_sub_pd(ell,uno); + const v2df a_w = _mm_sub_pd + (_mm_mul_pd(_mm_sub_pd(m2,ell),two_on_s2),_mm_mul_pd(ell,ellm1)); + const v2df a_x = _mm_mul_pd(_mm_mul_pd(cth,ellm1),lam_lm); + lambda_wx[l].a = + _mm_add_pd(_mm_mul_pd(a_w,lam_lm),_mm_mul_pd(t1,two_c_on_s2)); + lambda_wx[l].b = _mm_mul_pd(two_m_on_s2,_mm_sub_pd(t1,a_x)); + } + } + } + } + +void Ylmgen_recalc_lambda_wx_sse2 (Ylmgen_C *gen, int spin) + { + UTIL_ASSERT ((spin>0) && (spin<=max_spin), + "invalid spin in Ylmgen_recalc_lambda_wx_sse2"); + + if (!gen->lambda_wx_sse2[spin]) + gen->lambda_wx_sse2[spin]=RALLOC(v2df2,gen->lmax+1); + + if (gen->spinrec && spin==1) { Ylmgen_recalc_lambda_wx1_sse2(gen); return; } + if (gen->spinrec && spin==2) { Ylmgen_recalc_lambda_wx2_sse2(gen); return; } + + if (!gen->sylm[spin]) + { + gen->sylm[spin]=RALLOC(sylmgen_d,1); + sylmgen_init(gen->sylm[spin],gen,spin); + } + if (gen->lwx_uptodate_sse2[spin]) return; + sylmgen_prepare(gen->sylm[spin],gen,gen->m_cur); + sylmgen_recalc_sse2(gen->sylm[spin],gen,gen->ith1,gen->ith2, + gen->lambda_wx_sse2[spin],&gen->firstl[spin]); + gen->lwx_uptodate_sse2[spin] = 1; + } + +#endif /* PLANCK_HAVE_SSE2 */ + +double *Ylmgen_get_norm (int lmax, int spin, int spinrec) + { + const double pi = 3.141592653589793238462643383279502884197; + double *res=RALLOC(double,lmax+1); + int l; + double spinsign; + /* sign convention for H=1 (LensPix paper) */ +#if 1 + spinsign = (spin>0) ? -1.0 : 1.0; +#else + spinsign = 1.0; +#endif + + if (spin==0) + { + for (l=0; l<=lmax; ++l) + res[l]=1.; + return res; + } + + if ((!spinrec) || (spin>=3)) + { + spinsign = (spin&1) ? -spinsign : spinsign; + for (l=0; l<=lmax; ++l) + res[l] = (l0 transforms. */ + ylmgen_dbl2 **lambda_wx; + long double *logsum, *lc05, *ls05; + double *flm1, *flm2, *xl; + + sylmgen_d **sylm; + + int *lwx_uptodate; + int ylm_uptodate; + +#ifdef PLANCK_HAVE_SSE2 + int ith1, ith2; + /*! Points to an array of size [0..lmax] containing the Y_lm values. */ + v2df *ylm_sse2; + /*! Points to an array of size [0..lmax] containing the lambda_w + and lambda_x values for spin>0 transforms. */ + v2df2 **lambda_wx_sse2; + int *lwx_uptodate_sse2; + int ylm_uptodate_sse2; +#endif + + int recfac_uptodate, lamfact_uptodate; + } Ylmgen_C; + +/*! Creates a generator which will calculate Y_lm(theta,phi=0) + up to \a l=l_max and \a m=m_max. It may regard Y_lm whose absolute + magnitude is smaller than \a epsilon as zero. If \a spinrec is nonzero, + the spin-1 and spin-2 Y_lm will be calculated by recursion from the spin-0 + ones, otherwise Wigner d matrix elements will be used. */ +void Ylmgen_init (Ylmgen_C *gen, int l_max, int m_max, int spinrec, + double epsilon); + +/*! Passes am array \a theta of \a nth colatitudes that will be used in + subsequent calls. The individual angles will be referenced by their + index in the array, starting with 0. + \note The array can be freed or reused after the call. */ +void Ylmgen_set_theta (Ylmgen_C *gen, const double *theta, int nth); + +/*! Deallocates a generator previously initialised by Ylmgen_init(). */ +void Ylmgen_destroy (Ylmgen_C *gen); + +/*! Prepares the object for the calculation at \a theta and \a m. */ +void Ylmgen_prepare (Ylmgen_C *gen, int ith, int m); + +/*! Recalculates (if necessary) the Y_lm values. */ +void Ylmgen_recalc_Ylm (Ylmgen_C *gen); +/*! Recalculates (if necessary) the lambda_w and lambda_x values for spin >0 + transforms. */ +void Ylmgen_recalc_lambda_wx (Ylmgen_C *gen, int spin); + +#ifdef PLANCK_HAVE_SSE2 +/*! Prepares the object for the calculation at \a theta, \a theta2 and \a m. */ +void Ylmgen_prepare_sse2 (Ylmgen_C *gen, int ith1, int ith2, int m); + +/*! Recalculates (if necessary) the Y_lm values. */ +void Ylmgen_recalc_Ylm_sse2 (Ylmgen_C *gen); +/*! Recalculates (if necessary) the lambda_w and lambda_x values for spin >0 + transforms. */ +void Ylmgen_recalc_lambda_wx_sse2 (Ylmgen_C *gen, int spin); +#endif + +/*! Returns a pointer to an array with lmax+1 entries containing normalisation + factors that must be applied to Y_lm values computed for \a spin with the + given \a spinrec flag. The array must be deallocated (using free()) by the + user. */ +double *Ylmgen_get_norm (int lmax, int spin, int spinrec); + +/*! Returns the maximum spin quantum number supported by the Ylmgen code. */ +int Ylmgen_maxspin(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/external/healpix/test/alm2map.par b/external/healpix/test/alm2map.par new file mode 100644 index 0000000..a6905ee --- /dev/null +++ b/external/healpix/test/alm2map.par @@ -0,0 +1,5 @@ +nlmax=512 +infile=test.alm +outfile=!test.fits +nside=256 +polarisation=true diff --git a/external/healpix/test/alm2map2.par b/external/healpix/test/alm2map2.par new file mode 100644 index 0000000..3d4b186 --- /dev/null +++ b/external/healpix/test/alm2map2.par @@ -0,0 +1,5 @@ +nlmax=512 +infile=test2.alm +outfile=!test2.fits +nside=256 +polarisation=true diff --git a/external/healpix/test/alm2map3.par b/external/healpix/test/alm2map3.par new file mode 100644 index 0000000..a362830 --- /dev/null +++ b/external/healpix/test/alm2map3.par @@ -0,0 +1,5 @@ +nlmax=512 +infile=test.alm +outfile=!test4.fits +nside=317 +polarisation=true diff --git a/external/healpix/test/anafast.par b/external/healpix/test/anafast.par new file mode 100644 index 0000000..77aaeaa --- /dev/null +++ b/external/healpix/test/anafast.par @@ -0,0 +1,6 @@ +nlmax=512 +infile=test.fits +outfile_alms=!test2.alm +outfile=!test_cl.fits +polarisation=true +iter_order=3 diff --git a/external/healpix/test/runtest.sh b/external/healpix/test/runtest.sh new file mode 100755 index 0000000..4b6386f --- /dev/null +++ b/external/healpix/test/runtest.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +BINPATH=../$HEALPIX_TARGET/bin + +time $BINPATH/syn_alm_cxx syn_alm.par && \ +time $BINPATH/alm2map_cxx alm2map.par && \ +time $BINPATH/map2tga test.fits test.tga -bar -title "Synthesized Map" && \ +time $BINPATH/anafast_cxx anafast.par && \ +time $BINPATH/alm2map_cxx alm2map2.par && \ +time $BINPATH/map2tga test2.fits test2.tga -bar -title "Reconstructed Map" && \ +time $BINPATH/udgrade_cxx udgrade.par && \ +time $BINPATH/map2tga test3.fits test3.tga -bar -title "Downgraded Map" && \ +time $BINPATH/map2tga test3.fits test4.tga -bar -interpol -title "Downgraded, Interpolated Map" && \ +time $BINPATH/alm2map_cxx alm2map3.par && \ +time $BINPATH/map2tga test4.fits test5.tga -bar -title "Synthesized Map (Nside=317)" && \ +xv test.tga test2.tga test3.tga test4.tga test5.tga diff --git a/external/healpix/test/syn_alm.par b/external/healpix/test/syn_alm.par new file mode 100644 index 0000000..16522b6 --- /dev/null +++ b/external/healpix/test/syn_alm.par @@ -0,0 +1,6 @@ +fwhm_arcmin = 60 +infile = cl.fits +rand_seed = 1234 +nlmax = 512 +outfile = !test.alm +polarisation = true diff --git a/external/healpix/test/udgrade.par b/external/healpix/test/udgrade.par new file mode 100644 index 0000000..8fec5dc --- /dev/null +++ b/external/healpix/test/udgrade.par @@ -0,0 +1,4 @@ +infile=test2.fits +outfile=!test3.fits +polarisation=true +nside=8