[Debian-astro-maintainers] Bug#924938: unblock: healpix-java/3.40-1

Leo Singer leo.singer at ligo.org
Mon Mar 18 17:01:18 GMT 2019


Package: release.debian.org
Severity: normal
User: release.debian.org at packages.debian.org
Usertags: unblock

Please unblock package healpix-java.

The package fixes the important bug #923752, "healpix-java: FTBFS in
buster/sid". Note that aladin and topcat depend on healpix-java.

Thank you,
Leo

unblock healpix-java/3.40-1

-- System Information:
Debian Release: buster/sid
  APT prefers testing
  APT policy: (500, 'testing')
Architecture: amd64 (x86_64)

Kernel: Linux 4.19.0-2-amd64 (SMP w/1 CPU core)
Kernel taint flags: TAINT_CRAP
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8), LANGUAGE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled
-------------- next part --------------
diff -Nru healpix-java-3.40/CHANGES healpix-java-3.50/CHANGES
--- healpix-java-3.40/CHANGES	2015-07-06 13:56:00.000000000 -0400
+++ healpix-java-3.50/CHANGES	1969-12-31 19:00:00.000000000 -0500
@@ -1,48 +0,0 @@
-New features and improvements introduced with the healpix.essentials package,
-compared to the HealpixIndex, Healpix and PixTools classes:
-
-- close similarities with Healpix_Base_T class from Healpix C++, which allows
-  simultaneous development and bug fixes for both.
-- support for arbitrary positive Nside values in RING scheme; no longer limited
-  to powers of 2
-- maximum supported Nside value: 2^29
-- significant performance improvements: most methods have been accelerated
-  by integral factors, some by more than an order of magnitude.
-- trigonometric functions are computed using an adapted version of Naoki
-  Shibata's SLEEF library (http://freecode.com/projects/sleef), which is
-  considerably faster than Java's own implementation.
-- re-implementation of queryDisc and queryPolygon:
-  * query methods return RangeSet objects which allow much more compact storage
-    of the result
-  * new native query methods for NESTED ordering; these are slower than those
-    for RING ordering, but much quicker than converting all pixels from a RING
-    result to NESTED.
-  * inclusive queries have been improved: several bugs were fixed, and the
-    number of false positives in the result has been reduced. Users can now
-    choose between quick inclusive queries returning more false positives,
-    and slower ones returning fewer false positives.
-- the HealpixProc class offers a procedural (instead of object-oriented)
-  interface to the HealpixBase functionality, which simplifies transition
-  for users of the "Healpix" and "PixTools" classes.
-  NOTE: this only works for Nside parameters which are powers of 2
-- many bug fixes
-- no external library dependencies, except for "nom.tam.fits" if FITS I/O is
-  required
-- the code base is thread-safe in the following sense:
-  * HealpixProc methods can be called concurrently
-  * HealpixBase methods can be called concurrently on different objects
-
-
-Changes after version 3.11:
-===========================
-
-RangeSet.size() -> RangeSet.nranges()
-RangeSet(int) constructor has new semantics; see documentation!
-
-Changes after version 3.20:
-===========================
-
-- deprecated parts of the library have been removed
-- MOC support (see http://ivoa.net/documents/MOC/ for high-level description)
-- queries for arbitrary polygons (using MOC)
-- new targets in build.xml which allow compilation without external JARs
diff -Nru healpix-java-3.40/COPYING healpix-java-3.50/COPYING
--- healpix-java-3.40/COPYING	2012-05-25 05:37:08.000000000 -0400
+++ healpix-java-3.50/COPYING	1969-12-31 19:00:00.000000000 -0500
@@ -1,340 +0,0 @@
-		    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.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    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.
-
-  <signature of Ty Coon>, 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 -Nru healpix-java-3.40/debian/changelog healpix-java-3.50/debian/changelog
--- healpix-java-3.40/debian/changelog	2018-08-20 09:57:54.000000000 -0400
+++ healpix-java-3.50/debian/changelog	2019-03-06 00:11:09.000000000 -0500
@@ -1,3 +1,16 @@
+healpix-java (3.50-1) unstable; urgency=medium
+
+  * New upstream release.
+
+ -- Leo Singer <leo.singer at ligo.org>  Wed, 06 Mar 2019 00:11:09 -0500
+
+healpix-java (3.40-2) unstable; urgency=medium
+
+  * Remove build dependency on default-jdk-doc. (Closes: #923752)
+  * Update Standards-Version to 4.3.0.
+
+ -- Leo Singer <leo.singer at ligo.org>  Mon, 04 Mar 2019 22:20:38 -0500
+
 healpix-java (3.40-1) unstable; urgency=medium
 
   * New upstream version. 
diff -Nru healpix-java-3.40/debian/control healpix-java-3.50/debian/control
--- healpix-java-3.40/debian/control	2018-08-20 09:09:57.000000000 -0400
+++ healpix-java-3.50/debian/control	2019-03-04 22:18:53.000000000 -0500
@@ -4,8 +4,8 @@
 Uploaders: Leo Singer <leo.singer at ligo.org>
 Homepage: http://healpix.sourceforge.net
 Build-Depends: debhelper (>= 11), javahelper, libjs-jquery, libjs-jquery-ui
-Build-Depends-Indep: default-jdk, default-jdk-doc, junit, libfits-java (>= 1.15.1)
-Standards-Version: 4.2.0
+Build-Depends-Indep: default-jdk, junit, libfits-java (>= 1.15.1)
+Standards-Version: 4.3.0
 Vcs-Git: https://salsa.debian.org/debian-astro-team/healpix-java.git
 Vcs-Browser: https://salsa.debian.org/debian-astro-team/healpix-java
 Section: java
diff -Nru healpix-java-3.40/debian/copyright healpix-java-3.50/debian/copyright
--- healpix-java-3.40/debian/copyright	2018-08-20 08:43:58.000000000 -0400
+++ healpix-java-3.50/debian/copyright	2019-03-06 00:08:21.000000000 -0500
@@ -2,6 +2,10 @@
 Upstream-Name: HEALPix
 Upstream-Contact: Martin Reinecke <martin at mpa-garching.mpg.de>
 Upstream-Source: http://sourceforge.net/p/healpix/code
+Files-Excluded: COPYING INSTALL Makefile.in README READ_Copyrights_Licenses.txt
+                Version configure data doc healpix_doc hpxconfig_functions.sh
+                src/C src/cxx src/f90 src/healpy src/idl src/java/build.xml
+                src/python test
 
 Files: *
 Copyright: 1997-2013 HEALPix collaboration
diff -Nru healpix-java-3.40/debian/javabuild healpix-java-3.50/debian/javabuild
--- healpix-java-3.40/debian/javabuild	2018-08-20 08:43:58.000000000 -0400
+++ healpix-java-3.50/debian/javabuild	2019-03-06 00:09:42.000000000 -0500
@@ -1 +1 @@
-healpix.jar src/healpix/essentials/*.java
+healpix.jar src/java/src/healpix/essentials/*.java
diff -Nru healpix-java-3.40/debian/repack healpix-java-3.50/debian/repack
--- healpix-java-3.40/debian/repack	2018-08-20 08:43:58.000000000 -0400
+++ healpix-java-3.50/debian/repack	1969-12-31 19:00:00.000000000 -0500
@@ -1,5 +0,0 @@
-#!/bin/sh
-# Strip out the parts of the source tree that are unrelated to Java.
-version=$2
-filename=$3
-tar -xzf $filename --wildcards 'Healpix_*/src/java' --strip-components=2 && rm $filename && rm java/build.xml && tar -czf $filename java --transform=s,java/,healpix_java-$version/,  && rm -rf java && jh_repack $@
diff -Nru healpix-java-3.40/debian/rules healpix-java-3.50/debian/rules
--- healpix-java-3.40/debian/rules	2018-08-20 09:17:47.000000000 -0400
+++ healpix-java-3.50/debian/rules	2019-03-06 00:09:42.000000000 -0500
@@ -1,7 +1,7 @@
 #!/usr/bin/make -f
 
-JAVA_HOME=/usr/lib/jvm/default-java
-export CLASSPATH=/usr/share/java/fits.jar
+include /usr/share/javahelper/java-vars.mk
+export CLASSPATH := /usr/share/java/fits.jar
 
 %:
 	dh $@ --with javahelper
@@ -14,8 +14,8 @@
 	(for filename in /usr/share/javascript/jquery/* /usr/share/javascript/jquery-ui/*; do ln -s $$filename; done)
 
 override_dh_installchangelogs:
-	dh_installchangelogs CHANGES
+	dh_installchangelogs src/java/CHANGES
 
 override_dh_auto_test:
-	CLASSPATH=healpix.jar:/usr/share/java/junit.jar jh_build -N test.jar src/healpix/essentials/test
+	CLASSPATH=healpix.jar:/usr/share/java/junit.jar jh_build -N test.jar src/java/src/healpix/essentials/test
 	CLASSPATH=test.jar debian/tests/junit
diff -Nru healpix-java-3.40/debian/tests/build-and-junit healpix-java-3.50/debian/tests/build-and-junit
--- healpix-java-3.40/debian/tests/build-and-junit	2018-08-20 08:43:58.000000000 -0400
+++ healpix-java-3.50/debian/tests/build-and-junit	2019-03-06 00:09:42.000000000 -0500
@@ -1,3 +1,3 @@
 #!/bin/sh -e
-CLASSPATH=/usr/share/java/healpix.jar:/usr/share/java/junit.jar jh_build -N $ADTTMP/test.jar src/healpix/essentials/test
+CLASSPATH=/usr/share/java/healpix.jar:/usr/share/java/junit.jar jh_build -N $ADTTMP/test.jar src/java/src/healpix/essentials/test
 CLASSPATH=$ADTTMP/test.jar debian/tests/junit
diff -Nru healpix-java-3.40/debian/tests/junit healpix-java-3.50/debian/tests/junit
--- healpix-java-3.40/debian/tests/junit	2018-08-20 08:43:58.000000000 -0400
+++ healpix-java-3.50/debian/tests/junit	2019-03-06 00:09:42.000000000 -0500
@@ -1,5 +1,5 @@
 #!/bin/sh -e
-for filename in src/healpix/essentials/test/*.java
+for filename in src/java/src/healpix/essentials/test/*.java
 do
-	junit -text $(echo $filename | sed -e s/\.java\$// -e s,^src/,, -e s,/,\.,g)
+	junit -text $(echo $filename | sed -e s/\.java\$// -e s,^src/java/src/,, -e s,/,\.,g)
 done
diff -Nru healpix-java-3.40/debian/watch healpix-java-3.50/debian/watch
--- healpix-java-3.40/debian/watch	2018-08-20 09:09:57.000000000 -0400
+++ healpix-java-3.50/debian/watch	2019-03-06 00:08:21.000000000 -0500
@@ -1,2 +1,2 @@
-version=3
-opts="repack" https://sf.net/healpix/Healpix_([0-9\.]+)_\w+.tar.gz debian debian/repack
+version=4
+https://sf.net/healpix/ Healpix_([0-9\.]+)_\w+.tar.gz
diff -Nru healpix-java-3.40/README healpix-java-3.50/README
--- healpix-java-3.40/README	2015-03-30 16:18:36.000000000 -0400
+++ healpix-java-3.50/README	1969-12-31 19:00:00.000000000 -0500
@@ -1,46 +0,0 @@
-Installation of Healpix Java
-----------------------------
-requires a Java Development Kit and Apache Ant
-(see below Notes on installing Java, and on junit)
-% ant 
-
-for information on the build targets available:
-% ant -p
-
-Documentation
--------------
-preinstalled in <HEALPIX>/doc/html/java/index.html
-
-% ant docs
-will generate
-<HEALPIX>/src/java/doc/index.html
-from the source files
-
------------------------------------------------------------------
-
-
-Installing Java
-===============
-
-Java Development Kit (JDK aka SDK): required to compile any Java code
----------------------------------
-http://www.oracle.com/technetwork/java/index.html
-
-Java based build tool: Ant
---------------------------
-http://ant.apache.org/bindownload.cgi
-It is also available thru fink for MacOS
-
-
-About Junit
-===========
-junit.jar is required for Java Healpix library installation.
-It is shipped with Healpix and available in 
-<HEALPIX>/src/java/lib/
-Just make sure that this path (or a path to any other junit.jar)
-is included in your CLASSPATH environment variable.
-Alternatively you can use ant's "-lib" option:
-  ant -lib lib/junit*.jar test
-
-Please contact healpix-support AT lists.sourceforge.net for any questions on the
-code or its installation.
diff -Nru healpix-java-3.40/src/healpix/essentials/CircleFinder.java healpix-java-3.50/src/healpix/essentials/CircleFinder.java
--- healpix-java-3.40/src/healpix/essentials/CircleFinder.java	2015-08-05 05:00:40.000000000 -0400
+++ healpix-java-3.50/src/healpix/essentials/CircleFinder.java	1969-12-31 19:00:00.000000000 -0500
@@ -1,71 +0,0 @@
-/*
- *  This file is part of Healpix Java.
- *
- *  This code 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 code 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 code; 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.sourceforge.net
- */
-
-package healpix.essentials;
-
-/** Finds the smallest enclosing cone for a point set on the sphere according to
-    Barequet & Elber: Information Processing Letters 93(2005), p.83.
-    All points are expected to be passed as unit vectors.
-    The enclosing cone must have an opening angle smaller than pi/2.
-
-    @copyright 2011 Max-Planck-Society
-    @author Martin Reinecke */
-final class CircleFinder
-  {
-  private Vec3 center;
-  private double cosrad;
-
-  private void getCircle (Vec3[] point, int q1, int q2)
-    {
-    center = point[q1].add(point[q2]); center.normalize();
-    cosrad = point[q1].dot(center);
-    for (int i=0; i<q1; ++i)
-      if (point[i].dot(center)<cosrad) // point outside the current circle
-        {
-        center=(point[q1].sub(point[i])).cross(point[q2].sub(point[i]));
-        center.normalize();
-        cosrad=point[i].dot(center);
-        if (cosrad<0)
-          { center.flip(); cosrad=-cosrad; }
-        }
-    }
-  private void getCircle (Vec3[] point, int q)
-    {
-    center = point[0].add(point[q]); center.normalize();
-    cosrad = point[0].dot(center);
-    for (int i=1; i<q; ++i)
-      if (point[i].dot(center)<cosrad) // point outside the current circle
-        getCircle(point,i,q);
-    }
-
-  public CircleFinder (Vec3[] point) throws Exception
-    {
-    int np=point.length;
-    HealpixUtils.check(np>=2,"too few points");
-    center = point[0].add(point[1]); center.normalize();
-    cosrad = point[0].dot(center);
-    for (int i=2; i<np; ++i)
-      if (point[i].dot(center)<cosrad) // point outside the current circle
-        getCircle(point,i);
-    }
-
-  public Vec3 getCenter() { return new Vec3(center); }
-  public double getCosrad() { return cosrad; }
-  }
diff -Nru healpix-java-3.40/src/healpix/essentials/Compressor.java healpix-java-3.50/src/healpix/essentials/Compressor.java
--- healpix-java-3.40/src/healpix/essentials/Compressor.java	2015-03-30 16:19:17.000000000 -0400
+++ healpix-java-3.50/src/healpix/essentials/Compressor.java	1969-12-31 19:00:00.000000000 -0500
@@ -1,209 +0,0 @@
-/*
- *  This file is part of Healpix Java.
- *
- *  This code 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 code 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 code; 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.sourceforge.net
- */
-
-package healpix.essentials;
-import java.io.ByteArrayOutputStream;
-
-/** Class for compressing/uncompressing monotonous integer sequences.
-    Implementation inspired by Moffat and Stuiver 2000: "Binary Interpolative
-    Coding for Effective Index Compression", Information Retrieval 3, 25
-
-    @copyright 2014 Max-Planck-Society
-    @author Martin Reinecke */
-public class Compressor
-  {
-//FIXME: move into separate class
-  private static final class obitstream
-    {
-    private long bitpos;
-    private int curval;
-    private ByteArrayOutputStream strm;
-
-    public obitstream()
-      {
-      bitpos=0;
-      curval=0;
-      strm=new ByteArrayOutputStream();
-      }
-    private void put_internal (long val, int bits)
-      {
-      int bitsleft = 8-(int)(bitpos&7);
-      if (bits<=bitsleft) // wbits==bits
-        {
-        curval |= ((val&((1L<<bits)-1))<<(bitsleft-bits));
-        bitpos+=bits;
-        if ((bitpos&7)==0) { strm.write(curval); curval=0; }
-        }
-      else // wbits==bitsleft
-        {
-        curval |= ((val>>>(bits-bitsleft))&((1<<bitsleft)-1));
-        bitpos+=bitsleft;
-        if ((bitpos&7)==0) { strm.write(curval); curval=0; }
-        put_internal(val,bits-bitsleft);
-        }
-      }
-
-    public void put (long val, int bits) throws Exception
-      {
-      if (bits==0) return;
-      HealpixUtils.check(bits<=63,"too many bits");
-      HealpixUtils.check(val-(val&((1L<<bits)-1))==0,
-        "value has too many bits");
-      put_internal(val,bits);
-      }
-
-    public byte[] getData() throws Exception
-      {
-      if ((bitpos&7)!=0) strm.write(curval);
-      return strm.toByteArray();
-      }
-    }
-
-//FIXME: move into separate class
-  private static final class ibitstream
-    {
-    private long bitpos;
-    private int curval;
-    private byte[] data;
-
-    public ibitstream(byte[] data_in) throws Exception
-      {
-      HealpixUtils.check(data_in.length>0,"empty input array");
-      bitpos=0;
-      data=data_in.clone();
-      }
-    private long get_internal (long val, int bits)
-      {
-      int bitsleft = 8-(int)(bitpos&7);
-      if (bitsleft==8)
-        {curval=data[(int)(bitpos>>>3)]; if (curval<0) curval+=256;}
-      if (bits<=bitsleft)
-        {
-        val |= ((curval>>>(bitsleft-bits))&((1L<<bits)-1));
-        bitpos+=bits;
-        }
-      else
-        {
-        val |= (curval&((1L<<bitsleft)-1))<<(bits-bitsleft);
-        bitpos+=bitsleft;
-        val=get_internal(val,bits-bitsleft);
-        }
-      return val;
-      }
-    public long get (int bits) throws Exception
-      {
-      if (bits==0) return 0L;
-      HealpixUtils.check(bits<=63,"too many bits");
-      HealpixUtils.check((bitpos+bits)<=8*(long)data.length,
-        "reading past end of stream");
-      long res=0L;
-      return get_internal(res,bits);
-      }
-    }
-
-  private static void interpol_encode2 (long[] data, int l, int r,
-    obitstream obs, int shift) throws Exception
-    {
-    if (r-l<=1) return;
-    int m=l+(r-l)/2;
-
-    long nval = ((data[r]-data[l])>>>shift) - (r-l) + 1;
-    if (nval<=1) return;
-
-    int nb = 1+HealpixUtils.ilog2(nval-1);
-    long val = (data[m]>>>shift)-((data[l]>>>shift)+(m-l));
-    long nshort=(1L<<nb)-nval;
-    if (val<nshort)
-      obs.put(val,nb-1);
-    else
-      obs.put(val+nshort,nb);
-    interpol_encode2(data,l,m,obs,shift);
-    interpol_encode2(data,m,r,obs,shift);
-    }
-
-  /** Return a byte array representing the compressed sequence
-      [data[begin]; data[end-1]] */
-  public static byte[] interpol_encode (long[] data, int begin, int end)
-    throws Exception
-    {
-    obitstream obs=new obitstream();
-    if (begin>=end) // empty range
-      { obs.put(0,8); return obs.getData(); }
-    HealpixUtils.check(data[begin]>=0,"numbers must be nonnegative");
-    long combo=data[begin];
-    for (int i=begin+1; i<end; ++i)
-      {
-      HealpixUtils.check(data[i-1]<data[i],"numbers not strictly increasing");
-      combo|=data[i];
-      }
-    //determine allowable right shift
-    int shift = Long.numberOfTrailingZeros(combo);
-
-    long maxnum=data[end-1]>>>shift;
-    if (end-begin>maxnum) maxnum = end-begin;
-    int maxbits=1+HealpixUtils.ilog2(maxnum);
-    obs.put(maxbits,8);
-    obs.put(shift,8);
-    obs.put(end-begin,maxbits);
-    obs.put(data[begin]>>>shift,maxbits);
-    if (end-begin==1) return obs.getData(); // a single data entry
-    obs.put(data[end-1]>>>shift,maxbits);
-    interpol_encode2(data,begin,end-1,obs,shift);
-    return obs.getData();
-    }
-
-  private static void interpol_decode2 (long[] data, int l, int r,
-    ibitstream ibs, int shift) throws Exception
-    {
-    if (r-l<=1) return;
-    int m=l+(r-l)/2;
-
-    long nval = ((data[r]-data[l])>>>shift) - (r-l) + 1;
-    long val=0;
-
-    if (nval>1)
-      {
-      int nb = 1+HealpixUtils.ilog2(nval-1);
-      long nshort=(1L<<nb)-nval;
-      val=ibs.get(nb-1);
-      if (val>=nshort)
-        val=(val<<1)+ ibs.get(1) - nshort;
-      }
-    data[m]=data[l]+(((m-l)+val)<<shift);
-
-    interpol_decode2(data,l,m,ibs,shift);
-    interpol_decode2(data,m,r,ibs,shift);
-    }
-
-  /** Return an array containing the number sequence decompressed from data. */
-  public static long[] interpol_decode (byte[] data) throws Exception
-    {
-    ibitstream ibs=new ibitstream(data);
-    int maxbits=(int)ibs.get(8);
-    if (maxbits==0) return new long[0];
-    int shift=(int)ibs.get(8);
-    long[] v=new long[(int)ibs.get(maxbits)];
-    v[0]=ibs.get(maxbits)<<shift;
-    if (v.length==1) return v;
-    v[v.length-1]=ibs.get(maxbits)<<shift;
-    interpol_decode2(v,0,v.length-1,ibs,shift);
-    return v;
-    }
-  }
diff -Nru healpix-java-3.40/src/healpix/essentials/Constants.java healpix-java-3.50/src/healpix/essentials/Constants.java
--- healpix-java-3.40/src/healpix/essentials/Constants.java	2013-04-03 09:15:40.000000000 -0400
+++ healpix-java-3.50/src/healpix/essentials/Constants.java	1969-12-31 19:00:00.000000000 -0500
@@ -1,37 +0,0 @@
-/*
- *  This file is part of Healpix Java.
- *
- *  This code 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 code 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 code; 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.sourceforge.net
- */
-
-package healpix.essentials;
-
-/** Some frequently used constants. */
-public class Constants
-  {
-  /** The Constant halfpi */
-  public static final double halfpi = Math.PI/2.;
-
-  public static final double inv_halfpi = 2./Math.PI;
-
-  /** The Constant twopi. */
-  public static final double twopi = 2*Math.PI;
-  public static final double inv_twopi = 1./(2*Math.PI);
-
-  /** The Constant twothird. */
-  public static final double twothird = 2./3.;
-  }
diff -Nru healpix-java-3.40/src/healpix/essentials/FastMath.java healpix-java-3.50/src/healpix/essentials/FastMath.java
--- healpix-java-3.40/src/healpix/essentials/FastMath.java	2012-05-21 09:06:23.000000000 -0400
+++ healpix-java-3.50/src/healpix/essentials/FastMath.java	1969-12-31 19:00:00.000000000 -0500
@@ -1,168 +0,0 @@
-package healpix.essentials;
-
-/* Subset of the SLEEF Java library by Naoki Shibata. The code in this file is
-   released to the Public Domain. */
-
-/**
- * FastMath class is a Java implementation of the
- * <a href="http://freecode.com/projects/sleef">SLEEF</a>
- * library. Some of the methods can be used as substitutions of the
- * corresponding methods in Math class. They have slightly less
- * accuracy, and some methods are faster compared to those methods in
- * Math class. Please note that the methods in the standard Math class
- * are JNI methods, and the SLEEF library is specialized for SIMD
- * operations.
- */
-public final class FastMath {
-  private static final double mulsign(double x, double y)
-    { return Math.copySign(1, y) * x; }
-
-  /** Checks if the argument is a NaN or not. */
-  private static final boolean isnan(double d)
-    { return d != d; }
-
-  /** Checks if the argument is either positive or negative infinity. */
-  private static final boolean isinf(double d)
-    { return Math.abs(d) == Double.POSITIVE_INFINITY; }
-
-  private static final double sign(double d) { return Math.copySign(1, d); }
-
-  private static final double atanhelper(double s)
-    {
-    double t = s * s;
-    double u = -1.88796008463073496563746e-05;
-    u = u * t + (0.000209850076645816976906797);
-    u = u * t + (-0.00110611831486672482563471);
-    u = u * t + (0.00370026744188713119232403);
-    u = u * t + (-0.00889896195887655491740809);
-    u = u * t + (0.016599329773529201970117);
-    u = u * t + (-0.0254517624932312641616861);
-    u = u * t + (0.0337852580001353069993897);
-    u = u * t + (-0.0407629191276836500001934);
-    u = u * t + (0.0466667150077840625632675);
-    u = u * t + (-0.0523674852303482457616113);
-    u = u * t + (0.0587666392926673580854313);
-    u = u * t + (-0.0666573579361080525984562);
-    u = u * t + (0.0769219538311769618355029);
-    u = u * t + (-0.090908995008245008229153);
-    u = u * t + (0.111111105648261418443745);
-    u = u * t + (-0.14285714266771329383765);
-    u = u * t + (0.199999999996591265594148);
-    u = u * t + (-0.333333333333311110369124);
-
-    return u * t * s + s;
-    }
-
-  private static final double atan2k(double y, double x)
-    {
-    double q = 0.;
-
-    if (x < 0) { x = -x; q = -2.; }
-    if (y > x) { double t = x; x = y; y = -t; q += 1.; }
-
-    return atanhelper(y/x) + q*(Math.PI/2);
-    }
-
-  /** This method calculates the arc tangent of y/x in radians, using
-      the signs of the two arguments to determine the quadrant of the
-      result. The results may have maximum error of 2 ulps. */
-  public static final double atan2(double y, double x)
-    {
-    double r = atan2k(Math.abs(y), x);
-
-    r = mulsign(r, x);
-    if (isinf(x) || x == 0)
-      r = Math.PI/2 - (isinf(x) ? (sign(x) * (Math.PI  /2)) : 0);
-    if (isinf(y)          )
-      r = Math.PI/2 - (isinf(x) ? (sign(x) * (Math.PI*1/4)) : 0);
-    if (            y == 0)
-      r = (sign(x) == -1 ? Math.PI : 0);
-    return isnan(x) || isnan(y) ? Double.NaN : mulsign(r, y);
-    }
-
-  /** This method calculates the arc sine of x in radians. The return
-      value is in the range [-pi/2, pi/2]. The results may have
-      maximum error of 3 ulps. */
-  public static double asin(double d)
-    { return mulsign(atan2k(Math.abs(d), Math.sqrt((1+d)*(1-d))), d); }
-
-  /** This method calculates the arc cosine of x in radians. The
-      return value is in the range [0, pi]. The results may have
-      maximum error of 3 ulps. */
-  public static double acos(double d) {
-    return mulsign(atan2k(Math.sqrt((1+d)*(1-d)), Math.abs(d)), d)
-      + (d<0 ? Math.PI : 0);
-  }
-
-  /** Returns the arc tangent of an angle. The results may have
-      maximum error of 2 ulps. */
-  public static final double atan(double s)
-    {
-    int q = 0;
-    if (s < 0) { s = -s; q = 2; }
-    if (s > 1) { s = 1.0 / s; q |= 1; }
-
-    double t=atanhelper(s);
-
-    if ((q & 1) != 0) t = 1.570796326794896557998982 - t;
-    if ((q & 2) != 0) t = -t;
-
-    return t;
-    }
-
-  private static final double PI4_A = .7853981554508209228515625;
-  private static final double PI4_B
-    = .794662735614792836713604629039764404296875e-8;
-  private static final double PI4_C
-    = .306161699786838294306516483068750264552437361480769e-16;
-  private static final double M_1_PI = 0.3183098861837906715377675267450287;
-
-  private final static double sincoshelper(double d)
-    {
-    double s = d * d;
-    double u = -7.97255955009037868891952e-18;
-    u = u*s +2.81009972710863200091251e-15;
-    u = u*s -7.64712219118158833288484e-13;
-    u = u*s +1.60590430605664501629054e-10;
-    u = u*s -2.50521083763502045810755e-08;
-    u = u*s +2.75573192239198747630416e-06;
-    u = u*s -0.000198412698412696162806809;
-    u = u*s +0.00833333333333332974823815;
-    u = u*s -0.166666666666666657414808;
-    return s*u*d + d;
-    }
-
-  /** Returns the trigonometric sine of an angle. The results may
-      have maximum error of 2 ulps. */
-  public static final double sin(double d)
-    {
-    double u = d * M_1_PI;
-    long q = (long)(u < 0 ? u - 0.5 : u + 0.5);
-
-    double x=4.*q;
-    d -= x*PI4_A;
-    d -= x*PI4_B;
-    d -= x*PI4_C;
-
-    if ((q&1) != 0) d = -d;
-
-    return sincoshelper(d);
-    }
-
-  /** Returns the trigonometric cosine of an angle. The results may
-      have maximum error of 2 ulps. */
-  public static final double cos(double d)
-    {
-    double u = d*M_1_PI - 0.5;
-    long q = 1+2*(long)(u < 0 ? u - 0.5 : u + 0.5);
-
-    double x=2.*q;
-    d -= x*PI4_A;
-    d -= x*PI4_B;
-    d -= x*PI4_C;
-
-    if ((q&2) == 0) d = -d;
-
-    return sincoshelper(d);
-    }
-  }
diff -Nru healpix-java-3.40/src/healpix/essentials/FitsUtil.java healpix-java-3.50/src/healpix/essentials/FitsUtil.java
--- healpix-java-3.40/src/healpix/essentials/FitsUtil.java	2016-03-21 18:45:42.000000000 -0400
+++ healpix-java-3.50/src/healpix/essentials/FitsUtil.java	1969-12-31 19:00:00.000000000 -0500
@@ -1,170 +0,0 @@
-/*
- *  This file is part of Healpix Java.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- */
-package healpix.essentials;
-
-import java.io.FileOutputStream;
-
-import nom.tam.fits.BasicHDU;
-import nom.tam.fits.BinaryTable;
-import nom.tam.fits.BinaryTableHDU;
-import nom.tam.fits.Fits;
-import nom.tam.fits.FitsFactory;
-import nom.tam.fits.Header;
-import nom.tam.util.BufferedDataOutputStream;
-
-/** Basic FITS I/O support for Healpix maps.
-
-    @copyright 2011 Max-Planck-Society
-    @author Martin Reinecke */
-public class FitsUtil
-  {
-  private static String getKey (Header head, String key) throws Exception
-    {
-    String upkey = key.toUpperCase();
-    if (head.containsKey(upkey))
-      return head.findCard(upkey).getValue().trim();
-    else if (head.containsKey("HIERARCH."+key))
-      return head.findCard("HIERARCH."+key).getValue().trim();
-    else
-      HealpixUtils.check(false,"key not found: "+key);
-    return null;
-    }
-
-  private static Scheme getScheme(Header head) throws Exception
-    {
-    String fscheme=getKey(head,"Ordering");
-    HealpixUtils.check((fscheme.equals("RING")) || (fscheme.equals("NESTED")),
-      "unsupported ordering scheme");
-    return (fscheme.equals("RING")) ? Scheme.RING : Scheme.NESTED;
-    }
-
-  public static HealpixMapFloat getFloatMap(String filename, int hdu, int col)
-    throws Exception
-    {
-    FitsFactory.setUseHierarch(true);
-    FitsFactory.setUseAsciiTables(false);
-    FitsFactory.setLongStringsEnabled(true);
-    BasicHDU<?> bhdu = (new Fits(filename)).getHDU(hdu-1);
-    Header head = bhdu.getHeader();
-
-    Scheme scheme = getScheme(head);
-    int nside = Integer.parseInt(getKey(head,"Nside"));
-
-    Object tmp = ((BinaryTable)bhdu.getData()).getFlattenedColumn(col-1);
-    float[] data=null;
-    if (tmp instanceof float[])
-      data = (float[])tmp;
-    else if (tmp instanceof double[])
-      {
-      double[] tmp2 = (double[])tmp;
-      data = new float[tmp2.length];
-      for (int i=0; i<tmp2.length; ++i)
-        data[i] = (float)tmp2[i];
-      }
-    else
-      HealpixUtils.check(false,"unsupported data format");
-
-    HealpixUtils.check(nside*nside*12==data.length,
-      "inconsistent Nside and column length");
-    return new HealpixMapFloat(data, scheme);
-    }
-  public static HealpixMapDouble getDoubleMap(String filename, int hdu, int col)
-    throws Exception
-    {
-    FitsFactory.setUseHierarch(true);
-    FitsFactory.setUseAsciiTables(false);
-    FitsFactory.setLongStringsEnabled(true);
-    BasicHDU<?> bhdu = (new Fits(filename)).getHDU(hdu-1);
-    Header head = bhdu.getHeader();
-
-    Scheme scheme = getScheme(head);
-    int nside = Integer.parseInt(getKey(head,"Nside"));
-
-    Object tmp = ((BinaryTable)bhdu.getData()).getFlattenedColumn(col-1);
-    double[] data=null;
-    if (tmp instanceof double[])
-      data = (double[])tmp;
-    else if (tmp instanceof float[])
-      {
-      float[] tmp2 = (float[])tmp;
-      data = new double[tmp2.length];
-      for (int i=0; i<tmp2.length; ++i)
-        data[i] = tmp2[i];
-      }
-    else
-      HealpixUtils.check(false,"unsupported data format");
-
-    HealpixUtils.check(nside*nside*12==data.length,
-      "inconsistent Nside and column length");
-    return new HealpixMapDouble(data, scheme);
-    }
-
-  public static void writeFloatMap(HealpixMapFloat map, String filename)
-    throws Exception
-    {
-    FitsFactory.setUseHierarch(true);
-    FitsFactory.setUseAsciiTables(false);
-    Fits f = new Fits();
-    Object[] table = new Object[1];
-    table[0] = map.getData();
-
-    f.addHDU(Fits.makeHDU(table));
-    BinaryTableHDU bhdu = (BinaryTableHDU) f.getHDU(1);
-
-    bhdu.setColumnName(0, "data", "values");
-
-    bhdu.addValue("PIXTYPE", "HEALPIX", "This is a HEALPix map");
-    bhdu.addValue("NSIDE", map.getNside(), "HEALPix NSIDE parameter");
-    bhdu.addValue("ORDERING", map.getScheme().toString().toUpperCase(),
-      "HEALPix ordering scheme");
-
-    FileOutputStream fos = new FileOutputStream(filename);
-    BufferedDataOutputStream s = new BufferedDataOutputStream(fos);
-
-    f.write(s);
-    s.flush();
-    s.close();
-    }
-  public static void writeDoubleMap(HealpixMapDouble map, String filename)
-    throws Exception
-    {
-    FitsFactory.setUseHierarch(true);
-    FitsFactory.setUseAsciiTables(false);
-    Fits f = new Fits();
-    Object[] table = new Object[1];
-    table[0] = map.getData();
-
-    f.addHDU(Fits.makeHDU(table));
-    BinaryTableHDU bhdu = (BinaryTableHDU) f.getHDU(1);
-
-    bhdu.setColumnName(0, "data", "values");
-
-    bhdu.addValue("PIXTYPE", "HEALPIX", "This is a HEALPix map");
-    bhdu.addValue("NSIDE", map.getNside(), "HEALPix NSIDE parameter");
-    bhdu.addValue("ORDERING", map.getScheme().toString().toUpperCase(),
-      "HEALPix ordering scheme");
-
-    FileOutputStream fos = new FileOutputStream(filename);
-    BufferedDataOutputStream s = new BufferedDataOutputStream(fos);
-
-    f.write(s);
-    s.flush();
-    s.close();
-    }
-  }
diff -Nru healpix-java-3.40/src/healpix/essentials/Fxyf.java healpix-java-3.50/src/healpix/essentials/Fxyf.java
--- healpix-java-3.40/src/healpix/essentials/Fxyf.java	2013-04-03 09:15:40.000000000 -0400
+++ healpix-java-3.50/src/healpix/essentials/Fxyf.java	1969-12-31 19:00:00.000000000 -0500
@@ -1,114 +0,0 @@
-/*
- *  This file is part of Healpix Java.
- *
- *  This code 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 code 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 code; 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.sourceforge.net
- */
-
-package healpix.essentials;
-
-/** Class describing a location on the sphere
-
-    @copyright 2012 Max-Planck-Society
-    @author Martin Reinecke */
-public final class Fxyf extends HealpixTables
-  {
-  /** x-coordinate within the basis pixel, range [0.0;1.0] */
-  public double fx;
-  /** y-coordinate within the basis pixel, range [0.0;1.0] */
-  public double fy;
-  /** index of the HEALPix basis pixel, range [0;11] */
-  public int face;
-  public Fxyf (double x, double y, int f)
-    { fx=x; fy=y; face=f; }
-
-  protected Fxyf(Hploc loc)
-    {
-    double z=loc.z, phi=loc.phi;
-
-    double za = Math.abs(z);
-    double tt = HealpixUtils.fmodulo((phi*Constants.inv_halfpi),4.0);// in [0,4)
-
-    if (za<=Constants.twothird) // Equatorial region
-      {
-      double temp1 = 0.5+tt;
-      double temp2 = z*0.75;
-      double jp = temp1-temp2; // index of  ascending edge line
-      double jm = temp1+temp2; // index of descending edge line
-      long ifp = (long)jp;  // in {0,4}
-      long ifm = (long)jm;
-      long face_num = (ifp==ifm) ? (ifp|4) : ((ifp<ifm) ? ifp : (ifm+8));
-      fx = HealpixUtils.fmodulo(jm,1.);
-      fy = 1.-HealpixUtils.fmodulo(jp,1.);
-      face = (int)face_num;
-      }
-    else // polar region, za > 2/3
-      {
-      int ntt = Math.min(3,(int)tt);
-      double tp = tt-ntt;
-      double tmp = ((za<0.99)||(!loc.have_sth)) ?
-                    Math.sqrt(3*(1-za)) :
-                    loc.sth/Math.sqrt((1.+za)/3.);
-
-      double jp = tp*tmp; // increasing edge line index
-      double jm = (1.0-tp)*tmp; // decreasing edge line index
-      if (jp>=1.) jp = 1.; // for points too close to the boundary
-      if (jm>=1.) jm = 1.;
-      if (z>=0)
-        { fx=1.-jm; fy=1.-jp; face=ntt; }
-      else
-        { fx=jp; fy=jm; face=ntt+8; }
-      }
-    }
-
-  public Fxyf(Vec3 v)
-    { this(new Hploc(v)); }
-
-  protected Hploc toHploc()
-    {
-    Hploc loc = new Hploc();
-    double jr = jrll[face] - fx - fy;
-
-    double nr;
-    if (jr<1)
-      {
-      nr = jr;
-      double tmp = nr*nr/3.;
-      loc.z = 1 - tmp;
-      if (loc.z>0.99) { loc.sth=Math.sqrt(tmp*(2.-tmp)); loc.have_sth=true; }
-      }
-    else if (jr>3)
-      {
-      nr = 4-jr;
-      double tmp = nr*nr/3.;
-      loc.z = tmp - 1;
-      if (loc.z<-0.99) { loc.sth=Math.sqrt(tmp*(2.-tmp)); loc.have_sth=true; }
-      }
-    else
-      {
-      nr = 1;
-      loc.z = (2-jr)*2./3.;
-      }
-
-    double tmp=jpll[face]*nr+fx-fy;
-    if (tmp<0) tmp+=8;
-    if (tmp>=8) tmp-=8;
-    loc.phi = (nr<1e-15) ? 0 : (0.5*Constants.halfpi*tmp)/nr;
-    return loc;
-    }
-  public Vec3 toVec3()
-    { return toHploc().toVec3(); }
-  }
diff -Nru healpix-java-3.40/src/healpix/essentials/HealpixBase.java healpix-java-3.50/src/healpix/essentials/HealpixBase.java
--- healpix-java-3.40/src/healpix/essentials/HealpixBase.java	2015-09-12 05:25:53.000000000 -0400
+++ healpix-java-3.50/src/healpix/essentials/HealpixBase.java	1969-12-31 19:00:00.000000000 -0500
@@ -1,1297 +0,0 @@
-/*
- *  This file is part of Healpix Java.
- *
- *  This code 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 code 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 code; 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.sourceforge.net
- */
-
-package healpix.essentials;
-
-import java.util.Arrays;
-
-/** Basic opersations related to the HEALPix pixelisation.
-    This class is conceptually very similar the the Healpix_Base class
-    of Healpix_cxx. It supports the NESTED scheme for nside parameters which are
-    powers of 2, and the RING scheme for arbitrary positive nside parameters.
-    The maximum supported nside parameter is 2^29.
-
-    @copyright 2011, 2012 Max-Planck-Society
-    @author Martin Reinecke */
-public class HealpixBase extends HealpixTables
-  {
-  protected final class Xyf
-    {
-    public int ix, iy, face;
-    public Xyf () {}
-    public Xyf (int x, int y, int f)
-      { ix=x; iy=y; face=f; }
-    }
-
-  private final class RingInfoSmall
-    {
-    long startpix, ringpix;
-    boolean shifted;
-    }
-
-  /** Maximum order parameter */
-  public static final int order_max=29;
-  /** Maximum Nside parameter; equivalent to 2^{@code order_max}. */
-  public static final long ns_max=1L<<order_max;
-
-  /** The order of the map; -1 when {@code nside} is not a power of 2. */
-  protected int order;
-
-  /** The Nside parameter. */
-  protected long nside;
-
-  protected long nl2, nl3, nl4, npface, npix, ncap;
-  protected double fact1, fact2;
-
-  /** The ordering scheme. */
-  protected Scheme scheme;
-
-  private static long spread_bits (int v)
-    {
-    return (long)(utab[ v      &0xff])      | ((long)(utab[(v>>> 8)&0xff])<<16)
-        | ((long)(utab[(v>>>16)&0xff])<<32) | ((long)(utab[(v>>>24)&0xff])<<48);
-    }
-  private static int compress_bits (long v)
-    {
-    long raw = v&0x5555555555555555L;
-    raw |= raw>>>15;
-    int raw1 = (int)(raw&0xffffL), raw2 = (int)((raw>>>32)&0xffffL);
-    return ctab[raw1&0xff]      | (ctab[raw1>>>8]<< 4)
-        | (ctab[raw2&0xff]<<16) | (ctab[raw2>>>8]<<20);
-    }
-
-  private Xyf nest2xyf(long ipix)
-    {
-    long pix=ipix&(npface-1);
-    return new Xyf (compress_bits(pix), compress_bits(pix>>>1),
-                    (int)(ipix>>>(2*order)));
-    }
-
-  private long xyf2nest(int ix, int iy, int face_num)
-    {
-    return ((long)(face_num)<<(2*order)) +
-      spread_bits(ix) + (spread_bits(iy)<<1);
-    }
-
-  private long xyf2ring(int ix, int iy, int face_num)
-    {
-    long jr = ((long)jrll[face_num]*nside) - (long)ix - (long)iy  - 1L;
-
-    RingInfoSmall ris = get_ring_info_small(jr);
-    long nr=ris.ringpix>>>2, kshift=ris.shifted ? 0:1;
-
-    long jp = (jpll[face_num]*nr + (long)ix - (long)iy + 1L + kshift) / 2L;
-    if (jp>nl4)
-      jp-=nl4;
-    else
-      if (jp<1) jp+=nl4;
-
-    return ris.startpix + jp - 1L;
-    }
-
-  protected Xyf ring2xyf(long pix)
-    {
-    Xyf ret = new Xyf();
-    long iring, iphi, kshift, nr;
-
-    if (pix<ncap) // North Polar cap
-      {
-      iring = (1+HealpixUtils.isqrt(1L+2L*pix))>>>1; //counted from North pole
-      iphi = (pix+1) - 2*iring*(iring-1);
-      kshift = 0;
-      nr = iring;
-      ret.face=(int)((iphi-1)/nr);
-      }
-    else if (pix<(npix-ncap)) // Equatorial region
-      {
-      long ip = pix - ncap;
-      long tmp = (order>=0) ? ip>>>(order+2) : ip/nl4;
-      iring = tmp+nside;
-      iphi = ip-tmp*nl4 + 1;
-      kshift = (iring+nside)&1;
-      nr = nside;
-      long ire = iring-nside+1,
-           irm = nl2+2-ire;
-      long ifm = iphi - (ire>>>1) + nside -1,
-           ifp = iphi - (irm>>>1) + nside -1;
-      if (order>=0)
-        { ifm >>>= order; ifp >>>= order; }
-      else
-        { ifm /= nside; ifp /= nside; }
-      ret.face = (int)((ifp==ifm) ? (ifp|4) : ((ifp<ifm) ? ifp : (ifm+8)));
-      }
-    else // South Polar cap
-      {
-      long ip = npix - pix;
-      iring = (1+HealpixUtils.isqrt(2L*ip-1L))>>>1; //counted from South pole
-      iphi  = 4L*iring + 1 - (ip - 2L*iring*(iring-1L));
-      kshift = 0;
-      nr = iring;
-      iring = 2L*nl2-iring;
-      ret.face = 8 + (int)((iphi-1)/nr);
-      }
-
-    long irt = iring - ((long)jrll[ret.face]*nside) + 1L;
-    long ipt = 2L*iphi- (long)jpll[ret.face]*nr - kshift -1L;
-    if (ipt>=nl2) ipt-=8L*nside;
-
-    ret.ix = (int)(( ipt-irt)>>>1);
-    ret.iy = (int)((-ipt-irt)>>>1);
-
-    return ret;
-    }
-
-  protected Xyf pix2xyf (long pix)
-    { return (scheme==Scheme.RING) ? ring2xyf(pix) : nest2xyf(pix); }
-
-  protected long xyf2pix (int ix, int iy, int face_num)
-    {
-    return (scheme==Scheme.RING) ?
-      xyf2ring(ix,iy,face_num) : xyf2nest(ix,iy,face_num);
-    }
-  protected long xyf2pix (Xyf xyf)
-    {
-    return (scheme==Scheme.RING) ?
-      xyf2ring(xyf.ix,xyf.iy,xyf.face) : xyf2nest(xyf.ix,xyf.iy,xyf.face);
-    }
-
-  /** Calculates the map order from its Nside parameter.
-      @param nside the Nside parameter
-      @return the map order corresponding to {@code nside}; -1 if
-        {@code nside} is not a power of 2. */
-  public static int nside2order(long nside) throws Exception
-    {
-    HealpixUtils.check (nside>0,"nside must be positive");
-    return ((nside&(nside-1))!=0) ? -1 : HealpixUtils.ilog2(nside);
-    }
-
-  /** Calculates the Nside parameter from the number of pixels.
-      @param npix the number of pixels
-      @return the computed Nside parameter */
-  public static long npix2Nside(long npix) throws Exception
-    {
-    HealpixUtils.check (npix>0,"npix must be positive");
-    long nside = HealpixUtils.isqrt(npix/12);
-    HealpixUtils.check(12*nside*nside==npix,"npix is not 12*nside*nside");
-    HealpixUtils.check(nside<=ns_max,"nside is too large");
-    return nside;
-    }
-  /** Calculates the number of pixels from the Nside parameter.
-      @param nside the Nside parameter
-      @return the computed number of pixels */
-  public static long nside2Npix(long nside) throws Exception
-    {
-    HealpixUtils.check (nside>0,"nside must be positive");
-    HealpixUtils.check(nside<=ns_max,"nside is too large");
-    return 12*nside*nside;
-    }
-
-  /** Calculates the number of pixels from the order parameter.
-      @param order the order parameter
-      @return the computed number of pixels */
-  public static long order2Npix(int order) throws Exception
-    {
-    HealpixUtils.check (order>=0,"order must be nonnegative");
-    HealpixUtils.check(order<=order_max,"order is too large");
-    return 12*(1L<<(2*order));
-    }
-
-  /** Adjusts the object to nside_in.
-      @param nside_in the new Nside parameter */
-  public void setNside (long nside_in) throws Exception
-    {
-    if (nside==nside_in) return;
-    nside=nside_in;
-    HealpixUtils.check(nside<=ns_max && nside>0,
-      "Nside must be between 1 and " + ns_max);
-
-    order = nside2order(nside);
-    if (scheme==Scheme.NESTED && order<0)
-      throw new Exception("Nside must be a power of 2 for NESTED scheme");
-    nl2 = 2*nside;
-    nl3 = 3*nside;
-    nl4 = 4*nside;
-    npface = nside*nside;
-    ncap = 2*nside*(nside-1); // pixels in each polar cap
-    npix = 12*npface;
-    fact2 = 4.0/npix;
-    fact1 = (nside<<1)*fact2;
-    }
-
-  /** Adjusts the object to nside_in and scheme_in.
-      @param nside_in the new Nside parameter
-      @param scheme_in the new ordering scheme */
-  public void setNsideAndScheme (long nside_in, Scheme scheme_in)
-    throws Exception
-    {
-    if ((scheme==scheme_in) && (nside==nside_in)) return;
-    HealpixUtils.check (((nside_in&(nside_in-1))==0)||(scheme_in==Scheme.RING),
-      "Nside must be a power of 2 for NESTED scheme");
-    scheme=scheme_in;
-    setNside(nside_in);
-    }
-
-  /** Initializes the object to Nside=1 and scheme=NESTED. */
-  public HealpixBase()
-    {
-    try
-      { nside=0; setNsideAndScheme(1,Scheme.NESTED); }
-    catch(Exception Ex) {/*cannot happen*/}
-    }
-
-  /** Initializes the object to a user-supplied Nside and ordering scheme.
-      @param nside_in the Nside parameter
-      @param scheme_in the ordering scheme */
-  public HealpixBase(long nside_in, Scheme scheme_in) throws Exception
-    { nside=nside_in-1; setNsideAndScheme(nside_in, scheme_in); }
-
-  /** Returns the current ordering scheme.
-      @return the current ordering scheme */
-  public Scheme getScheme()
-    { return scheme; }
-
-  /** Returns the current Nside parameter.
-      @return the current Nside parameter */
-  public int getNside()
-    { return (int)nside; }
-
-  /** Returns the total number of pixels in the pixelisation.
-      @return the current total number of pixels */
-  public long getNpix()
-    { return npix; }
-
-  /** Adjusts the object to scheme.
-      @param scheme_in the new ordering scheme */
-  public void setScheme(Scheme scheme_in) throws Exception
-    {
-    if (scheme_in==Scheme.NESTED && order<0)
-      throw new Exception("Nside must be a power of 2 for NESTED scheme");
-    scheme = scheme_in;
-    }
-
-  /** Returns the current order parameter.
-      @return the current map order parameter. */
-  public int getOrder()
-    { return order; }
-
-  /** Returns the pixel which contains the supplied Pointing.
-      @param ptg the requested location on the sphere.
-      @return the pixel number containing the location. */
-  public long ang2pix(Pointing ptg) throws Exception
-    { return loc2pix(new Hploc(ptg)); }
-
-  /** Returns the Pointing corresponding to the center of the supplied pixel.
-      @param pix the requested pixel number.
-      @return the pixel's center coordinates. */
-  public Pointing pix2ang(long pix) throws Exception
-    { return pix2loc(pix).toPointing(); }
-
-  /** Returns the pixel which contains the supplied Vec3.
-      @param vec the requested location on the sphere (need not be normalized).
-      @return the pixel number containing the location. */
-  public long vec2pix(Vec3 vec) throws Exception
-    { return loc2pix(new Hploc(vec)); }
-
-  /** Returns the normalized 3-vector corresponding to the center of the
-      supplied pixel.
-      @param pix the requested pixel number.
-      @return the pixel's center coordinates. */
-  public Vec3 pix2vec(long pix) throws Exception
-    { return pix2loc(pix).toVec3(); }
-
-  /** Returns nested pixel number for the supplied ring pixel number.
-      @param ipring the requested pixel number in RING scheme.
-      @return the corresponding pixel number in NESTED scheme. */
-  public long ring2nest(long ipring) throws Exception
-    {
-    Xyf xyf = ring2xyf(ipring);
-    return xyf2nest (xyf.ix,xyf.iy, xyf.face);
-    }
-
-  /** Returns ring pixel number for the supplied nested pixel number.
-      @param ipnest the requested pixel number in NESTED scheme.
-      @return the corresponding pixel number in RING scheme. */
-  public long nest2ring(long ipnest) throws Exception
-    {
-    Xyf xyf = nest2xyf(ipnest);
-    return xyf2ring (xyf.ix,xyf.iy, xyf.face);
-    }
-
-  protected long loc2pix (Hploc loc)
-    {
-    double z=loc.z, phi=loc.phi;
-
-    double za = Math.abs(z);
-    double tt = HealpixUtils.fmodulo((phi*Constants.inv_halfpi),4.0);// in [0,4)
-
-    if (scheme==Scheme.RING)
-      {
-      if (za<=Constants.twothird) // Equatorial region
-        {
-        double temp1 = nside*(0.5+tt);
-        double temp2 = nside*z*0.75;
-        long jp = (long)(temp1-temp2); // index of  ascending edge line
-        long jm = (long)(temp1+temp2); // index of descending edge line
-
-        // ring number counted from z=2/3
-        long ir = nside + 1 + jp - jm; // in {1,2n+1}
-        long kshift = 1-(ir&1); // kshift=1 if ir even, 0 otherwise
-
-        long t1 = jp+jm-nside+kshift+1+nl4+nl4;
-        long ip = (order>0) ?
-          (t1>>>1)&(nl4-1) : ((t1>>>1)%nl4); // in {0,4n-1}
-
-        return ncap + (ir-1)*nl4 + ip;
-        }
-      else  // North & South polar caps
-        {
-        double tp = tt-(long)(tt);
-        double tmp = ((za<0.99)||(!loc.have_sth)) ?
-                     nside*Math.sqrt(3*(1-za)) :
-                     nside*loc.sth/Math.sqrt((1.+za)/3.);
-
-        long jp = (long)(tp*tmp); // increasing edge line index
-        long jm = (long)((1.0-tp)*tmp); // decreasing edge line index
-
-        long ir = jp+jm+1; // ring number counted from the closest pole
-        long ip = (long)(tt*ir); // in {0,4*ir-1}
-        assert((ip>=0)&&(ip<4*ir));
-
-        return (z>0)  ?  2*ir*(ir-1) + ip  :  npix - 2*ir*(ir+1) + ip;
-        }
-      }
-    else // scheme_ == NEST
-      {
-      if (za<=Constants.twothird) // Equatorial region
-        {
-        double temp1 = nside*(0.5+tt);
-        double temp2 = nside*(z*0.75);
-        long jp = (long)(temp1-temp2); // index of  ascending edge line
-        long jm = (long)(temp1+temp2); // index of descending edge line
-        long ifp = jp >>> order;  // in {0,4}
-        long ifm = jm >>> order;
-        long face_num = (ifp==ifm) ? (ifp|4) : ((ifp<ifm) ? ifp : (ifm+8));
-
-        long ix = jm & (nside-1),
-             iy = nside - (jp & (nside-1)) - 1;
-        return xyf2nest((int)ix,(int)iy,(int)face_num);
-        }
-      else // polar region, za > 2/3
-        {
-        int ntt = Math.min(3,(int)tt);
-        double tp = tt-ntt;
-        double tmp = ((za<0.99)||(!loc.have_sth)) ?
-                     nside*Math.sqrt(3*(1-za)) :
-                     nside*loc.sth/Math.sqrt((1.+za)/3.);
-
-        long jp = (long)(tp*tmp); // increasing edge line index
-        long jm = (long)((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;
-        return (z>=0) ?
-          xyf2nest((int)(nside-jm -1),(int)(nside-jp-1),ntt) :
-          xyf2nest((int)jp,(int)jm,ntt+8);
-        }
-      }
-    }
-
-  /** Returns the pixel which contains the supplied Zphi.
-      @param zphi the requested location on the sphere.
-      @return the pixel number containing the location. */
-  public long zphi2pix (Zphi zphi)
-    { return loc2pix (new Hploc(zphi)); }
-
-  protected Hploc pix2loc (long pix)
-    {
-    Hploc loc = new Hploc();
-    if (scheme==Scheme.RING)
-      {
-      if (pix<ncap) // North Polar cap
-        {
-        long iring = (1+(HealpixUtils.isqrt(1+2*pix)))>>>1; //from North pole
-        long iphi  = (pix+1) - 2*iring*(iring-1);
-
-        double tmp = (iring*iring)*fact2;
-        loc.z = 1.0 - tmp;
-        if (loc.z>0.99) { loc.sth=Math.sqrt(tmp*(2.-tmp)); loc.have_sth=true; }
-        loc.phi = (iphi-0.5) * Constants.halfpi/iring;
-        }
-      else if (pix<(npix-ncap)) // Equatorial region
-        {
-        long ip  = pix - ncap;
-        long tmp = (order>=0) ? ip>>>(order+2) : ip/nl4;
-        long iring = tmp + nside,
-          iphi = ip-nl4*tmp+1;;
-        // 1 if iring+nside is odd, 1/2 otherwise
-        double fodd = ((iring+nside)&1)!=0 ? 1 : 0.5;
-
-        loc.z = (nl2-iring)*fact1;
-        loc.phi = (iphi-fodd) * Math.PI*0.75*fact1;
-        }
-      else // South Polar cap
-        {
-        long ip = npix - pix;
-        long iring = (1+HealpixUtils.isqrt(2*ip-1))>>>1; //from South pole
-        long iphi  = 4*iring + 1 - (ip - 2*iring*(iring-1));
-
-        double tmp = (iring*iring)*fact2;
-        loc.z = tmp-1.0;
-        if (loc.z<-0.99) { loc.sth=Math.sqrt(tmp*(2.-tmp)); loc.have_sth=true; }
-        loc.phi = (iphi-0.5) * Constants.halfpi/iring;
-        }
-      }
-    else
-      {
-      Xyf xyf= nest2xyf(pix);
-
-      long jr = ((long)(jrll[xyf.face])<<order) -xyf.ix - xyf.iy - 1;
-
-      long nr;
-      if (jr<nside)
-        {
-        nr = jr;
-        double tmp = (nr*nr)*fact2;
-        loc.z = 1 - tmp;
-        if (loc.z>0.99) { loc.sth=Math.sqrt(tmp*(2.-tmp)); loc.have_sth=true; }
-        }
-      else if (jr>nl3)
-        {
-        nr = nl4-jr;
-        double tmp = (nr*nr)*fact2;
-        loc.z = tmp - 1;
-        if (loc.z<-0.99) { loc.sth=Math.sqrt(tmp*(2.-tmp)); loc.have_sth=true; }
-        }
-      else
-        {
-        nr = nside;
-        loc.z = (nl2-jr)*fact1;
-        }
-
-      long tmp=(long)(jpll[xyf.face])*nr+xyf.ix-xyf.iy;
-      assert(tmp<8*nr); // must not happen
-      if (tmp<0) tmp+=8*nr;
-      loc.phi = (nr==nside) ? 0.75*Constants.halfpi*tmp*fact1 :
-                             (0.5*Constants.halfpi*tmp)/nr;
-      }
-    return loc;
-    }
-
-  /** Returns the Zphi corresponding to the center of the supplied pixel.
-      @param pix the requested pixel number.
-      @return the pixel's center coordinates. */
-  public Zphi pix2zphi (long pix)
-    { return pix2loc(pix).toZphi(); }
-
-  /** Returns the neighboring pixels of ipix.
-      This method works in both RING and NEST schemes, but is
-      considerably faster in the NEST scheme.
-      @param ipix the requested pixel number.
-      @return array with indices of the neighboring pixels.
-        The returned array contains (in this order)
-        the pixel numbers of the SW, W, NW, N, NE, E, SE and S neighbor
-        of ipix. If a neighbor does not exist (this can only happen
-        for the W, N, E and S neighbors), its entry is set to -1. */
-  public long[] neighbours(long ipix) throws Exception
-    {
-    long[] result = new long[8];
-    Xyf xyf = (scheme==Scheme.NESTED) ? nest2xyf(ipix) : ring2xyf(ipix);
-    int ix = xyf.ix, iy=xyf.iy, face_num=xyf.face;
-
-    long nsm1 = nside-1;
-    if ((ix>0)&&(ix<nsm1)&&(iy>0)&&(iy<nsm1))
-      {
-      if (scheme==Scheme.RING)
-        for (int m=0; m<8; ++m)
-          result[m]=(xyf2ring(ix+xoffset[m],iy+yoffset[m],face_num));
-      else
-        {
-        long fpix = (long)(face_num)<<(2*order),
-             px0=spread_bits(ix  ), py0=spread_bits(iy  )<<1,
-             pxp=spread_bits(ix+1), pyp=spread_bits(iy+1)<<1,
-             pxm=spread_bits(ix-1), pym=spread_bits(iy-1)<<1;
-
-        result[0]=fpix+pxm+py0; result[1]=fpix+pxm+pyp;
-        result[2]=fpix+px0+pyp; result[3]=fpix+pxp+pyp;
-        result[4]=fpix+pxp+py0; result[5]=fpix+pxp+pym;
-        result[6]=fpix+px0+pym; result[7]=fpix+pxm+pym;
-        }
-      }
-    else
-      {
-      for (int i=0; i<8; ++i)
-        {
-        int x=ix+xoffset[i];
-        int y=iy+yoffset[i];
-        int nbnum=4;
-        if (x<0)
-          { x+=nside; nbnum-=1; }
-        else if (x>=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)
-          {
-          int bits = swaparray[nbnum][face_num>>>2];
-          if ((bits&1)>0) x=(int)(nside-x-1);
-          if ((bits&2)>0) y=(int)(nside-y-1);
-          if ((bits&4)>0) { int tint=x; x=y; y=tint; }
-          result[i] = (scheme==Scheme.NESTED) ?
-            xyf2nest(x,y,f) : xyf2ring(x,y,f);
-          }
-        else
-          result[i]=-1;
-        }
-      }
-    return result;
-    }
-
-  /** Returns the maximum angular distance between a pixel center and its
-      corners.
-      @return maximum angular distance between a pixel center and its
-        corners. */
-  public double maxPixrad()
-    {
-    Vec3 va = new Vec3(new Zphi(2./3., Math.PI/nl4));
-    double t1 = 1.-1./nside;
-    t1*=t1;
-    Vec3 vb = new Vec3(new Zphi(1-t1/3, 0));
-    return va.angle(vb);
-    }
-
-  private RingInfoSmall get_ring_info_small (long ring)
-    {
-    RingInfoSmall ret = new RingInfoSmall();
-    if (ring<nside)
-      {
-      ret.shifted = true;
-      ret.ringpix = 4*ring;
-      ret.startpix = 2*ring*(ring-1);
-      }
-    else if (ring<nl3)
-      {
-      ret.shifted = ((ring-nside) & 1) == 0;
-      ret.ringpix = nl4;
-      ret.startpix = ncap + (ring-nside)*nl4;
-      }
-    else
-      {
-      ret.shifted = true;
-      long nr=nl4-ring;
-      ret.ringpix = 4*nr;
-      ret.startpix = npix-2*nr*(nr+1);
-      }
-    return ret;
-    }
-
-  private long ringAbove (double z)
-    {
-    double az=Math.abs(z);
-    if (az> Constants.twothird) // polar caps
-      {
-      long iring = (long)(nside*Math.sqrt(3*(1-az)));
-      return (z>0) ? iring : nl4-iring-1;
-      }
-    else // equatorial region
-      return (long)(nside*(2.0-1.5*z));
-    }
-
-  /** Returns the z-coordinate (equivalent to the cosine of the colatitude)
-      for the requested ring.
-      This method also accepts the not-really-existing ring indices 0 and
-      4*Nside, which correspond to North and South Poles, respectively.
-      @param ring ring index: the northernmost ring in the map has index 1;
-        ring indices are increasing towards the South pole.
-      @return z-coordinate of the ring. */
-  public double ring2z (long ring)
-    {
-    if (ring<nside)
-      return 1 - ring*ring*fact2;
-    if (ring <=nl3)
-      return (nl2-ring)*fact1;
-    ring=nl4 - ring;
-    return ring*ring*fact2 - 1;
-    }
-  /** Returns the colatitude for the requested ring.
-      This method also accepts the not-really-existing ring indices 0 and
-      4*Nside, which correspond to North and South Poles, respectively.
-      @param ring ring index: the northernmost ring in the map has index 1;
-        ring indices are increasing towards the South pole.
-      @return z-coordinate of the ring. */
-  public double ring2theta (long ring)
-    {
-    if (ring<nside)
-      {
-      double tmp=ring*ring*fact2;
-      return FastMath.atan2 (Math.sqrt(tmp*(2.-tmp)),1-tmp);
-      }
-    if (ring <=nl3)
-      {
-      double cth=(nl2-ring)*fact1;
-      return FastMath.atan2 (Math.sqrt(1.-cth*cth),cth);
-      }
-    ring=nl4 - ring;
-    double tmp=ring*ring*fact2;
-    return FastMath.atan2 (Math.sqrt(tmp*(2.-tmp)),tmp-1);
-    }
-
-  private final class pstack
-    {
-    private long[] p;
-    private int[] o;
-    private int s, m;
-
-    public pstack (int sz)
-      { p=new long[sz]; o=new int[sz]; s=m=0; }
-    public void push (long p_, int o_)
-      { p[s]=p_; o[s]=o_; ++s; }
-    public void pop ()
-      { --s; }
-    public void popToMark ()
-      { s=m; }
-    public int size ()
-      { return s; }
-    public void mark ()
-      { m=s; }
-    public int otop ()
-      { return o[s-1]; }
-    public long ptop ()
-      { return p[s-1]; }
-    }
-
-  private RangeSet queryStripInternal(double theta1, double theta2,
-    boolean inclusive) throws Exception
-    {
-    RangeSet pixset = new RangeSet(1);
-    if (scheme==Scheme.RING)
-      {
-      long ring1 = Math.max(1,1+ringAbove(FastMath.cos(theta1))),
-           ring2 = Math.min(4*nside-1,ringAbove(FastMath.cos(theta2)));
-      if (inclusive)
-        {
-        ring1 = Math.max(1,ring1-1);
-        ring2 = Math.min(4*nside-1,ring2+1);
-        }
-
-      RingInfoSmall ris1 = get_ring_info_small(ring1),
-                    ris2 = get_ring_info_small(ring2);
-      long pix1 = ris1.startpix,
-           pix2 = ris2.startpix+ris2.ringpix;
-      if (pix1<pix2) pixset.append(pix1,pix2);
-      }
-    else
-      HealpixUtils.check(false,"queryStrip not yet implemented for NESTED");
-
-    return pixset;
-    }
-
-  /** Returns a range set of pixels whose centers lie within a given latitude
-      range (if {@code inclusive==false}), or which overlap with this range
-      (if {@code inclusive==true}).<p>
-      The latitude range is defined as follows:
-      <ul>
-      <li>if {@code theta1<theta2}, it is the range between {@code theta1}
-          and {@code theta2}</li>
-      <li>otherwise it is the range between 0 and {@code theta2}, and between
-          {@code theta1} and pi.</li>
-      </ul>
-      This method currently only works in the RING scheme. */
-  public RangeSet queryStrip(double theta1, double theta2,
-    boolean inclusive) throws Exception
-    {
-    if (theta1<theta2)
-      return queryStripInternal(theta1,theta2,inclusive);
-    RangeSet res = queryStripInternal(0.,theta2,inclusive);
-    return res.union(queryStripInternal(theta1,Math.PI,inclusive));
-    }
-
-  private boolean checkPixelRing (HealpixBase b2, long pix, long nr,
-    long ipix1, int fct, Zphi czphi, double cosrp2, long cpix)
-    {
-    if (pix>=nr) pix-=nr;
-    if (pix<0) pix+=nr;
-    pix+=ipix1;
-    if (pix==cpix) return false; // disk center in pixel => overlap
-    Xyf xyf=pix2xyf(pix);
-    for (int i=0; i<fct-1; ++i) // go along the 4 edges
-      {
-      int ox=fct*xyf.ix, oy=fct*xyf.iy;
-      Xyf xyf2 = new Xyf (ox,oy,xyf.face);
-      double pz,pphi;
-      xyf2.ix=ox+i; xyf2.iy=oy;
-      if (HealpixUtils.cosdist_zphi(czphi,b2.pix2zphi(b2.xyf2pix(xyf2)))>cosrp2)
-        return false; // overlap
-      xyf2.ix=ox+fct-1; xyf2.iy=oy+i;
-      if (HealpixUtils.cosdist_zphi(czphi,b2.pix2zphi(b2.xyf2pix(xyf2)))>cosrp2)
-        return false; // overlap
-      xyf2.ix=ox+fct-1-i; xyf2.iy=oy+fct-1;
-      if (HealpixUtils.cosdist_zphi(czphi,b2.pix2zphi(b2.xyf2pix(xyf2)))>cosrp2)
-        return false; // overlap
-      xyf2.ix=ox; xyf2.iy=oy+fct-1-i;
-      if (HealpixUtils.cosdist_zphi(czphi,b2.pix2zphi(b2.xyf2pix(xyf2)))>cosrp2)
-        return false; // overlap
-      }
-    return true;
-    }
-
-  private RangeSet queryDiscInternal(Pointing ptg, double radius, int fact)
-    throws Exception
-    {
-    boolean inclusive=(fact!=0);
-    RangeSet pixset = new RangeSet();
-    if (scheme==Scheme.RING)
-      {
-      int fct=1;
-      if (inclusive)
-        {
-        HealpixUtils.check ((1L<<order_max)/nside>=fact,
-          "invalid oversampling factor");
-        fct = fact;
-        }
-      HealpixBase b2=null;
-      double rsmall,rbig;
-      if (fct>1)
-        {
-        b2=new HealpixBase(fct*nside,Scheme.RING);
-        rsmall = radius+b2.maxPixrad();
-        rbig = radius+maxPixrad();
-        }
-      else
-        rsmall = rbig = inclusive ? radius+maxPixrad() : radius;
-
-      if (rsmall>=Math.PI)
-        { pixset.append(0,npix); return pixset; }
-
-      rbig = Math.min (Math.PI,rbig);
-
-      double cosrsmall = FastMath.cos(rsmall);
-      double cosrbig = FastMath.cos(rbig);
-
-      double z0 = FastMath.cos(ptg.theta);
-      double xa = 1./Math.sqrt((1-z0)*(1+z0));
-
-      Zphi czphi = new Zphi(z0,ptg.phi);
-      long cpix = zphi2pix(czphi);
-
-      double rlat1  = ptg.theta - rsmall;
-      double zmax = FastMath.cos(rlat1);
-      long irmin = ringAbove (zmax)+1;
-
-      if ((rlat1<=0) && (irmin>1)) // north pole in the disk
-        {
-        RingInfoSmall info =get_ring_info_small(irmin-1);
-        pixset.append(0,info.startpix+info.ringpix);
-        }
-
-      if ((fct>1) && (rlat1>0)) irmin=Math.max(1L,irmin-1);
-
-      double rlat2  = ptg.theta + rsmall;
-      double zmin = FastMath.cos(rlat2);
-      long irmax = ringAbove (zmin);
-
-      if ((fct>1) && (rlat2<Math.PI)) irmax=Math.min(nl4-1,irmax+1);
-
-      for (long iz=irmin; iz<=irmax; ++iz) // rings partially in the disk
-        {
-        double z=ring2z(iz);
-
-        double x = (cosrbig-z*z0)*xa;
-        double ysq = 1-z*z-x*x;
-        double dphi=-1;
-        if (ysq<=0) // no intersection, ring completely inside or outside
-          dphi = (fct==1) ? 0: Math.PI-1e-15;
-        else
-          dphi = FastMath.atan2(Math.sqrt(ysq),x);
-        if (dphi>0)
-          {
-          RingInfoSmall info =get_ring_info_small(iz);
-          long ipix1 = info.startpix, nr=info.ringpix, ipix2=ipix1+nr-1;
-          double shift = info.shifted ? 0.5 : 0.;
-
-          long ip_lo = (long)Math.floor
-            (nr*Constants.inv_twopi*(ptg.phi-dphi) - shift)+1;
-          long ip_hi = (long)Math.floor
-            (nr*Constants.inv_twopi*(ptg.phi+dphi) - shift);
-
-          if (fct>1)
-            {
-            while ((ip_lo<=ip_hi) && checkPixelRing
-                  (b2,ip_lo,nr,ipix1,fct,czphi,cosrsmall,cpix))
-              ++ip_lo;
-            while ((ip_hi>ip_lo) && checkPixelRing
-                  (b2,ip_hi,nr,ipix1,fct,czphi,cosrsmall,cpix))
-              --ip_hi;
-            }
-
-          if (ip_lo<=ip_hi)
-            {
-            if (ip_hi>=nr)
-              { ip_lo-=nr; ip_hi-=nr; }
-            if (ip_lo<0)
-              {
-              pixset.append(ipix1,ipix1+ip_hi+1);
-              pixset.append(ipix1+ip_lo+nr,ipix2+1);
-              }
-            else
-              pixset.append(ipix1+ip_lo,ipix1+ip_hi+1);
-            }
-          }
-        }
-
-      if ((rlat2>=Math.PI) && (irmax+1<nl4)) // south pole in the disk
-        {
-        RingInfoSmall info =get_ring_info_small(irmax+1);
-        pixset.append(info.startpix,npix);
-        }
-      }
-    else // scheme_==NEST
-      {
-      if (radius>=Math.PI) // disk covers the whole sphere
-        { pixset.append(0,npix); return pixset; }
-
-      int oplus=0;
-      if (inclusive)
-        {
-        HealpixUtils.check ((1L<<order_max)>=fact,"invalid oversampling factor");
-        HealpixUtils.check ((fact&(fact-1))==0,
-          "oversampling factor must be a power of 2");
-        oplus=HealpixUtils.ilog2(fact);
-        }
-      int omax=Math.min(order_max,order+oplus); // the order up to which we test
-
-      Vec3 vptg = new Vec3(ptg);
-
-      double[] crpdr = new double[omax+1];
-      double[] crmdr = new double[omax+1];
-
-      double cosrad=FastMath.cos(radius),
-             sinrad=FastMath.sin(radius);
-      for (int o=0; o<=omax; o++) // prepare data at the required orders
-        {
-        double dr = HealpixProc.mpr[o]; // safety distance
-        double cdr = HealpixProc.cmpr[o];
-        double sdr = HealpixProc.smpr[o];
-        crpdr[o] = (radius+dr>Math.PI) ? -1. : cosrad*cdr-sinrad*sdr;
-        crmdr[o] = (radius-dr<0.)      ?  1. : cosrad*cdr+sinrad*sdr;
-        }
-
-      pstack stk=new pstack(12+3*omax);
-
-/* Still experimental, therefore disabled
-      Fxyf fxyf=new Fxyf(vptg);
-      for (int o=order; o>=0; --o)
-        {
-        long nsd=HealpixProc.bn[o].nside;
-        double fx=nsd*fxyf.fx-(int)(nsd*fxyf.fx),
-               fy=nsd*fxyf.fy-(int)(nsd*fxyf.fy);
-        double fmin = Math.min(Math.min(fx,fy),Math.min(1-fx,1-fy));
-        if (fmin*0.7>nsd*radius)
-          {
-          System.out.println("contained completely at order "+o);
-          stk.push(HealpixProc.bn[o].vec2pix(vptg),o);
-          break;
-          }
-        }
-      if (stk.size()==0)
-*/
-
-      for (int i=0; i<12; i++) // insert the 12 base pixels in reverse order
-        stk.push(11-i,0);
-
-      while (stk.size()>0) {// as long as there are pixels on the stack
-        // pop current pixel number and order from the stack
-        long pix=stk.ptop();
-        int o=stk.otop();
-        stk.pop();
-
-        Zphi pos=HealpixProc.bn[o].pix2zphi(pix);
-        // cosine of angular distance between pixel center and disk center
-        double cangdist=HealpixUtils.cosdist_zphi(vptg.z,ptg.phi,pos.z,pos.phi);
-
-        if (cangdist>crpdr[o])
-          {
-          int zone = (cangdist<cosrad) ? 1 : ((cangdist<=crmdr[o]) ? 2 : 3);
-
-          check_pixel (o, omax, zone, pixset, pix, stk, inclusive);
-          }
-        }
-      }
-    return pixset;
-    }
-
-  /** Returns a range set of pixels whose centers lie within a given disk. <p>
-      This method is more efficient in the RING scheme.
-      @param ptg the angular coordinates of the disk center
-      @param radius the radius (in radians) of the disk
-      @return the requested set of pixel number ranges  */
-  public RangeSet queryDisc(Pointing ptg, double radius)
-    throws Exception
-    { return queryDiscInternal (ptg, radius, 0); }
-  /** Returns a range set of pixels which overlap with a given disk. <p>
-      This method is more efficient in the RING scheme. <p>
-      This method may return some pixels which don't overlap with
-      the polygon at all. The higher {@code fact} is chosen, the fewer false
-      positives are returned, at the cost of increased run time.
-      @param ptg the angular coordinates of the disk center
-      @param radius the radius (in radians) of the disk
-      @param fact The overlapping test will be done at the resolution
-        {@code fact*nside}. For NESTED ordering, {@code fact} must be a power
-        of 2, else it can be any positive integer. A typical choice would be 4.
-      @return the requested set of pixel number ranges  */
-  public RangeSet queryDiscInclusive (Pointing ptg, double radius, int fact)
-    throws Exception
-    { return queryDiscInternal (ptg, radius, fact); }
-
-  private RangeSet queryMultiDisc (Vec3[] norm, double[] rad,
-    int fact) throws Exception
-    {
-    boolean inclusive = (fact!=0);
-    int nv=norm.length;
-    HealpixUtils.check(nv==rad.length,"inconsistent input arrays");
-    RangeSet res = new RangeSet();
-
-    if (scheme==Scheme.RING)
-      {
-      int fct=1;
-      if (inclusive)
-        {
-        HealpixUtils.check (((1L<<order_max)/nside)>=fact,
-          "invalid oversampling factor");
-        fct = fact;
-        }
-      HealpixBase b2=null;
-      double rpsmall,rpbig;
-      if (fct>1)
-        {
-        b2=new HealpixBase(fct*nside,Scheme.RING);
-        rpsmall = b2.maxPixrad();
-        rpbig = maxPixrad();
-        }
-      else
-        rpsmall = rpbig = inclusive ? maxPixrad() : 0;
-
-      long irmin=1, irmax=nl4-1;
-      int nd=0;
-      double[] z0=new double[nv];
-      double[] xa=new double[nv];
-      double[] cosrsmall=new double[nv];
-      double[] cosrbig=new double[nv];
-      Pointing[] ptg=new Pointing[nv];
-      long[] cpix=new long[nv];
-      Zphi[] czphi=new Zphi[nv];
-      for (int i=0; i<nv; ++i)
-        {
-        double rsmall=rad[i]+rpsmall;
-        if (rsmall<Math.PI)
-          {
-          double rbig = Math.min(Math.PI,rad[i]+rpbig);
-          Pointing pnt= new Pointing(norm[i]);
-          cosrsmall[nd]=FastMath.cos(rsmall);
-          cosrbig[nd]=FastMath.cos(rbig);
-          double cth=FastMath.cos(pnt.theta);
-          z0[nd]=cth;
-          if (fct>1) cpix[nd]=zphi2pix(new Zphi(cth,pnt.phi));
-          if (fct>1) czphi[nd]=new Zphi(cth,pnt.phi);
-          xa[nd]=1./Math.sqrt((1-cth)*(1+cth));
-          ptg[nd]=pnt;
-
-          double rlat1 = pnt.theta - rsmall;
-          double zmax = FastMath.cos(rlat1);
-          long irmin_t = (rlat1<=0) ? 1 : ringAbove (zmax)+1;
-
-          if ((fct>1) && (rlat1>0)) irmin_t=Math.max(1L,irmin_t-1);
-
-          double rlat2 = pnt.theta + rsmall;
-          double zmin = FastMath.cos(rlat2);
-          long irmax_t = (rlat2>=Math.PI) ? nl4-1 : ringAbove (zmin);
-
-          if ((fct>1) && (rlat2<Math.PI))
-            irmax_t=Math.min(nl4-1,irmax_t+1);
-          if (irmax_t < irmax) irmax=irmax_t;
-          if (irmin_t > irmin) irmin=irmin_t;
-
-          ++nd;
-          }
-        }
-
-      for (long iz=irmin; iz<=irmax; ++iz)
-        {
-        double z=ring2z(iz);
-        RingInfoSmall ris=get_ring_info_small(iz);
-        long ipix1=ris.startpix, nr=ris.ringpix;
-        long ipix2 = ipix1 + nr - 1; // highest pixel number in the ring
-        double shift = ris.shifted ? 0.5 : 0.;
-        RangeSet rstmp = new RangeSet();
-        rstmp.append(ipix1,ipix2+1);
-
-        for (int j=0; (j<nd)&&(rstmp.nranges()>0); ++j)
-          {
-          double x = (cosrbig[j]-z*z0[j])*xa[j];
-          double ysq = 1.-z*z-x*x;
-          double dphi = (ysq<=0) ? Math.PI-1e-15 :
-                                   FastMath.atan2(Math.sqrt(ysq),x);
-
-          long ip_lo = (long)Math.floor
-            (nr*Constants.inv_twopi*(ptg[j].phi-dphi)-shift)+1;
-          long ip_hi = (long)Math.floor
-            (nr*Constants.inv_twopi*(ptg[j].phi+dphi)-shift);
-
-          if (fct>1)
-            {
-            while ((ip_lo<=ip_hi) && checkPixelRing
-                  (b2,ip_lo,nr,ipix1,fct,czphi[j],cosrsmall[j],cpix[j]))
-              ++ip_lo;
-            while ((ip_hi>ip_lo) && checkPixelRing
-                  (b2,ip_hi,nr,ipix1,fct,czphi[j],cosrsmall[j],cpix[j]))
-              --ip_hi;
-            }
-
-          if (ip_hi>=nr)
-            { ip_lo-=nr; ip_hi-=nr;}
-
-          if (ip_lo<0)
-            {
-            if (ip_hi+1<=ip_lo+nr-1)
-              rstmp.remove(ipix1+ip_hi+1,ipix1+ip_lo+nr);
-            }
-          else
-            rstmp.intersect(ipix1+ip_lo,ipix1+ip_hi+1);
-          }
-        res.append(rstmp);
-        }
-      }
-    else // scheme == NEST
-      {
-      int oplus = 0;
-      if (inclusive)
-        {
-        HealpixUtils.check ((1L<<(order_max-order))>=fact,
-          "invalid oversampling factor");
-        HealpixUtils.check ((fact&(fact-1))==0,
-          "oversampling factor must be a power of 2");
-        oplus=HealpixUtils.ilog2(fact);
-        }
-      int omax=order+oplus; // the order up to which we test
-
-      // TODO: ignore all disks with radius>=pi
-
-      double[][][] crlimit=new double[omax+1][nv][3];
-      for (int o=0; o<=omax; ++o) // prepare data at the required orders
-        {
-        double dr=HealpixProc.bn[o].maxPixrad(); // safety distance
-        for (int i=0; i<nv; ++i)
-          {
-          crlimit[o][i][0] = (rad[i]+dr>Math.PI) ? -1: FastMath.cos(rad[i]+dr);
-          crlimit[o][i][1] = (o==0) ? FastMath.cos(rad[i]) : crlimit[0][i][1];
-          crlimit[o][i][2] = (rad[i]-dr<0.) ?  1. : FastMath.cos(rad[i]-dr);
-          }
-        }
-
-      pstack stk=new pstack(12+3*omax);
-      for (int i=0; i<12; i++) // insert the 12 base pixels in reverse order
-        stk.push(11-i,0);
-
-      while (stk.size()>0) { // as long as there are pixels on the stack
-        // pop current pixel number and order from the stack
-        long pix=stk.ptop();
-        int o=stk.otop();
-        stk.pop();
-
-        Vec3 pv = HealpixProc.bn[o].pix2vec(pix);
-
-        int zone=3;
-        for (int i=0; (i<nv)&&(zone>0); ++i)
-          {
-          double crad=pv.dot(norm[i]);
-          for (int iz=0; iz<zone; ++iz)
-            if (crad<crlimit[o][i][iz])
-              zone=iz;
-          }
-
-        if (zone>0) check_pixel (o, omax, zone, res, pix, stk, inclusive);
-        }
-      }
-    return res;
-    }
-
-  private RangeSet queryPolygonInternal (Pointing[] vertex, int fact)
-    throws Exception
-    {
-    boolean inclusive = (fact!=0);
-    int nv=vertex.length;
-    int ncirc = inclusive ? nv+1 : nv;
-    HealpixUtils.check(nv>=3,"not enough vertices in polygon");
-    Vec3[] vv = new Vec3[nv];
-    for (int i=0; i<nv; ++i)
-      vv[i] = new Vec3(vertex[i]);
-    Vec3[] normal = new Vec3[ncirc];
-    int flip=0;
-    for (int i=0; i<nv; ++i)
-      {
-      normal[i]=vv[i].cross(vv[(i+1)%nv]).norm();
-      double hnd=normal[i].dot(vv[(i+2)%nv]);
-      HealpixUtils.check(Math.abs(hnd)>1e-10,"degenerate corner");
-      if (i==0)
-        flip = (hnd<0.) ? -1 : 1;
-      else
-        HealpixUtils.check(flip*hnd>0,"polygon is not convex");
-      normal[i].scale(flip);
-      }
-    double[] rad = new double[ncirc];
-    Arrays.fill(rad,Constants.halfpi);
-    if (inclusive)
-      {
-      CircleFinder cf = new CircleFinder(vv);
-      normal[nv]=cf.getCenter();
-      rad[nv]=FastMath.acos(cf.getCosrad());
-      }
-    return queryMultiDisc(normal,rad,fact);
-    }
-  /** Returns a range set of pixels whose centers lie within the convex
-      polygon defined by the {@code vertex} array. <p>
-      This method is more efficient in the RING scheme.
-      @param vertex an array containing the vertices of the requested convex
-        polygon.
-      @return the requested set of pixel number ranges  */
-  public RangeSet queryPolygon (Pointing[] vertex) throws Exception
-    { return queryPolygonInternal (vertex, 0); }
-  /** Returns a range set of pixels that overlap with the convex
-      polygon defined by the {@code vertex} array. <p>
-      This method is more efficient in the RING scheme.<p>
-      This method may return some pixels which don't overlap with
-      the polygon at all. The higher {@code fact} is chosen, the fewer false
-      positives are returned, at the cost of increased run time.
-      @param vertex an array containing the vertices of the requested convex
-        polygon.
-      @param fact The overlapping test will be done at the resolution
-        {@code fact*nside}. For NESTED ordering, {@code fact} must be a power
-        of 2, else it can be any positive integer. A typical choice would be 4.
-      @return the requested set of pixel number ranges  */
-  public RangeSet queryPolygonInclusive (Pointing[] vertex, int fact)
-    throws Exception
-    { return queryPolygonInternal (vertex, fact); }
-
-  private void check_pixel (int o, int omax, int zone,
-    RangeSet pixset, long pix, pstack stk, boolean inclusive)
-    {
-    if (zone==0) return;
-
-    if (o<order)
-      {
-      if (zone>=3) // output all subpixels
-        {
-        int sdist=2*(order-o); // the "bit-shift distance" between map orders
-        pixset.append(pix<<sdist,((pix+1)<<sdist));
-        }
-      else // (zone>=1)
-        for (int i=0; i<4; ++i)
-          stk.push(4*pix+3-i,o+1); // add children
-      }
-    else if (o>order) // this implies that inclusive==true
-      {
-      if (zone>=2) // pixel center in shape
-        {
-        pixset.append(pix>>>(2*(o-order))); // output the parent pixel at order
-        stk.popToMark(); // unwind the stack
-        }
-      else // (zone>=1): pixel center in safety range
-        {
-        if (o<omax) // check sublevels
-          for (int i=0; i<4; ++i) // add children in reverse order
-            stk.push(4*pix+3-i,o+1); // add children
-        else // at resolution limit
-          {
-          pixset.append(pix>>>(2*(o-order)));// output the parent pixel at order
-          stk.popToMark(); // unwind the stack
-          }
-        }
-      }
-    else // o==order
-      {
-      if (zone>=2)
-        pixset.append(pix);
-      else if (inclusive) // and (zone>=1)
-        {
-        if (order<omax) // check sublevels
-          {
-          stk.mark(); // remember current stack position
-          for (int i=0; i<4; ++i) // add children in reverse order
-            stk.push(4*pix+3-i,o+1); // add children
-          }
-        else // at resolution limit
-          pixset.append(pix); // output the pixel
-        }
-      }
-    }
-
-  /** Compute ring index from pixel number.
-      Works in both RING and NESTED schemes
-      @param pix pixel number
-      @return ring index (1 to 4Nside-1) */
-  public long pix2ring (long pix)
-    {
-    if (scheme==Scheme.RING)
-      {
-      if (pix<ncap) // North Polar cap
-        return (1+HealpixUtils.isqrt(1+2*pix))>>>1; // counted from North pole
-      else if (pix<(npix-ncap)) // Equatorial region
-        return (pix-ncap)/nl4 + nside; // counted from North pole
-      else // South Polar cap
-        return nl4-((1+HealpixUtils.isqrt(2*(npix-pix)-1))>>>1);
-      }
-    else
-      {
-      Xyf xyf = nest2xyf(pix);
-      return ((long)(jrll[xyf.face])<<order) - xyf.ix - xyf.iy - 1;
-      }
-    }
-
-  /** Returns a set of points along the boundary of the given pixel.
-    * Step 1 gives 4 points on the corners. The first point corresponds
-    * to the northernmost corner, the subsequent points follow the pixel
-    * boundary through west, south and east corners.
-    *
-    * @param pix pixel index number
-    * @param step the number of returned points is 4*step
-    * @return {@link Vec3} for each point
-    * @throws Exception
-    */
-  public Vec3[] boundaries(long pix, int step) throws Exception
-    {
-    HealpixUtils.check(step>0,"step must be positive");
-    Vec3[] points = new Vec3[4*step];
-    Xyf xyf = pix2xyf(pix);
-    double dc=0.5/nside;
-    double xc=(xyf.ix+0.5)/nside, yc=(xyf.iy+0.5)/nside;
-    double d = 1./(step*nside);
-    for (int i=0; i<step; ++i)
-      {
-      points[i       ]=new Fxyf(xc+dc-i*d, yc+dc, xyf.face).toVec3();
-      points[i+  step]=new Fxyf(xc-dc, yc+dc-i*d, xyf.face).toVec3();
-      points[i+2*step]=new Fxyf(xc-dc+i*d, yc-dc, xyf.face).toVec3();
-      points[i+3*step]=new Fxyf(xc+dc, yc-dc+i*d, xyf.face).toVec3();
-      }
-    return points;
-    }
-  }
diff -Nru healpix-java-3.40/src/healpix/essentials/HealpixMapDouble.java healpix-java-3.50/src/healpix/essentials/HealpixMapDouble.java
--- healpix-java-3.40/src/healpix/essentials/HealpixMapDouble.java	2014-10-24 05:23:50.000000000 -0400
+++ healpix-java-3.50/src/healpix/essentials/HealpixMapDouble.java	1969-12-31 19:00:00.000000000 -0500
@@ -1,227 +0,0 @@
-/*
- *  This file is part of Healpix Java.
- *
- *  This code 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 code 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 code; 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.sourceforge.net
- */
-
-package healpix.essentials;
-
-import java.util.Arrays;
-
-/** Class representing a full HEALPix map containing double values.
-    This class is conceptually very similar the the Healpix_Map<double>
-    class of Healpix_cxx.
-
-    @copyright 2011,2012 Max-Planck-Society
-    @author Martin Reinecke */
-public class HealpixMapDouble extends HealpixBase
-  {
-  private double[] data;
-
-  public static final double undef=-1.6375e30;
-
-  public HealpixMapDouble() throws Exception
-    { this(1,Scheme.NESTED); }
-  public HealpixMapDouble(long nside_in, Scheme scheme_in) throws Exception
-    {
-    super(nside_in,scheme_in);
-    HealpixUtils.check(nside<=(1<<13),"resolution too high");
-    data=new double[(int)getNpix()];
-    }
-  public HealpixMapDouble(double[] data_in, Scheme scheme_in) throws Exception
-    {
-    super(npix2Nside(data_in.length),scheme_in);
-    HealpixUtils.check(nside<=(1<<13),"resolution too high");
-    data=data_in;
-    }
-
-  /** Adjusts the object to nside_in.
-      @param nside_in the new Nside parameter */
-  public void setNside (long nside_in) throws Exception
-    {
-    if (nside_in!=nside)
-      {
-      super.setNside(nside_in);
-      HealpixUtils.check(nside<=(1<<13),"resolution too high");
-      data=new double[(int)getNpix()];
-      }
-    }
-
-  /** Adjusts the object to nside_in and scheme_in.
-      @param nside_in the new Nside parameter
-      @param scheme_in the new ordering scheme */
-  public void setNsideAndScheme (long nside_in, Scheme scheme_in)
-    throws Exception
-    {
-    super.setNsideAndScheme(nside_in,scheme_in);
-    HealpixUtils.check(nside<=(1<<13),"resolution too high");
-    data=new double[(int)getNpix()];
-    }
-
-  /** Adjusts the object to scheme_in, and sets pixel data to data_in.
-      @param data_in pixel data; must have a valid length (12*nside^2)
-      @param scheme_in the new ordering scheme */
-  public void setDataAndScheme(double[] data_in, Scheme scheme_in)
-    throws Exception
-    {
-    super.setNsideAndScheme(npix2Nside(data_in.length),scheme_in);
-    data=data_in;
-    }
-
-  /** Sets all map pixel to a specific value.
-      @param val pixel value to use */
-  public void fill(double val)
-    { Arrays.fill(data,val); }
-
-  /** Converts the map from NESTED to RING scheme or vice versa.
-      This operation is done in-place, i.e. it does not require additional
-      memory. */
-  public void swapScheme() throws Exception
-    {
-    HealpixUtils.check((order>=0) && (order<=13),
-      "swapping not supported for this Nside");
-    for (int m=0; m<swap_cycle[order].length; ++m)
-      {
-      int istart = swap_cycle[order][m];
-
-      double pixbuf = data[istart];
-      long iold = istart,
-           inew = (scheme==Scheme.RING) ? nest2ring(istart) : ring2nest(istart);
-      while (inew != istart)
-        {
-        data[(int)iold] = data[(int)inew];
-        iold = inew;
-        inew = (scheme==Scheme.RING) ? nest2ring(inew) : ring2nest(inew);
-        }
-      data[(int)iold] = pixbuf;
-      }
-    scheme = (scheme==Scheme.RING) ? Scheme.NESTED : Scheme.RING;
-    }
-
-  /** Returns the value of the pixel with a given index.
-      @param ipix index of the requested pixel
-      @return pixel value */
-  public double getPixel(int ipix)
-    { return data[ipix]; }
-  /** Returns the value of the pixel with a given index.
-      @param ipix index of the requested pixel
-      @return pixel value */
-  public double getPixel(long ipix)
-    { return data[(int)ipix]; }
-  /** Sets the value of a specific pixel.
-      @param ipix index of the pixel
-      @param val new value for the pixel */
-  public void setPixel(int ipix, double val)
-    { data[ipix] = val; }
-  /** Sets the value of a specific pixel.
-      @param ipix index of the pixel
-      @param val new value for the pixel */
-  public void setPixel(long ipix, double val)
-    { data[(int)ipix] = val; }
-
-  /** Returns the array containing all map pixels.
-      @return the map array */
-  public double[] getData()
-    { return data; }
-
-  /** Imports the map "orig" to this object, adjusting pixel ordering.
-      @param orig map to import */
-  public void importNograde (HealpixMapDouble orig) throws Exception
-    {
-    HealpixUtils.check (nside==orig.nside,
-      "importNograde: maps have different nside");
-    if (orig.scheme == scheme)
-      System.arraycopy(orig.data,0,data,0,(int)npix);
-    else
-      for (int m=0; m<npix; ++m)
-        data[scheme==Scheme.NESTED ? (int)ring2nest(m) : (int)nest2ring(m)]
-          = orig.data[m];
-    }
-  /** Imports the map "orig" to this object, adjusting pixel ordering
-      and increasing resolution.
-      @param orig map to import */
-  public void importUpgrade (HealpixMapDouble orig) throws Exception
-    {
-    HealpixUtils.check(nside>orig.nside,"importUpgrade: this is no upgrade");
-    int fact = (int)(nside/orig.nside);
-    HealpixUtils.check(nside==orig.nside*fact,
-      "the larger Nside must be a multiple of the smaller one");
-
-    for (int m=0; m<orig.npix; ++m)
-      {
-      Xyf xyf = orig.pix2xyf(m);
-      int x=xyf.ix, y=xyf.iy, f=xyf.face;
-      for (int j=fact*y; j<fact*(y+1); ++j)
-        for (int i=fact*x; i<fact*(x+1); ++i)
-          {
-          long mypix = xyf2pix(i,j,f);
-          data[(int)mypix] = orig.data[m];
-          }
-      }
-    }
-  /** Imports the map "orig" to this object, adjusting pixel ordering
-      and reducing resolution.
-      @param orig map to import
-      @param pessimistic if true, set a pixel to undefined if at least one the
-        original subpixels was undefined; otherwise only set it to undefined if
-        all original subpixels were undefined. */
-  public void importDegrade (HealpixMapDouble orig, boolean pessimistic)
-    throws Exception
-    {
-    HealpixUtils.check(nside<orig.nside,"importDegrade: this is no degrade");
-    int fact = (int)(orig.nside/nside);
-    HealpixUtils.check(orig.nside==nside*fact,
-      "the larger Nside must be a multiple of the smaller one");
-
-    int minhits = pessimistic ? fact*fact : 1;
-    for (int m=0; m<npix; ++m)
-      {
-      Xyf xyf = pix2xyf(m);
-      int x=xyf.ix, y=xyf.iy, f=xyf.face;
-      int hits = 0;
-      double sum = 0;
-      for (int j=fact*y; j<fact*(y+1); ++j)
-        for (int i=fact*x; i<fact*(x+1); ++i)
-          {
-          int opix = (int)orig.xyf2pix(i,j,f);
-          if (!HealpixUtils.approx(orig.data[opix],undef,1e-5))
-            {
-            ++hits;
-            sum += orig.data[opix];
-            }
-          }
-      data[m] = (hits<minhits) ? undef : (sum/hits);
-      }
-    }
-  /** Imports the map "orig" to this object, adjusting pixel ordering
-      and resolution if necessary.
-      @param orig map to import
-      @param pessimistic only used when resolution must be reduced: if true,
-        set a pixel to undefined if at least one the original subpixels
-        was undefined; otherwise only set it to undefined if all original
-        subpixels were undefined. */
-  public void importGeneral (HealpixMapDouble orig, boolean pessimistic)
-    throws Exception
-    {
-    if (orig.nside==nside)
-      importNograde(orig);
-    else if (orig.nside<nside) // upgrading
-      importUpgrade(orig);
-    else
-      importDegrade(orig,pessimistic);
-    }
-  }
diff -Nru healpix-java-3.40/src/healpix/essentials/HealpixMapFloat.java healpix-java-3.50/src/healpix/essentials/HealpixMapFloat.java
--- healpix-java-3.40/src/healpix/essentials/HealpixMapFloat.java	2014-10-24 05:23:50.000000000 -0400
+++ healpix-java-3.50/src/healpix/essentials/HealpixMapFloat.java	1969-12-31 19:00:00.000000000 -0500
@@ -1,227 +0,0 @@
-/*
- *  This file is part of Healpix Java.
- *
- *  This code 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 code 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 code; 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.sourceforge.net
- */
-
-package healpix.essentials;
-
-import java.util.Arrays;
-
-/** Class representing a full HEALPix map containing float values.
-    This class is conceptually very similar the the Healpix_Map<float>
-    class of Healpix_cxx.
-
-    @copyright 2011,2012 Max-Planck-Society
-    @author Martin Reinecke */
-public class HealpixMapFloat extends HealpixBase
-  {
-  private float[] data;
-
-  public static final float undef=(float)(-1.6375e30);
-
-  public HealpixMapFloat() throws Exception
-    { this(1,Scheme.NESTED); }
-  public HealpixMapFloat(long nside_in, Scheme scheme_in) throws Exception
-    {
-    super(nside_in,scheme_in);
-    HealpixUtils.check(nside<=(1<<13),"resolution too high");
-    data=new float[(int)getNpix()];
-    }
-  public HealpixMapFloat(float[] data_in, Scheme scheme_in) throws Exception
-    {
-    super(npix2Nside(data_in.length),scheme_in);
-    HealpixUtils.check(nside<=(1<<13),"resolution too high");
-    data=data_in;
-    }
-
-  /** Adjusts the object to nside_in.
-      @param nside_in the new Nside parameter */
-  public void setNside (long nside_in) throws Exception
-    {
-    if (nside_in!=nside)
-      {
-      super.setNside(nside_in);
-      HealpixUtils.check(nside<=(1<<13),"resolution too high");
-      data=new float[(int)getNpix()];
-      }
-    }
-
-  /** Adjusts the object to nside_in and scheme_in.
-      @param nside_in the new Nside parameter
-      @param scheme_in the new ordering scheme */
-  public void setNsideAndScheme (long nside_in, Scheme scheme_in)
-    throws Exception
-    {
-    super.setNsideAndScheme(nside_in,scheme_in);
-    HealpixUtils.check(nside<=(1<<13),"resolution too high");
-    data=new float[(int)getNpix()];
-    }
-
-  /** Adjusts the object to scheme_in, and sets pixel data to data_in.
-      @param data_in pixel data; must have a valid length (12*nside^2)
-      @param scheme_in the new ordering scheme */
-  public void setDataAndScheme(float[] data_in, Scheme scheme_in)
-    throws Exception
-    {
-    super.setNsideAndScheme(npix2Nside(data_in.length),scheme_in);
-    data=data_in;
-    }
-
-  /** Sets all map pixel to a specific value.
-      @param val pixel value to use */
-  public void fill(float val)
-    { Arrays.fill(data,val); }
-
-  /** Converts the map from NESTED to RING scheme or vice versa.
-      This operation is done in-place, i.e. it does not require additional
-      memory. */
-  public void swapScheme() throws Exception
-    {
-    HealpixUtils.check((order>=0) && (order<=13),
-      "swapping not supported for this Nside");
-    for (int m=0; m<swap_cycle[order].length; ++m)
-      {
-      int istart = swap_cycle[order][m];
-
-      float pixbuf = data[istart];
-      long iold = istart,
-           inew = (scheme==Scheme.RING) ? nest2ring(istart) : ring2nest(istart);
-      while (inew != istart)
-        {
-        data[(int)iold] = data[(int)inew];
-        iold = inew;
-        inew = (scheme==Scheme.RING) ? nest2ring(inew) : ring2nest(inew);
-        }
-      data[(int)iold] = pixbuf;
-      }
-    scheme = (scheme==Scheme.RING) ? Scheme.NESTED : Scheme.RING;
-    }
-
-  /** Returns the value of the pixel with a given index.
-      @param ipix index of the requested pixel
-      @return pixel value */
-  public float getPixel(int ipix)
-    { return data[ipix]; }
-  /** Returns the value of the pixel with a given index.
-      @param ipix index of the requested pixel
-      @return pixel value */
-  public float getPixel(long ipix)
-    { return data[(int)ipix]; }
-  /** Sets the value of a specific pixel.
-      @param ipix index of the pixel
-      @param val new value for the pixel */
-  public void setPixel(int ipix, float val)
-    { data[ipix] = val; }
-  /** Sets the value of a specific pixel.
-      @param ipix index of the pixel
-      @param val new value for the pixel */
-  public void setPixel(long ipix, float val)
-    { data[(int)ipix] = val; }
-
-  /** Returns the array containing all map pixels.
-      @return the map array */
-  public float[] getData()
-    { return data; }
-
-  /** Imports the map "orig" to this object, adjusting pixel ordering.
-      @param orig map to import */
-  public void importNograde (HealpixMapFloat orig) throws Exception
-    {
-    HealpixUtils.check (nside==orig.nside,
-      "importNograde: maps have different nside");
-    if (orig.scheme == scheme)
-      System.arraycopy(orig.data,0,data,0,(int)npix);
-    else
-      for (int m=0; m<npix; ++m)
-        data[scheme==Scheme.NESTED ? (int)ring2nest(m) : (int)nest2ring(m)]
-          = orig.data[m];
-    }
-  /** Imports the map "orig" to this object, adjusting pixel ordering
-      and increasing resolution.
-      @param orig map to import */
-  public void importUpgrade (HealpixMapFloat orig) throws Exception
-    {
-    HealpixUtils.check(nside>orig.nside,"importUpgrade: this is no upgrade");
-    int fact = (int)(nside/orig.nside);
-    HealpixUtils.check(nside==orig.nside*fact,
-      "the larger Nside must be a multiple of the smaller one");
-
-    for (int m=0; m<orig.npix; ++m)
-      {
-      Xyf xyf = orig.pix2xyf(m);
-      int x=xyf.ix, y=xyf.iy, f=xyf.face;
-      for (int j=fact*y; j<fact*(y+1); ++j)
-        for (int i=fact*x; i<fact*(x+1); ++i)
-          {
-          long mypix = xyf2pix(i,j,f);
-          data[(int)mypix] = orig.data[m];
-          }
-      }
-    }
-  /** Imports the map "orig" to this object, adjusting pixel ordering
-      and reducing resolution.
-      @param orig map to import
-      @param pessimistic if true, set a pixel to undefined if at least one the
-        original subpixels was undefined; otherwise only set it to undefined if
-        all original subpixels were undefined. */
-  public void importDegrade (HealpixMapFloat orig, boolean pessimistic)
-    throws Exception
-    {
-    HealpixUtils.check(nside<orig.nside,"importDegrade: this is no degrade");
-    int fact = (int)(orig.nside/nside);
-    HealpixUtils.check(orig.nside==nside*fact,
-      "the larger Nside must be a multiple of the smaller one");
-
-    int minhits = pessimistic ? fact*fact : 1;
-    for (int m=0; m<npix; ++m)
-      {
-      Xyf xyf = pix2xyf(m);
-      int x=xyf.ix, y=xyf.iy, f=xyf.face;
-      int hits = 0;
-      double sum = 0;
-      for (int j=fact*y; j<fact*(y+1); ++j)
-        for (int i=fact*x; i<fact*(x+1); ++i)
-          {
-          int opix = (int)orig.xyf2pix(i,j,f);
-          if (!HealpixUtils.approx(orig.data[opix],undef,1e-5))
-            {
-            ++hits;
-            sum += orig.data[opix];
-            }
-          }
-      data[m] = (hits<minhits) ? undef : (float) (sum/hits);
-      }
-    }
-  /** Imports the map "orig" to this object, adjusting pixel ordering
-      and resolution if necessary.
-      @param orig map to import
-      @param pessimistic only used when resolution must be reduced: if true,
-        set a pixel to undefined if at least one the original subpixels
-        was undefined; otherwise only set it to undefined if all original
-        subpixels were undefined. */
-  public void importGeneral (HealpixMapFloat orig, boolean pessimistic)
-    throws Exception
-    {
-    if (orig.nside==nside)
-      importNograde(orig);
-    else if (orig.nside<nside) // upgrading
-      importUpgrade(orig);
-    else
-      importDegrade(orig,pessimistic);
-    }
-  }
diff -Nru healpix-java-3.40/src/healpix/essentials/HealpixMap.tmpl healpix-java-3.50/src/healpix/essentials/HealpixMap.tmpl
--- healpix-java-3.40/src/healpix/essentials/HealpixMap.tmpl	2014-10-24 05:23:50.000000000 -0400
+++ healpix-java-3.50/src/healpix/essentials/HealpixMap.tmpl	1969-12-31 19:00:00.000000000 -0500
@@ -1,227 +0,0 @@
-/*
- *  This file is part of Healpix Java.
- *
- *  This code 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 code 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 code; 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.sourceforge.net
- */
-
-package healpix.essentials;
-
-import java.util.Arrays;
-
-/** Class representing a full HEALPix map containing <type> values.
-    This class is conceptually very similar the the Healpix_Map<<type>>
-    class of Healpix_cxx.
-
-    @copyright 2011,2012 Max-Planck-Society
-    @author Martin Reinecke */
-public class HealpixMap<Type> extends HealpixBase
-  {
-  private <type>[] data;
-
-  public static final <type> undef=(<type>)(-1.6375e30);
-
-  public HealpixMap<Type>() throws Exception
-    { this(1,Scheme.NESTED); }
-  public HealpixMap<Type>(long nside_in, Scheme scheme_in) throws Exception
-    {
-    super(nside_in,scheme_in);
-    HealpixUtils.check(nside<=(1<<13),"resolution too high");
-    data=new <type>[(int)getNpix()];
-    }
-  public HealpixMap<Type>(<type>[] data_in, Scheme scheme_in) throws Exception
-    {
-    super(npix2Nside(data_in.length),scheme_in);
-    HealpixUtils.check(nside<=(1<<13),"resolution too high");
-    data=data_in;
-    }
-
-  /** Adjusts the object to nside_in.
-      @param nside_in the new Nside parameter */
-  public void setNside (long nside_in) throws Exception
-    {
-    if (nside_in!=nside)
-      {
-      super.setNside(nside_in);
-      HealpixUtils.check(nside<=(1<<13),"resolution too high");
-      data=new <type>[(int)getNpix()];
-      }
-    }
-
-  /** Adjusts the object to nside_in and scheme_in.
-      @param nside_in the new Nside parameter
-      @param scheme_in the new ordering scheme */
-  public void setNsideAndScheme (long nside_in, Scheme scheme_in)
-    throws Exception
-    {
-    super.setNsideAndScheme(nside_in,scheme_in);
-    HealpixUtils.check(nside<=(1<<13),"resolution too high");
-    data=new <type>[(int)getNpix()];
-    }
-
-  /** Adjusts the object to scheme_in, and sets pixel data to data_in.
-      @param data_in pixel data; must have a valid length (12*nside^2)
-      @param scheme_in the new ordering scheme */
-  public void setDataAndScheme(<type>[] data_in, Scheme scheme_in)
-    throws Exception
-    {
-    super.setNsideAndScheme(npix2Nside(data_in.length),scheme_in);
-    data=data_in;
-    }
-
-  /** Sets all map pixel to a specific value.
-      @param val pixel value to use */
-  public void fill(<type> val)
-    { Arrays.fill(data,val); }
-
-  /** Converts the map from NESTED to RING scheme or vice versa.
-      This operation is done in-place, i.e. it does not require additional
-      memory. */
-  public void swapScheme() throws Exception
-    {
-    HealpixUtils.check((order>=0) && (order<=13),
-      "swapping not supported for this Nside");
-    for (int m=0; m<swap_cycle[order].length; ++m)
-      {
-      int istart = swap_cycle[order][m];
-
-      <type> pixbuf = data[istart];
-      long iold = istart,
-           inew = (scheme==Scheme.RING) ? nest2ring(istart) : ring2nest(istart);
-      while (inew != istart)
-        {
-        data[(int)iold] = data[(int)inew];
-        iold = inew;
-        inew = (scheme==Scheme.RING) ? nest2ring(inew) : ring2nest(inew);
-        }
-      data[(int)iold] = pixbuf;
-      }
-    scheme = (scheme==Scheme.RING) ? Scheme.NESTED : Scheme.RING;
-    }
-
-  /** Returns the value of the pixel with a given index.
-      @param ipix index of the requested pixel
-      @return pixel value */
-  public <type> getPixel(int ipix)
-    { return data[ipix]; }
-  /** Returns the value of the pixel with a given index.
-      @param ipix index of the requested pixel
-      @return pixel value */
-  public <type> getPixel(long ipix)
-    { return data[(int)ipix]; }
-  /** Sets the value of a specific pixel.
-      @param ipix index of the pixel
-      @param val new value for the pixel */
-  public void setPixel(int ipix, <type> val)
-    { data[ipix] = val; }
-  /** Sets the value of a specific pixel.
-      @param ipix index of the pixel
-      @param val new value for the pixel */
-  public void setPixel(long ipix, <type> val)
-    { data[(int)ipix] = val; }
-
-  /** Returns the array containing all map pixels.
-      @return the map array */
-  public <type>[] getData()
-    { return data; }
-
-  /** Imports the map "orig" to this object, adjusting pixel ordering.
-      @param orig map to import */
-  public void importNograde (HealpixMap<Type> orig) throws Exception
-    {
-    HealpixUtils.check (nside==orig.nside,
-      "importNograde: maps have different nside");
-    if (orig.scheme == scheme)
-      System.arraycopy(orig.data,0,data,0,(int)npix);
-    else
-      for (int m=0; m<npix; ++m)
-        data[scheme==Scheme.NESTED ? (int)ring2nest(m) : (int)nest2ring(m)]
-          = orig.data[m];
-    }
-  /** Imports the map "orig" to this object, adjusting pixel ordering
-      and increasing resolution.
-      @param orig map to import */
-  public void importUpgrade (HealpixMap<Type> orig) throws Exception
-    {
-    HealpixUtils.check(nside>orig.nside,"importUpgrade: this is no upgrade");
-    int fact = (int)(nside/orig.nside);
-    HealpixUtils.check(nside==orig.nside*fact,
-      "the larger Nside must be a multiple of the smaller one");
-
-    for (int m=0; m<orig.npix; ++m)
-      {
-      Xyf xyf = orig.pix2xyf(m);
-      int x=xyf.ix, y=xyf.iy, f=xyf.face;
-      for (int j=fact*y; j<fact*(y+1); ++j)
-        for (int i=fact*x; i<fact*(x+1); ++i)
-          {
-          long mypix = xyf2pix(i,j,f);
-          data[(int)mypix] = orig.data[m];
-          }
-      }
-    }
-  /** Imports the map "orig" to this object, adjusting pixel ordering
-      and reducing resolution.
-      @param orig map to import
-      @param pessimistic if true, set a pixel to undefined if at least one the
-        original subpixels was undefined; otherwise only set it to undefined if
-        all original subpixels were undefined. */
-  public void importDegrade (HealpixMap<Type> orig, boolean pessimistic)
-    throws Exception
-    {
-    HealpixUtils.check(nside<orig.nside,"importDegrade: this is no degrade");
-    int fact = (int)(orig.nside/nside);
-    HealpixUtils.check(orig.nside==nside*fact,
-      "the larger Nside must be a multiple of the smaller one");
-
-    int minhits = pessimistic ? fact*fact : 1;
-    for (int m=0; m<npix; ++m)
-      {
-      Xyf xyf = pix2xyf(m);
-      int x=xyf.ix, y=xyf.iy, f=xyf.face;
-      int hits = 0;
-      double sum = 0;
-      for (int j=fact*y; j<fact*(y+1); ++j)
-        for (int i=fact*x; i<fact*(x+1); ++i)
-          {
-          int opix = (int)orig.xyf2pix(i,j,f);
-          if (!HealpixUtils.approx(orig.data[opix],undef,1e-5))
-            {
-            ++hits;
-            sum += orig.data[opix];
-            }
-          }
-      data[m] = (hits<minhits) ? undef : (<type>) (sum/hits);
-      }
-    }
-  /** Imports the map "orig" to this object, adjusting pixel ordering
-      and resolution if necessary.
-      @param orig map to import
-      @param pessimistic only used when resolution must be reduced: if true,
-        set a pixel to undefined if at least one the original subpixels
-        was undefined; otherwise only set it to undefined if all original
-        subpixels were undefined. */
-  public void importGeneral (HealpixMap<Type> orig, boolean pessimistic)
-    throws Exception
-    {
-    if (orig.nside==nside)
-      importNograde(orig);
-    else if (orig.nside<nside) // upgrading
-      importUpgrade(orig);
-    else
-      importDegrade(orig,pessimistic);
-    }
-  }
diff -Nru healpix-java-3.40/src/healpix/essentials/HealpixProc.java healpix-java-3.50/src/healpix/essentials/HealpixProc.java
--- healpix-java-3.40/src/healpix/essentials/HealpixProc.java	2013-04-03 09:15:40.000000000 -0400
+++ healpix-java-3.50/src/healpix/essentials/HealpixProc.java	1969-12-31 19:00:00.000000000 -0500
@@ -1,127 +0,0 @@
-/*
- *  This file is part of Healpix Java.
- *
- *  This code 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 code 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 code; 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.sourceforge.net
- */
-
-package healpix.essentials;
-
-/** Procedural interface to the {@link HealpixBase} functionality.
-    This class is intended for users who prefer a procedural (instead of
-    object-oriented) interface to the HEALPix functionality. It should make
-    transition from packages like PixTools easier.
-
-    @copyright 2012 Max-Planck-Society
-    @author Martin Reinecke */
-public abstract class HealpixProc extends HealpixBase
-  {
-  static final HealpixBase[] bn=new HealpixBase[HealpixBase.order_max+1],
-                             br=new HealpixBase[HealpixBase.order_max+1];
-  static final double[] mpr =new double[HealpixBase.order_max+1],
-                        cmpr=new double[HealpixBase.order_max+1],
-                        smpr=new double[HealpixBase.order_max+1];
-
-  static
-    {
-    try {
-      for (int i=0; i<=HealpixBase.order_max; ++i)
-        {
-        bn[i]=new HealpixBase(1L<<i, Scheme.NESTED);
-        br[i]=new HealpixBase(1L<<i, Scheme.RING);
-        mpr[i]=bn[i].maxPixrad();
-        cmpr[i]=FastMath.cos(mpr[i]);
-        smpr[i]=FastMath.sin(mpr[i]);
-        }
-      }
-    catch (Exception Ex) {/*doesn't happen*/}
-    }
-
-  private HealpixProc() {} // this class should not be instantiated
-
-  public static double maxPixrad (int order)
-    { return bn[order].maxPixrad(); }
-
-  public static long ang2pixNest (int order, Pointing ptg) throws Exception
-    { return bn[order].ang2pix(ptg); }
-  public static long ang2pixRing (int order, Pointing ptg) throws Exception
-    { return br[order].ang2pix(ptg); }
-
-  public static Pointing pix2angNest (int order, long pix) throws Exception
-    { return bn[order].pix2ang(pix); }
-  public static Pointing pix2angRing (int order, long pix) throws Exception
-    { return br[order].pix2ang(pix); }
-
-  public static long vec2pixNest (int order, Vec3 vec) throws Exception
-    { return bn[order].vec2pix(vec); }
-  public static long vec2pixRing (int order, Vec3 vec) throws Exception
-    { return br[order].vec2pix(vec); }
-
-  public static Vec3 pix2vecNest (int order, long pix) throws Exception
-    { return bn[order].pix2vec(pix); }
-  public static Vec3 pix2vecRing (int order, long pix) throws Exception
-    { return br[order].pix2vec(pix); }
-
-  public static long ring2nest (int order, long pix) throws Exception
-    { return bn[order].ring2nest(pix); }
-  public static long nest2ring (int order, long pix) throws Exception
-    { return bn[order].nest2ring(pix); }
-
-  public static long[] neighboursNest (int order, long pix) throws Exception
-    { return bn[order].neighbours(pix); }
-  public static long[] neighboursRing (int order, long pix) throws Exception
-    { return br[order].neighbours(pix); }
-
-  public static Vec3[] boundariesNest(int order, long pix, int step)
-    throws Exception
-    { return bn[order].boundaries(pix,step); }
-  public static Vec3[] boundariesRing(int order, long pix, int step)
-    throws Exception
-    { return br[order].boundaries(pix,step); }
-
-  public static RangeSet queryDiscNest(int order, Pointing ptg, double radius)
-    throws Exception
-    { return bn[order].queryDisc(ptg,radius); }
-  public static RangeSet queryDiscRing(int order, Pointing ptg, double radius)
-    throws Exception
-    { return br[order].queryDisc(ptg,radius); }
-  public static RangeSet queryDiscInclusiveNest(int order, Pointing ptg,
-    double radius, int fact) throws Exception
-    { return bn[order].queryDiscInclusive(ptg,radius,fact); }
-  public static RangeSet queryDiscInclusiveRing(int order, Pointing ptg,
-    double radius, int fact) throws Exception
-    { return br[order].queryDiscInclusive(ptg,radius,fact); }
-
-  public static RangeSet queryPolygonNest(int order, Pointing[] vertex)
-    throws Exception
-    { return bn[order].queryPolygon(vertex); }
-  public static RangeSet queryPolygonRing(int order, Pointing[] vertex)
-    throws Exception
-    { return br[order].queryPolygon(vertex); }
-  public static RangeSet queryPolygonInclusiveNest(int order, Pointing[] vertex,
-    int fact) throws Exception
-    { return bn[order].queryPolygonInclusive(vertex,fact); }
-  public static RangeSet queryPolygonInclusiveRing(int order, Pointing[] vertex,
-    int fact) throws Exception
-    { return br[order].queryPolygonInclusive(vertex,fact); }
-
-  public static RangeSet queryStripNest(int order, double theta1, double theta2,
-    boolean inclusive) throws Exception
-    { return bn[order].queryStrip(theta1,theta2,inclusive); }
-  public static RangeSet queryStripRing(int order, double theta1, double theta2,
-    boolean inclusive) throws Exception
-    { return br[order].queryStrip(theta1,theta2,inclusive); }
-  };
diff -Nru healpix-java-3.40/src/healpix/essentials/HealpixTables.java healpix-java-3.50/src/healpix/essentials/HealpixTables.java
--- healpix-java-3.40/src/healpix/essentials/HealpixTables.java	2016-03-10 10:13:56.000000000 -0500
+++ healpix-java-3.50/src/healpix/essentials/HealpixTables.java	1969-12-31 19:00:00.000000000 -0500
@@ -1,116 +0,0 @@
-/*
- *  This file is part of Healpix Java.
- *
- *  This code 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 code 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 code; 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.sourceforge.net
- */
-
-package healpix.essentials;
-
-import java.io.Serializable;
-
-/** Various data tables needed by the {@link HealpixBase} class.
-
-    @copyright 2011, 2012 Max-Planck-Society
-    @author Martin Reinecke */
-public class HealpixTables implements Serializable
-  {
-  static final protected short[] ctab={
-  0,1,256,257,2,3,258,259,512,513,768,769,514,515,770,771,4,5,260,261,6,7,262,
-  263,516,517,772,773,518,519,774,775,1024,1025,1280,1281,1026,1027,1282,1283,
-  1536,1537,1792,1793,1538,1539,1794,1795,1028,1029,1284,1285,1030,1031,1286,
-  1287,1540,1541,1796,1797,1542,1543,1798,1799,8,9,264,265,10,11,266,267,520,
-  521,776,777,522,523,778,779,12,13,268,269,14,15,270,271,524,525,780,781,526,
-  527,782,783,1032,1033,1288,1289,1034,1035,1290,1291,1544,1545,1800,1801,1546,
-  1547,1802,1803,1036,1037,1292,1293,1038,1039,1294,1295,1548,1549,1804,1805,
-  1550,1551,1806,1807,2048,2049,2304,2305,2050,2051,2306,2307,2560,2561,2816,
-  2817,2562,2563,2818,2819,2052,2053,2308,2309,2054,2055,2310,2311,2564,2565,
-  2820,2821,2566,2567,2822,2823,3072,3073,3328,3329,3074,3075,3330,3331,3584,
-  3585,3840,3841,3586,3587,3842,3843,3076,3077,3332,3333,3078,3079,3334,3335,
-  3588,3589,3844,3845,3590,3591,3846,3847,2056,2057,2312,2313,2058,2059,2314,
-  2315,2568,2569,2824,2825,2570,2571,2826,2827,2060,2061,2316,2317,2062,2063,
-  2318,2319,2572,2573,2828,2829,2574,2575,2830,2831,3080,3081,3336,3337,3082,
-  3083,3338,3339,3592,3593,3848,3849,3594,3595,3850,3851,3084,3085,3340,3341,
-  3086,3087,3342,3343,3596,3597,3852,3853,3598,3599,3854,3855 };
-  static final protected short[] utab={
-  0,1,4,5,16,17,20,21,64,65,68,69,80,81,84,85,256,257,260,261,272,273,276,277,
-  320,321,324,325,336,337,340,341,1024,1025,1028,1029,1040,1041,1044,1045,1088,
-  1089,1092,1093,1104,1105,1108,1109,1280,1281,1284,1285,1296,1297,1300,1301,
-  1344,1345,1348,1349,1360,1361,1364,1365,4096,4097,4100,4101,4112,4113,4116,
-  4117,4160,4161,4164,4165,4176,4177,4180,4181,4352,4353,4356,4357,4368,4369,
-  4372,4373,4416,4417,4420,4421,4432,4433,4436,4437,5120,5121,5124,5125,5136,
-  5137,5140,5141,5184,5185,5188,5189,5200,5201,5204,5205,5376,5377,5380,5381,
-  5392,5393,5396,5397,5440,5441,5444,5445,5456,5457,5460,5461,16384,16385,16388,
-  16389,16400,16401,16404,16405,16448,16449,16452,16453,16464,16465,16468,16469,
-  16640,16641,16644,16645,16656,16657,16660,16661,16704,16705,16708,16709,16720,
-  16721,16724,16725,17408,17409,17412,17413,17424,17425,17428,17429,17472,17473,
-  17476,17477,17488,17489,17492,17493,17664,17665,17668,17669,17680,17681,17684,
-  17685,17728,17729,17732,17733,17744,17745,17748,17749,20480,20481,20484,20485,
-  20496,20497,20500,20501,20544,20545,20548,20549,20560,20561,20564,20565,20736,
-  20737,20740,20741,20752,20753,20756,20757,20800,20801,20804,20805,20816,20817,
-  20820,20821,21504,21505,21508,21509,21520,21521,21524,21525,21568,21569,21572,
-  21573,21584,21585,21588,21589,21760,21761,21764,21765,21776,21777,21780,21781,
-  21824,21825,21828,21829,21840,21841,21844,21845 };
-
-  // coordinate of the lowest corner of each face
-  static final protected byte[] jrll = { 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4 };
-  static final protected byte[] jpll = { 1, 3, 5, 7, 0, 2, 4, 6, 1, 3, 5, 7 };
-
-  static final protected short[] xoffset = { -1,-1, 0, 1, 1, 1, 0,-1 };
-  static final protected short[] yoffset = {  0, 1, 1, 1, 0,-1,-1,-1 };
-  static final protected short[][] facearray =
-        { {  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 final protected byte[][] swaparray =
-        { { 0,0,3 },   // S
-          { 0,0,6 },   // SE
-          { 0,0,0 },   // E
-          { 0,0,5 },   // SW
-          { 0,0,0 },   // center
-          { 5,0,0 },   // NE
-          { 0,0,0 },   // W
-          { 6,0,0 },   // NW
-          { 3,0,0 } }; // N
-
-  static final protected int swap_cycle[][] = {
-    {},
-    {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} };
-  }
diff -Nru healpix-java-3.40/src/healpix/essentials/HealpixUtils.java healpix-java-3.50/src/healpix/essentials/HealpixUtils.java
--- healpix-java-3.40/src/healpix/essentials/HealpixUtils.java	2014-10-22 05:32:25.000000000 -0400
+++ healpix-java-3.50/src/healpix/essentials/HealpixUtils.java	1969-12-31 19:00:00.000000000 -0500
@@ -1,140 +0,0 @@
-/*
- *  This file is part of Healpix Java.
- *
- *  This code 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 code 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 code; 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.sourceforge.net
- */
-
-package healpix.essentials;
-
-/** Collection of utility functions.
-
-    @copyright 2011-2014 Max-Planck-Society
-    @author Martin Reinecke */
-public class HealpixUtils
-  {
-  /** Evaluates cond; if it is false, throws an Exception containing errtxt. */
-  static public void check(boolean cond, String errtxt) throws Exception
-    { if (!cond) throw new Exception(errtxt); }
-
-  /** Integer base 2 logarithm.
-      @param arg
-      @return the largest integer {@code n} that fulfills {@code 2^n<=arg}.
-      For negative arguments and zero, 0 is returned. */
-  static public int ilog2(long arg)
-    {
-    return 63-Long.numberOfLeadingZeros(Math.max(arg,1L));
-    }
-
-  /** Integer square root.
-      @param arg
-      @return the integer {@code n} which fulfills {@code n^2<=arg<(n+1)^2} */
-  static public int isqrt(long arg)
-    {
-    long res = (long)Math.sqrt(((double)arg)+0.5);
-    if (arg<(1L<<50)) return (int)res;
-    if (res*res>arg)
-      --res;
-    else if ((res+1)*(res+1)<=arg)
-      ++res;
-    return (int)res;
-    }
-
-  /** Computes the cosine of the angular distance between two z, phi positions
-      on the unit sphere. */
-  static public double cosdist_zphi (double z1, double phi1,
-    double z2, double phi2)
-    {
-    return z1*z2+ FastMath.cos(phi1-phi2)* Math.sqrt((1.0-z1*z1)*(1.0-z2*z2));
-    }
-  /** Computes the cosine of the angular distance between two z, phi positions
-      on the unit sphere. */
-  static public double cosdist_zphi (Zphi zp1, Zphi zp2)
-    { return cosdist_zphi(zp1.z,zp1.phi,zp2.z,zp2.phi); }
-
-  /** Returns the remainder of the division {@code v1/v2}.
-      The result is non-negative.
-      @param v1 dividend; can be positive or negative
-      @param v2 divisor; must be positive
-      @return remainder of the division; positive and smaller than {@code v2} */
-  static public double fmodulo (double v1, double v2)
-    {
-    if (v1>=0)
-      return (v1<v2) ? v1 : v1%v2;
-    double tmp=v1%v2+v2;
-    return (tmp==v2) ? 0. : tmp;
-    }
-
-  static public boolean approx (float a, float b, float epsilon)
-    { return Math.abs(a-b) < (epsilon*Math.abs(b)); }
-  static public boolean approx (double a, double b, double epsilon)
-    { return Math.abs(a-b) < (epsilon*Math.abs(b)); }
-
-  static public int uniq2order (long uniq)
-    { return ilog2(uniq>>>2)>>>1; }
-
-  static private long nest_peano_helper (long pix, int order, int dir)
-    {
-    final short arr2[] =
-      {   0, 35, 65, 66, 68,  5,103,  6,110,109, 15, 44, 72,  9,107, 10,
-         31,126, 60,125, 81, 16, 82, 51,123, 88, 26, 25,119, 84, 22, 21,
-         42, 75, 41,104, 12, 47, 77, 78, 38, 71, 37,100, 98, 97,  3, 32,
-         53, 54,116, 87, 57, 58,120, 91, 19,114, 48,113, 93, 28, 94, 63,
-         64,  1, 99,  2, 46, 79, 45,108,  4, 39, 69, 70,  8, 43, 73, 74,
-         85, 20, 86, 55,115, 80, 18, 17, 89, 24, 90, 59, 61, 62,124, 95,
-        106,105, 11, 40,102,101,  7, 36, 76, 13,111, 14, 34, 67, 33, 96,
-        127, 92, 30, 29, 27,122, 56,121, 49, 50,112, 83, 23,118, 52,117,
-        128,194,195,161,196,133,135,230,204,141,143,238,171,233,232,138,
-        149,212,214,183,221,159,158,252,217,155,154,248,178,243,241,144,
-        175,237,236,142,235,170,168,201,227,162,160,193,132,198,199,165,
-        186,251,249,152,242,176,177,211,246,180,181,215,157,220,222,191,
-        192,129,131,226,136,202,203,169,140,206,207,173,231,166,164,197,
-        213,151,150,244,145,208,210,179,153,216,218,187,254,188,189,223,
-        239,174,172,205,167,229,228,134,163,225,224,130,200,137,139,234,
-        250,184,185,219,190,255,253,156,182,247,245,148,209,147,146,240 };
-    final byte arr[] = { 16, 1,27, 2,31,20, 6, 5,10,19, 9,24,13,14,28,23,
-                          0,11,17,18,21, 4,22,15,26,25, 3, 8, 7,30,12,29,
-                         48,33,35,58,53,39,38,60,59,42,40,49,62,44,45,55,
-                         32,50,51,41,37,52,54,47,43,57,56,34,46,63,61,36 };
-    final byte peano_face2path[][] =
-      { { 2,5,2,5,3,6,3,6,2,3,2,3 }, { 2,6,2,3,3,5,2,6,2,3,3,5 } };
-    final byte peano_face2face[][] =
-      { { 0,5,6,11,10,1,4,7,2,3,8,9 }, { 0,5,8,9,6,1,2,7,10,11,4,3 } };
-
-    int face = (int)(pix>>>(2*order));
-    long result = 0L;
-    int state = ((peano_face2path[dir][face]<<4))|(dir<<7);
-    int shift=2*order-4;
-    for (; shift>=0; shift-=4)
-      {
-      state=arr2[(state&0xF0) | (((int)(pix>>>shift))&0xF)];
-      result = (result<<4) | (state&0xF);
-      }
-    if (shift==-2)
-      {
-      state=arr[((state>>>2)&0xFC) | ((int)(pix)&0x3)];
-      result = (result<<2) | (state&0x3);
-      }
-
-    return result + (((long)peano_face2face[dir][face])<<(2*order));
-    }
-
-  static public long nest2peano(long pix, int order)
-    { return nest_peano_helper(pix,order,0); }
-  static public long peano2nest(long pix, int order)
-    { return nest_peano_helper(pix,order,1); }
-
-  }
diff -Nru healpix-java-3.40/src/healpix/essentials/Hploc.java healpix-java-3.50/src/healpix/essentials/Hploc.java
--- healpix-java-3.40/src/healpix/essentials/Hploc.java	2013-04-03 09:15:40.000000000 -0400
+++ healpix-java-3.50/src/healpix/essentials/Hploc.java	1969-12-31 19:00:00.000000000 -0500
@@ -1,76 +0,0 @@
-/*
- *  This file is part of Healpix Java.
- *
- *  This code 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 code 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 code; 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.sourceforge.net
- */
-
-package healpix.essentials;
-
-/** Healpix-internal class for specifying locations on the sphere.
-
-    @copyright 2011 Max-Planck-Society
-    @author Martin Reinecke */
-final class Hploc
-  {
-  public double z, phi, sth;
-  public boolean have_sth;
-
-  /** Default constructor. */
-  public Hploc() {}
-  public Hploc (Vec3 v)
-    {
-    double xl = 1./v.length();
-    z = v.z*xl;
-    phi = FastMath.atan2(v.y,v.x);
-    if (Math.abs(z)>0.99)
-      {
-      sth = Math.sqrt(v.x*v.x+v.y*v.y)*xl;
-      have_sth=true;
-      }
-    }
-  public Hploc (Zphi zphi)
-    {
-    z = zphi.z;
-    phi = zphi.phi;
-    have_sth=false;
-    }
-  public Hploc (Pointing ptg) throws Exception
-    {
-    HealpixUtils.check((ptg.theta>=0.)&&(ptg.theta<=Math.PI),
-      "invalid theta value");
-    z = FastMath.cos(ptg.theta);
-    phi = ptg.phi;
-    if (Math.abs(z)>0.99)
-      {
-      sth = FastMath.sin(ptg.theta);
-      have_sth=true;
-      }
-    }
-
-  public Zphi toZphi()
-    { return new Zphi(z,phi); }
-  public Pointing toPointing()
-    {
-    double st = have_sth ? sth : Math.sqrt((1.0-z)*(1.0+z));
-    return new Pointing(FastMath.atan2(st,z),phi);
-    }
-  public Vec3 toVec3()
-    {
-    double st = have_sth ? sth : Math.sqrt((1.0-z)*(1.0+z));
-    return new Vec3(st*FastMath.cos(phi),st*FastMath.sin(phi),z);
-    }
-  }
diff -Nru healpix-java-3.40/src/healpix/essentials/MocFitsIO.java healpix-java-3.50/src/healpix/essentials/MocFitsIO.java
--- healpix-java-3.40/src/healpix/essentials/MocFitsIO.java	2016-03-21 18:45:42.000000000 -0400
+++ healpix-java-3.50/src/healpix/essentials/MocFitsIO.java	1969-12-31 19:00:00.000000000 -0500
@@ -1,120 +0,0 @@
-/*
- *  This file is part of Healpix Java.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- */
-package healpix.essentials;
-
-import java.io.*;
-import nom.tam.fits.*;
-
-/** Moc FITS I/O routines.
-    @copyright 2014-2015 Max-Planck-Society
-    @author Martin Reinecke */
-public class MocFitsIO
-  {
-  /** Converts the contents of a FITS input stream to a MOC. */
-  public static Moc mocFromFits(InputStream inp) throws Exception
-    {
-    FitsFactory.setUseHierarch(true);
-    FitsFactory.setUseAsciiTables(false);
-    FitsFactory.setLongStringsEnabled(true);
-    BasicHDU<?> bhdu = (new Fits(inp)).getHDU(1);
-    Header head = bhdu.getHeader();
-
-    Object tmp = ((BinaryTable)bhdu.getData()).getFlattenedColumn(0);
-    long[] data=null;
-    if (tmp instanceof long[])
-      data = (long[])tmp;
-    else if (tmp instanceof int[])
-      {
-      int[] tmp2 = (int[])tmp;
-      data = new long[tmp2.length];
-      for (int i=0; i<tmp2.length; ++i)
-        data[i] = (long)tmp2[i];
-      }
-    else if (tmp instanceof short[])
-      {
-      short[] tmp2 = (short[])tmp;
-      data = new long[tmp2.length];
-      for (int i=0; i<tmp2.length; ++i)
-        data[i] = (long)tmp2[i];
-      }
-    else
-      HealpixUtils.check(false,"unsupported data format");
-
-    RangeSet ru = new RangeSet();
-    for (int i=0; i<data.length; ++i)
-      ru.append(data[i]);
-    return Moc.fromUniqRS(ru);
-    }
-  /** Converts the contents of a FITS file to a MOC. */
-  public static Moc mocFromFits(String filename) throws Exception
-    {
-    FileInputStream inp = new FileInputStream(filename);
-    Moc moc = mocFromFits(inp);
-    inp.close();
-    return moc;
-    }
-
-  /** Writes the provided Moc to the stream in FITS format. */
-  public static void mocToFits(Moc moc, OutputStream out) throws Exception
-    {
-    FitsFactory.setUseHierarch(true);
-    FitsFactory.setUseAsciiTables(false);
-    FitsFactory.setLongStringsEnabled(true);
-    Fits f = new Fits();
-    Object[] table = new Object[1];
-    long[] data=moc.toUniq();
-    long maxval=0;
-    if (data.length>0) maxval=data[data.length-1];
-    if (maxval<=0x7fff)
-      {
-      short[] dtmp = new short[data.length];
-      for (int i=0; i<data.length; ++i)
-        dtmp[i]=(short)data[i];
-      table[0]=dtmp;
-      }
-    else if (maxval<=0x7FFFFFFF)
-      {
-      int[] dtmp = new int[data.length];
-      for (int i=0; i<data.length; ++i)
-        dtmp[i]=(int)data[i];
-      table[0]=dtmp;
-      }
-    else
-      table[0] = data;
-
-    f.addHDU(Fits.makeHDU(table));
-    BinaryTableHDU bhdu = (BinaryTableHDU) f.getHDU(1);
-
-    bhdu.setColumnName(0, "PIXEL", "");
-    bhdu.addValue("PIXTYPE", "HEALPIX", "HEALPix magic value");
-    bhdu.addValue("ORDERING", "NUNIQ", "NUNIQ coding method");
-    bhdu.addValue("COORDSYS", "C", "mandated by MOC standard");
-    bhdu.addValue("MOCORDER", moc.maxOrder(), "MOC resolution (best order)");
-
-    f.write(new DataOutputStream(out));
-    out.flush();
-    }
-  /** Writes the provided Moc to the specified file in FITS format. */
-  public static void mocToFits(Moc moc, String filename) throws Exception
-    {
-    FileOutputStream out = new FileOutputStream(filename);
-    mocToFits(moc,out);
-    out.close();
-    }
-  }
diff -Nru healpix-java-3.40/src/healpix/essentials/Moc.java healpix-java-3.50/src/healpix/essentials/Moc.java
--- healpix-java-3.40/src/healpix/essentials/Moc.java	2015-04-14 09:49:56.000000000 -0400
+++ healpix-java-3.50/src/healpix/essentials/Moc.java	1969-12-31 19:00:00.000000000 -0500
@@ -1,207 +0,0 @@
-/*
- *  This file is part of Healpix Java.
- *
- *  This code 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 code 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 code; 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.sourceforge.net
- */
-
-package healpix.essentials;
-
-/** Support for MOC algorithms.
-    @copyright 2014-2015 Max-Planck-Society
-    @author Martin Reinecke */
-public class Moc
-  {
-  private final static int maxorder=29;
-  private RangeSet rs;
-
-  /** Creates a new, empty Moc. */
-  public Moc()
-    { rs=new RangeSet(); }
-  /** Creates a new Moc, which is identical to "other". */
-  public Moc(Moc other)
-    { rs=new RangeSet(other.rs); }
-  /** Creates a new Moc from the range set of NESTED pixels at the given order.
-      */
-  public Moc(RangeSet rs2, int order)
-    {
-    rs=new RangeSet(rs2.nranges());
-    int shift=2*(maxorder-order);
-    for (int i=0; i<rs2.nranges(); ++i)
-      rs.append(rs2.ivbegin(i)<<shift,rs2.ivend(i)<<shift);
-    }
-
-  static private Moc fromNewRangeSet(RangeSet rngset)
-    {
-    Moc res = new Moc();
-    res.rs = rngset;
-    return res;
-    }
-
-  /** Returns the internal range set. */
-  public RangeSet getRangeSet()
-    { return new RangeSet(rs); }
-
-  /** Returns the maximum HEALPix order necessary to describe the Moc exactly.
-      */
-  public int maxOrder()
-    {
-    long combo=0;
-    for (int i=0; i<rs.nranges(); ++i)
-      combo|=rs.ivbegin(i)|rs.ivend(i);
-    return maxorder-(Long.numberOfTrailingZeros(combo)>>>1);
-    }
-
-  /** Returns a Moc with degraded resolution.
-      @param order the maximum HEALPix order used for the result
-      @param keepPartialCells if true, partially filled cells will be included
-        in the output Moc; if false, they will be ignored. */
-  public Moc degradedToOrder (int order, boolean keepPartialCells)
-    {
-    int shift=2*(maxorder-order);
-    long ofs=(1L<<shift)-1;
-    long mask = ~ofs;
-    long adda = keepPartialCells ? 0L : ofs,
-         addb = keepPartialCells ? ofs : 0L;
-    RangeSet rs2=new RangeSet();
-    for (int i=0; i<rs.nranges(); ++i)
-      {
-      long a=(rs.ivbegin(i)+adda)&mask;
-      long b=(rs.ivend  (i)+addb)&mask;
-      if (b>a) rs2.append(a,b);
-      }
-    return fromNewRangeSet(rs2);
-    }
-
-  /** Adds a range of pixels at a given HEALPix order to the Moc.
-      @param order the HEALPix order of the added pixels
-      @param p1 the first pixel of the range
-      @param p2 the one-after-last pixel of the range */
-  public void addPixelRange (int order, long p1, long p2)
-    {
-    int shift=2*(maxorder-order);
-    rs.add(p1<<shift,p2<<shift);
-    }
-  public void addPixel (int order, long p)
-    { addPixelRange(order, p, p+1); }
-  /** Returns a new Moc that contains the union of this Moc and "other". */
-  public Moc union (Moc other)
-    { return fromNewRangeSet(rs.union(other.rs)); }
-  /** Returns a new Moc that contains the intersection of this Moc and "other".
-      */
-  public Moc intersection (Moc other)
-    { return fromNewRangeSet(rs.intersection(other.rs)); }
-  /** Returns a new Moc that contains all parts of this Moc that are not
-      contained in "other". */
-  public Moc subtraction (Moc other)
-    { return fromNewRangeSet(rs.difference(other.rs)); }
-  /** Returns the complement of this Moc. */
-  public Moc complement()
-    {
-    RangeSet full = new RangeSet(new long[]{0L,12L*(1L<<(2*maxorder))});
-    return fromNewRangeSet(full.difference(rs));
-    }
-  /** @return true, if "other" is a subset of this Moc, else false. */
-  public boolean contains(Moc other) // FIXME: needs optimization!
-    { return rs.contains(other.rs); }
-  /** @return true, if the intersection of this Moc and "other" is not empty. */
-  public boolean overlaps(Moc other) // FIXME: needs optimization!
-    { return rs.overlaps(other.rs); }
-  /** @return A RangeSet containing all HEALPix pixels (in NUNIQ order) covered
-      by this Moc. The result is well-formed in the sense that every pixel is
-      given at its lowest possible HEALPix order. */
-  public RangeSet toUniqRS() // should be tuned!
-    {
-    RangeSet r2 = new RangeSet(rs);
-    RangeSet r3 = new RangeSet();
-    RangeSet res= new RangeSet();
-    for (int o=0; o<=maxorder; ++o)
-      {
-      if (r2.isEmpty()) return res;
-
-      int shift = 2*(maxorder-o);
-      long ofs=(1L<<shift)-1;
-      long ofs2 = 1L<<(2*o+2);
-      r3.clear();
-      for (int iv=0; iv<r2.nranges(); ++iv)
-        {
-        long a=(r2.ivbegin(iv)+ofs)>>>shift,
-             b=r2.ivend(iv)>>>shift;
-        r3.append(a<<shift, b<<shift);
-        res.append(a+ofs2,b+ofs2);
-        }
-      if (!r3.isEmpty())
-        r2 = r2.difference(r3);
-      }
-    return res;
-    }
-  public long[] toUniq() // should be tuned!
-    { return toUniqRS().toArray(); }
-
-  /** @return A Moc built from the RangeSet of NUNIQ HEALPix pixels given in
-      "ru". "ru" need not be well-formed. */
-  public static Moc fromUniqRS (RangeSet ru) // should be tuned!
-    {
-    RangeSet r= new RangeSet();
-    RangeSet rtmp = new RangeSet();
-    int lastorder=0;
-    int shift=2*maxorder;
-    for (int i=0; i<ru.nranges(); ++i)
-      for (long j=ru.ivbegin(i); j<ru.ivend(i); ++j)
-        {
-        int order = HealpixUtils.uniq2order(j);
-        if (order!=lastorder)
-          {
-          r=r.union(rtmp);
-          rtmp.clear();
-          lastorder=order;
-          shift=2*(maxorder-order);
-          }
-        long pix = j-(1L<<(2*order+2));
-        rtmp.append (pix<<shift,(pix+1)<<shift);
-        }
-    r=r.union(rtmp);
-    return fromNewRangeSet(r);
-    }
-
-  public static Moc fromUniq (long []u) // should be tuned!
-    {
-    return fromUniqRS(RangeSet.fromArray(u));
-    }
-
-  /** @return A compressed representation of the Moc obtained by interpolative
-      coding. */
-  public byte[] toCompressed() throws Exception
-    { return rs.toCompressed(); }
-  /** @return A Moc built from the compressed representation given in "data". */
-  public static Moc fromCompressed(byte[] data) throws Exception
-    { return fromNewRangeSet(RangeSet.fromCompressed(data)); }
-
-  public boolean equals(Object obj)
-    {
-    if (this == obj)
-      return true;
-    if ((obj==null) || (!(obj instanceof Moc)))
-      return false;
-    Moc other = (Moc) obj;
-    return rs.equals(other.rs);
-    }
-  public int hashCode()
-    { return rs.hashCode(); }
-
-  public int nranges()
-    { return rs.nranges(); }
-  }
diff -Nru healpix-java-3.40/src/healpix/essentials/MocQuery.java healpix-java-3.50/src/healpix/essentials/MocQuery.java
--- healpix-java-3.40/src/healpix/essentials/MocQuery.java	2015-08-05 05:49:32.000000000 -0400
+++ healpix-java-3.50/src/healpix/essentials/MocQuery.java	1969-12-31 19:00:00.000000000 -0500
@@ -1,470 +0,0 @@
-/*
- *  This file is part of Healpix Java.
- *
- *  This code 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 code 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 code; 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.sourceforge.net
- */
-
-package healpix.essentials;
-import java.util.ArrayList;
-
-/** Support for MOC queries.
-    @copyright 2015 Max-Planck-Society
-    @author Martin Reinecke */
-public class MocQuery
-  {
-  static public enum MocQueryOp { AND,OR,XOR,NOT,NONE }
-
-  static public class MocQueryComponent
-    {
-    public MocQueryOp op;
-    public Vec3 center;
-    public double radius;
-    public int nops;
-    public MocQueryComponent(MocQueryOp op_) throws Exception
-      {
-      op= op_;
-      HealpixUtils.check(op_!=MocQueryOp.NONE,"bad operator");
-      switch (op)
-        {
-        case AND:
-        case OR:
-        case XOR:
-          nops=2;
-          break;
-        case NOT:
-          nops=1;
-          break;
-        case NONE:
-          nops=0;
-          break;
-        }
-      }
-    public MocQueryComponent(MocQueryOp op_, int nops_) throws Exception
-      {
-      op= op_;
-      nops=nops_;
-      switch (op)
-        {
-        case AND:
-        case OR:
-          HealpixUtils.check(nops>=2,"bad nops");
-          break;
-        case XOR:
-          HealpixUtils.check(nops==2,"bad nops");
-          break;
-        case NOT:
-          HealpixUtils.check(nops==1,"bad nops");
-          break;
-        case NONE:
-          HealpixUtils.check(false,"bad operator");
-          break;
-        }
-      }
-    public MocQueryComponent(Vec3 cnt, double rad)
-      {
-      op = MocQueryOp.NONE;
-      center = new Vec3(cnt);
-      center.normalize();
-      radius = rad;
-      nops=0;
-      }
-    }
-
-  static private class queryHelper
-    {
-    private final class pstack
-      {
-      private long[] p;
-      private int[] o;
-      private int s, m;
-
-      public pstack (int sz)
-        { p=new long[sz]; o=new int[sz]; s=m=0; }
-      public void push (long p_, int o_)
-        { p[s]=p_; o[s]=o_; ++s; }
-      public void pop ()
-        { --s; }
-      public void popToMark ()
-        { s=m; }
-      public int size ()
-        { return s; }
-      public void mark ()
-        { m=s; }
-      public int otop ()
-        { return o[s-1]; }
-      public long ptop ()
-        { return p[s-1]; }
-      public void clear ()
-        { s=m=0; }
-      public boolean empty ()
-        { return s==0; }
-      }
-
-    private int order, omax, ncomp;
-    private boolean inclusive;
-    private HealpixBase base[];
-    private double cr[], crmin[][], crmax[][];
-    private int shortcut[];
-    private MocQueryOp op[];
-    private int nops[];
-    private Vec3 center[];
-
-    private pstack stk; // stack for pixel numbers and their orders
-    private long pix;
-    private int o;
-    private Vec3 pv;
-    private int loc;
-
-    private void check_pixel (int zone, Moc pixset)
-      {
-      if (zone==0) return;
-      if (o<order)
-        {
-        if (zone>=3)
-          pixset.addPixel(o,pix); // output all subpixels
-        else // (zone>=1)
-          for (int i=0; i<4; ++i)
-            stk.push(4*pix+3-i,o+1); // add children
-        }
-      else if (o>order) // this implies that inclusive==true
-        {
-        if (zone>=2) // pixel center in shape
-          {
-          pixset.addPixel(order,pix>>>(2*(o-order))); // output parent pixel
-          stk.popToMark(); // unwind the stack
-          }
-        else // (zone>=1): pixel center in safety range
-          {
-          if (o<omax) // check sublevels
-            for (int i=0; i<4; ++i) // add children in reverse order
-              stk.push(4*pix+3-i,o+1);
-          else // at resolution limit
-            {
-            pixset.addPixel(order,pix>>>(2*(o-order))); // output parent pixel
-            stk.popToMark(); // unwind the stack
-            }
-          }
-        }
-      else // o==order
-        {
-        if (zone>=2)
-          pixset.addPixel(order,pix);
-        else if (inclusive) // and (zone>=1)
-          {
-          if (order<omax) // check sublevels
-            {
-            stk.mark(); // remember current stack position
-            for (int i=0; i<4; ++i) // add children in reverse order
-              stk.push(4*pix+3-i,o+1);
-            }
-          else // at resolution limit
-            pixset.addPixel(order,pix); // output the pixel
-          }
-        }
-      }
-
-    void correctLoc() throws Exception
-      {
-      int myloc=loc--;
-      HealpixUtils.check((myloc>=0)&&(myloc<ncomp),"inconsistency");
-      for (int i=0; i<nops[myloc]; ++i)
-        correctLoc();
-      }
-    int getZone (int zmin, int zmax)
-      {
-      if (zmin==zmax) { loc=shortcut[loc]; return zmin; } // short-circuit
-      int myloc=loc--;
-      switch (op[myloc])
-        {
-        case AND:
-          {
-          int z1=zmax;
-          for (int i=0; i<nops[myloc]; ++i)
-            z1 = getZone(zmin,z1);
-          return z1;
-          }
-        case OR:
-          {
-          int z1=zmin;
-          for (int i=0; i<nops[myloc]; ++i)
-            z1 = getZone(z1,zmax);
-          return z1;
-          }
-        case XOR:
-          {
-          int z1=getZone(0,3);
-          int z2=getZone(0,3);
-          return Math.max(zmin,Math.min(zmax,
-            Math.max(Math.min(z1,3-z2),Math.min(3-z1,z2))));
-          }
-        case NOT:
-          return 3-getZone(3-zmax,3-zmin);
-        case NONE:
-          {
-          int res=zmax;
-          double crad=pv.dot(center[myloc]);
-          if (crad<=crmax[o][myloc]) res=0;
-          else if (crad<=cr[myloc]) res=1;
-          else if (crad<=crmin[o][myloc]) res=2;
-          return Math.max(zmin,Math.min(zmax,res));
-          }
-        }
-      return -1; // unreachable
-      }
-
-    public queryHelper (int order_, int omax_, boolean inclusive_,
-      ArrayList<MocQueryComponent> comp) throws Exception
-      {
-      order=order_;
-      omax=omax_;
-      ncomp=comp.size();
-      inclusive=inclusive_;
-      base=new HealpixBase[omax+1];
-      cr=new double[ncomp];
-      crmin=new double [omax+1][ncomp];
-      crmax=new double [omax+1][ncomp];
-      HealpixUtils.check(ncomp>=1,"bad query component ArrayList");
-      HealpixUtils.check(order<=omax,"order>omax");
-      if (!inclusive) HealpixUtils.check(order==omax,"inconsistency");
-      HealpixUtils.check(omax<=HealpixBase.order_max,"omax too high");
-
-      op=new MocQueryOp[ncomp];
-      nops=new int[ncomp];
-      center=new Vec3[ncomp];
-      for (int i=0; i<ncomp; ++i)
-        {
-        op[i]=comp.get(i).op;
-        nops[i]=comp.get(i).nops;
-        center[i]=comp.get(i).center;
-        if (op[i]==MocQueryOp.NONE) // it's a cap
-          cr[i]=Math.cos(comp.get(i).radius);
-        }
-      for (o=0; o<=omax; ++o) // prepare data at the required orders
-        {
-        base[o] = new HealpixBase(1<<o,Scheme.NESTED);
-        double dr=base[o].maxPixrad(); // safety distance
-        for (int i=0; i<ncomp; ++i)
-          if (op[i]==MocQueryOp.NONE) // it's a cap
-            {
-            double r=comp.get(i).radius;
-            crmax[o][i] = (r+dr>=Math.PI) ?
-              -1.01 : Math.cos(r+dr);
-            crmin[o][i] = (r-dr<=0.) ?
-               1.01 : Math.cos(r-dr);
-            }
-        }
-      stk=new pstack(12+3*omax); // reserve maximum size to avoid reallocation
-
-      shortcut=new int[ncomp];
-      for (int i=0; i<ncomp; ++i)
-        {
-        loc=i;
-        correctLoc();
-        shortcut[i]=loc;
-        }
-      }
-    Moc result() throws Exception
-      {
-      Moc pixset = new Moc();
-      stk.clear();
-      stk.mark();
-      for (int i=0; i<12; ++i) // insert the 12 base pixels in reverse order
-        stk.push(11-i,0);
-
-      while (!stk.empty()) // as long as there are pixels on the stack
-        {
-        // pop current pixel number and order from the stack
-        pix=stk.ptop();
-        o=stk.otop();
-        stk.pop();
-        pv = base[o].pix2vec(pix);
-
-        loc=ncomp-1;
-        int zone=getZone(0,3);
-        check_pixel (zone, pixset);
-        HealpixUtils.check(loc==-1,"stack not used up");
-        }
-      return pixset;
-      }
-    }
-
-  static public Moc doMocQuery (int order, ArrayList<MocQueryComponent> comp)
-    throws Exception
-    { return (new queryHelper(order,order,false,comp)).result(); }
-
-  static public Moc doMocQueryInclusive (int order, int omax,
-    ArrayList<MocQueryComponent> comp)
-    throws Exception
-    { return (new queryHelper(order,omax,true,comp)).result(); }
-
-  static private double isLeft (Vec3 a, Vec3 b, Vec3 c)
-    {
-    return (a.cross(b)).dot(c);
-    }
-
-  // adapted from code available at http://geomalgorithms.com/a12-_hull-3.html
-  // Original copyright notice follows:
-  // Copyright 2001 softSurfer, 2012 Dan Sunday
-  // This code may be freely used and modified for any purpose
-  // providing that this copyright notice is included with it.
-  // SoftSurfer makes no warranty for this code, and cannot be held
-  // liable for any real or imagined damage resulting from its use.
-  // Users of this code must verify correctness for their application.
-  static private int[] getHull (Vec3 vert[], int P[])
-    throws Exception
-    {
-    // initialize a deque D[] from bottom to top so that the
-    // 1st three vertices of P[] are a ccw triangle
-    int n = P.length;
-    int D[] = new int[2*n+1];
-    int bot = n-2, top = bot+3;    // initial bottom and top deque indices
-    D[bot] = D[top] = P[2];      // 3rd vertex is at both bot and top
-    if (isLeft(vert[P[0]], vert[P[1]], vert[P[2]]) > 0)
-      {
-      D[bot+1] = P[0];
-      D[bot+2] = P[1];           // ccw vertices are: 2,0,1,2
-      }
-    else
-      {
-      D[bot+1] = P[1];
-      D[bot+2] = P[0];           // ccw vertices are: 2,1,0,2
-      }
-
-    // compute the hull on the deque D[]
-    for (int i=3; i<n; i++)
-      {   // process the rest of vertices
-      // test if next vertex is inside the deque hull
-      if ((isLeft(vert[D[bot]], vert[D[bot+1]], vert[P[i]]) > 0) &&
-          (isLeft(vert[D[top-1]], vert[D[top]], vert[P[i]]) > 0) )
-        continue;         // skip an interior vertex
-
-      // incrementally add an exterior vertex to the deque hull
-      // get the rightmost tangent at the deque bot
-      while (isLeft(vert[D[bot]], vert[D[bot+1]], vert[P[i]]) <= 0)
-        ++bot;                 // remove bot of deque
-      D[--bot] = P[i];         // insert P[i] at bot of deque
-
-      // get the leftmost tangent at the deque top
-      while (isLeft(vert[D[top-1]], vert[D[top]], vert[P[i]]) <= 0)
-        --top;                 // pop top of deque
-      D[++top] = P[i];         // push P[i] onto top of deque
-      }
-
-    // transcribe deque D[] to the output hull array H[]
-    int nout = top-bot;
-    int res[] = new int[nout];
-    for (int h=0; h<nout; h++)
-      res[h] = D[bot + h +1];
-
-    return res;
-    }
-
-  static public ArrayList<MocQueryComponent> prepPolyHelper (Vec3 vv[],
-    int P[], ArrayList<MocQueryComponent> comp, boolean doLast)
-    throws Exception
-    {
-    int hull[]=getHull(vv,P);
-    boolean addHull[]=new boolean[hull.length];
-
-    // sync both sequences at the first point of the convex hull
-    int ihull=0, ipoly=0, nhull=hull.length, npoly=P.length;
-    while (hull[ihull]!=P[ipoly]) ++ipoly;
-
-    // iterate over the pockets between the polygon and its convex hull
-    int npockets=0;
-    if (P.length==3)
-      for (int i=0; i<3; i++) addHull[i]=true;
-    else
-      {
-      do
-        {
-        int ihull_next = (ihull+1)%nhull,
-            ipoly_next = (ipoly+1)%npoly;
-        if (hull[ihull_next]==P[ipoly_next]) // no pocket found
-          { addHull[ihull]=true; ihull=ihull_next; ipoly=ipoly_next; }
-        else // query pocket
-          {
-          int nvpocket=2; // number of vertices for this pocket
-          while (P[ipoly_next]!=hull[ihull_next])
-            {
-            ipoly_next = (ipoly_next+1)%npoly;
-            ++nvpocket;
-            }
-          int ppocket[] = new int[nvpocket];
-          int idx=0;
-          int ipoly_bw=ipoly_next;
-          while (P[ipoly_bw]!=hull[ihull])
-            {
-            ppocket[idx++]=P[ipoly_bw];
-            ipoly_bw=(ipoly_bw+npoly-1)%npoly;
-            }
-          ppocket[idx]=hull[ihull];
-          // process pocket recursively
-          ++npockets;
-          comp=prepPolyHelper (vv, ppocket, comp, false);
-          ihull=ihull_next;
-          ipoly=ipoly_next;
-          }
-        } while (ihull!=0);
-      }
-    if (npockets>1) 
-      comp.add(new MocQueryComponent(MocQueryOp.OR,npockets));
-    if (npockets>0) 
-      comp.add(new MocQueryComponent(MocQueryOp.NOT));
-
-    if (!doLast)
-      addHull[hull.length-1]=false;
-
-    // add convex hull
-    for (int i=0; i<hull.length; ++i)
-      if (addHull[i])
-        comp.add(new MocQueryComponent
-          (vv[hull[i]].cross(vv[hull[(i+1)%hull.length]]).norm(),0.5*Math.PI));
-
-    int num_and = 0;
-    for (int i=0; i<hull.length; ++i)
-      if (addHull[i]) ++num_and;
-    if (npockets>0) ++num_and;
-    if (num_and>1) 
-      comp.add(new MocQueryComponent(MocQueryOp.AND,num_and));
-
-    return comp;
-    }
-
-  static public ArrayList<MocQueryComponent> prepPolygon(ArrayList<Vec3> vertex)
-    throws Exception
-    {
-    HealpixUtils.check(vertex.size()>=3,"not enough vertices in polygon");
-    Vec3 vv[] = new Vec3[vertex.size()];
-    for (int i=0; i<vertex.size(); ++i)
-      vv[i]=vertex.get(i).norm();
-
-    int[] P=new int[vv.length];
-    for (int i=0; i<P.length; ++i)
-      P[i]=i;
-    ArrayList<MocQueryComponent> comp = new ArrayList<MocQueryComponent>();
-    return prepPolyHelper(vv,P,comp,true);
-    }
-
-  static public Moc queryGeneralPolygon (ArrayList<Vec3> vertex, int order)
-    throws Exception
-    { return doMocQuery (order, MocQuery.prepPolygon(vertex)); }
-  static public Moc queryGeneralPolygonInclusive (ArrayList<Vec3> vertex,
-    int order, int omax)
-    throws Exception
-    { return doMocQueryInclusive (order, omax, MocQuery.prepPolygon(vertex)); }
-  }
diff -Nru healpix-java-3.40/src/healpix/essentials/MocStringIO.java healpix-java-3.50/src/healpix/essentials/MocStringIO.java
--- healpix-java-3.40/src/healpix/essentials/MocStringIO.java	2015-07-05 02:56:22.000000000 -0400
+++ healpix-java-3.50/src/healpix/essentials/MocStringIO.java	1969-12-31 19:00:00.000000000 -0500
@@ -1,121 +0,0 @@
-/*
- *  This file is part of Healpix Java.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- */
-package healpix.essentials;
-
-import java.io.*;
-
-/** Moc string I/O routines.
-    @copyright 2014-2015 Max-Planck-Society
-    @author Martin Reinecke */
-public class MocStringIO
-  {
-  /** Parses a string following either the basic ASCII or JSON syntax given in
-      the MOC standard document, and converts it into a MOC.
-      The string need not obey the rules for a well-formed MOC given in the
-      document. */
-  public static Moc mocFromString(String in)
-    {
-    in=in.replaceAll(",+"," "); // replace commas with spaces
-    in=in.replaceAll("[\\[\\]{}\"]+",""); // get rid of useless characters
-    in=in.replaceAll("\\s*[:/]\\s*","/ "); // stick order indicator to order
-    in=in.replaceAll("\\s*-\\s*","-"); // fuse ranges into one token
-    String[] tok = in.split("[\\s]+"); // split at whitespace
-    RangeSet ru = new RangeSet();
-    int order=0;
-    long ofs=0;
-    for (int i=0; i<tok.length; ++i)
-      {
-      if (tok[i].isEmpty()) continue;
-      if (tok[i].contains("/")) // new order
-        {
-        tok[i]=tok[i].split("/")[0];
-        order=Integer.parseInt(tok[i]);
-        ofs = 4*(1L<<(2*order));
-        }
-      else if (tok[i].contains("-")) // range of values
-        {
-        String [] lim=tok[i].split("-");
-        ru.add(Long.parseLong(lim[0])+ofs,
-               Long.parseLong(lim[1])+ofs+1);
-        }
-      else // single value
-        ru.add(Long.parseLong(tok[i])+ofs);
-      }
-    return Moc.fromUniqRS(ru);
-    }
-  private static String mocToStringGeneral(Moc moc, boolean json)
-    {
-    RangeSet ru = moc.toUniqRS();
-    StringBuilder s = new StringBuilder();
-    if (json) s.append("{");
-    boolean firstOrder=true;
-    int omax = moc.maxOrder();
-    for (int o=0; o<=omax; ++o)
-      {
-      RangeSet rt = new RangeSet();
-      long offset=4*(1L<<(2*o));
-      rt.append(offset, 4*offset);
-      rt=rt.intersection(ru);
-      boolean prefix=false;
-      if (!rt.isEmpty())
-        {
-        for (int iv=0; iv<rt.nranges(); ++iv)
-          {
-          long a=rt.ivbegin(iv)-offset,
-               b=rt.ivend(iv)-offset;
-          if (!prefix)
-            {
-            if (!firstOrder) s.append(json ? ", " : " ");
-            firstOrder=false;
-            if (json)
-              s.append("\"").append(o).append("\":[");
-            else
-              s.append(o).append("/");
-            prefix=true;
-            }
-          else
-            s.append(",");
-          if (json)
-            {
-            for (long i=a;i<b-1;++i)
-              s.append(i).append(",");
-            s.append(b-1);
-            }
-          else
-            {
-            s.append(a);
-            if (b>a+1) s.append("-").append(b-1);
-            }
-          }
-        }
-      if (json&&prefix)
-        s.append("]");
-      }
-    if (json) s.append("}");
-    return s.toString();
-    }
-  /** Converts the Moc to its basic ASCII representation as described in the MOC
-      standard document. The result is well-formed. */
-  public static String mocToStringASCII (Moc moc)
-    { return mocToStringGeneral(moc,false); }
-  /** Converts the Moc to its JSON representation as described in the MOC
-      standard document. The result is well-formed. */
-  public static String mocToStringJSON(Moc moc)
-    { return mocToStringGeneral(moc,true); }
-  }
diff -Nru healpix-java-3.40/src/healpix/essentials/package-info.java healpix-java-3.50/src/healpix/essentials/package-info.java
--- healpix-java-3.40/src/healpix/essentials/package-info.java	2012-05-29 07:57:22.000000000 -0400
+++ healpix-java-3.50/src/healpix/essentials/package-info.java	1969-12-31 19:00:00.000000000 -0500
@@ -1,48 +0,0 @@
-/**
-Package implementing essential HEALPix functionality.<br>
-healpix.essentials is a Java package aiming to combine the advantages
-of other Java HEALPix libraries like
-the gov.fnal.eag.healpix package by N. Kuropatkin
-(<a href="http://home.fnal.gov/~kuropat/HEALPIX/PixTools.html">http://home.fnal.gov/~kuropat/HEALPIX/PixTools.html</a>),
-Jan Kotek's org.asterope.healpix package
-(<a href="https://github.com/jankotek/HEALPix">https://github.com/jankotek/HEALPix</a>),
-and the healpix.core package developed at ESO.
-<br>
-Current features include:
-<ul>
-<li>close similarities with Healpix_Base_T class from Healpix C++, which allows
-  simultaneous development and bug fixes for both.
-<li>support for arbitrary positive Nside values in RING scheme; no longer
-  limited to powers of 2
-<li>maximum supported Nside value: 2^29
-<li>significant performance improvements: most methods have been accelerated
-  by integral factors, some by more than an order of magnitude.
-<li>re-implementation of queryDisc and queryPolygon:
-<ul>
-  <li> query methods return RangeSet objects which allow much more compact
-    storage of the result
-  <li> new native query methods for NESTED ordering; these are slower than those
-    for RING ordering, but much quicker than converting all pixels from a RING
-    result to NESTED.
-  <li> inclusive queries have been improved: several bugs were fixed, and the
-    number of false positives in the result has been reduced. Users can now
-    choose between quick inclusive queries returning more false positives,
-    and slower ones returning fewer false positives.
-</ul>
-<li> the HealpixProc class offers a procedural (instead of object-oriented)
-  interface to the HealpixBase functionality, which simplifies transition
-  for users of the "Healpix" and "PixTools" classes.
-  NOTE: this only works for Nside parameters which are powers of 2
-<li> many bug fixes
-<li> no external library dependencies, except for "nom.tam.fits" if FITS I/O is
-  required
-<li> the code base is thread-safe in the following sense:
-<ul>
-  <li> HealpixProc methods can be called concurrently
-  <li> HealpixBase methods can be called concurrently on different objects
-</ul>
-</ul>
- at copyright 2011, 2012 Max-Planck-Society
- at author Martin Reinecke
-*/
-package healpix.essentials;
diff -Nru healpix-java-3.40/src/healpix/essentials/Pointing.java healpix-java-3.50/src/healpix/essentials/Pointing.java
--- healpix-java-3.40/src/healpix/essentials/Pointing.java	2015-04-01 08:52:19.000000000 -0400
+++ healpix-java-3.50/src/healpix/essentials/Pointing.java	1969-12-31 19:00:00.000000000 -0500
@@ -1,108 +0,0 @@
-/*
- *  This file is part of Healpix Java.
- *
- *  This code 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 code 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 code; 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.sourceforge.net
- */
-
-package healpix.essentials;
-
-/** An angular position on the unit sphere.
-
-    @copyright 2011 Max-Planck-Society
-    @author Martin Reinecke */
-public class Pointing
-  {
-  /** Colatitude in radians (0 is North Pole; Pi is South Pole) */
-  public double theta;
-
-  /** Longitude in radians */
-  public double phi;
-
-  /** Default constructor */
-  public Pointing() {}
-
-  public Pointing(Pointing ptg)
-    { this.theta = ptg.theta; this.phi = ptg.phi; }
-
-  /** Simple constructor initializing both values.
-      @param theta in radians [0,Pi]
-      @param phi in radians [0,2*Pi] */
-  public Pointing(double theta, double phi)
-    { this.theta = theta; this.phi = phi; }
-
-  /** Conversion from {@link Vec3} */
-  public Pointing(Vec3 vec)
-    {
-    theta = FastMath.atan2(Math.sqrt(vec.x*vec.x+vec.y*vec.y),vec.z);
-    phi = FastMath.atan2 (vec.y,vec.x);
-    if (phi<0.) phi += 2*Math.PI;
-    if (phi>=2*Math.PI) phi -= 2*Math.PI;
-    }
-
-  /** Conversion from {@link Zphi} */
-  public Pointing (Zphi zphi)
-    {
-    double xy=Math.sqrt((1.-zphi.z)*(1.+zphi.z));
-    theta = FastMath.atan2(xy,zphi.z); phi=zphi.phi;
-    }
-  // for some reason, the alternative below is much slower...
-  //{ theta=FastMath.acos(zphi.z); phi=zphi.phi; }
-
-  /** Normalize theta range */
-  public void normalizeTheta()
-    {
-    theta=HealpixUtils.fmodulo(theta,2*Math.PI);
-    if (theta>Math.PI)
-      {
-      phi+=Math.PI;
-      theta=2*Math.PI-theta;
-      }
-    }
-
-  /** Normalize theta and phi ranges */
-  public void normalize()
-    {
-    normalizeTheta();
-    phi=HealpixUtils.fmodulo(phi,2*Math.PI);
-    }
-
-  public String toString()
-    {
-    StringBuilder s = new StringBuilder();
-    s.append("ptg(");s.append(theta);
-    s.append(",");s.append(phi);
-    s.append(")");
-    return s.toString();
-    }
-
-  public boolean equals(Object o)
-    {
-    if (this==o) return true;
-    if ((o==null) || (getClass()!=o.getClass())) return false;
-    Pointing pointing = (Pointing) o;
-    if (Double.compare(pointing.phi, phi) != 0) return false;
-    if (Double.compare(pointing.theta, theta) != 0) return false;
-    return true;
-    }
-
-  public int hashCode()
-    {
-    int result = Double.valueOf(theta).hashCode();
-    result = 31 * result + Double.valueOf(phi).hashCode();
-    return result;
-    }
-  }
diff -Nru healpix-java-3.40/src/healpix/essentials/RangeSet.java healpix-java-3.50/src/healpix/essentials/RangeSet.java
--- healpix-java-3.40/src/healpix/essentials/RangeSet.java	2015-04-01 08:52:19.000000000 -0400
+++ healpix-java-3.50/src/healpix/essentials/RangeSet.java	1969-12-31 19:00:00.000000000 -0500
@@ -1,523 +0,0 @@
-/*
- *  This file is part of Healpix Java.
- *
- *  This code 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 code 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 code; 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.sourceforge.net
- */
-
-package healpix.essentials;
-import java.util.NoSuchElementException;
-
-/** Class for dealing with sets of integer ranges.
-    Ranges are described by the first element and the one-past-last element.
-    This code was inspired by Jan Kotek's "LongRangeSet" class, but has been
-    completely reimplemented.
-
-    @copyright 2011-2015 Max-Planck-Society
-    @author Martin Reinecke */
-public class RangeSet
-  {
-  /** Interface describing an iterator for going through all values in
-      a RangeSet object. */
-  public interface ValueIterator {
-    public boolean hasNext();
-    public long next();
-    }
-
-  private static final ValueIterator EMPTY_ITER = new ValueIterator()
-    {
-    public boolean hasNext() { return false; }
-    public long next() { throw new NoSuchElementException(); }
-    };
-
-  /** Sorted list of interval boundaries. */
-  protected long[] r;
-  /** Current number of active entries. */
-  protected int sz;
-
-  /** Construct new object with initial space for 4 ranges. */
-  public RangeSet() { this(4); }
-  /** Construct new object with initial capacity for a given number of ranges.
-      @param cap number of initially reserved ranges. */
-  public RangeSet(int cap)
-    {
-    if (cap<0) throw new IllegalArgumentException("capacity must be positive");
-    r = new long[cap<<1];
-    sz=0;
-    }
-  /** Construct new object from an array of longs.
-      @param data */
-   public RangeSet(long[] data)
-     {
-     sz=data.length;
-     r = new long[sz];
-     System.arraycopy(data,0,r,0,sz);
-     checkConsistency();
-     }
-  /** Construct new object from another RangeSet
-      @param other */
-  public RangeSet(RangeSet other)
-    {
-    sz=other.sz;
-    r = new long[sz];
-    System.arraycopy(other.r,0,r,0,sz);
-    }
-
-  /** Checks the object for internal consistency. If a problem is detected,
-      an IllegalArgumentException is thrown. */
-  public void checkConsistency()
-    {
-    if ((sz&1)!=0)
-      throw new IllegalArgumentException("invalid number of entries");
-    for (int i=1; i<sz; ++i)
-      if (r[i]<=r[i-1])
-        throw new IllegalArgumentException("inconsistent entries");
-    }
-
-  private void resize(int newsize)
-    {
-    if (newsize<sz)
-      throw new IllegalArgumentException("requested array size too small");
-    if (newsize==r.length) return;
-    long[] rnew = new long[newsize];
-    System.arraycopy(r,0,rnew,0,sz);
-    r = rnew;
-    }
-
-  /** Make sure the object can hold at least the given number of entries. */
-  public void ensureCapacity(int cap)
-    { if (r.length<cap) resize (Math.max(2*r.length,cap)); }
-  /** Shrinks the array for the entries to minimum size. */
-  public void trimSize()
-    { resize(sz); }
-  /** Shrinks the array for the entries to minimum size, if it is more than
-      twice the minimum size */
-  public void trimIfTooLarge()
-    { if (r.length-sz>=sz) resize(sz); }
-
-  /** Returns an internal representation of the interval a number belongs to.
-      @param val number whose interval is requested
-      @return interval number, starting with -1 (smaller than all numbers in the
-      RangeSet), 0 (first "on" interval), 1 (first "off" interval etc.), up to
-      (and including) sz-1 (larger than all numbers in the RangeSet). */
-  private int iiv (long val)
-    {
-    int count=sz, first=0;
-    while (count>0)
-      {
-      int step=count>>>1, it = first+step;
-      if (r[it]<=val)
-        { first=++it; count-=step+1; }
-      else
-        count=step;
-      }
-    return first-1;
-    }
-
-  /** Append a single-value range to the object.
-      @param val value to append */
-  public void append(long val)
-    { append(val,val+1); }
-
-  /** Append a range to the object.
-      @param a first long in range
-      @param b one-after-last long in range */
-  public void append (long a, long b)
-    {
-    if (a>=b) return;
-    if ((sz>0) && (a<=r[sz-1]))
-      {
-      if (a<r[sz-2]) throw new IllegalArgumentException("bad append operation");
-      if (b>r[sz-1]) r[sz-1]=b;
-      return;
-      }
-    ensureCapacity(sz+2);
-
-    r[sz] = a;
-    r[sz+1] = b;
-    sz+=2;
-    }
-
-  /** Append an entire range set to the object. */
-  public void append (RangeSet other)
-    {
-    for (int i=0; i<other.sz; i+=2)
-      append(other.r[i],other.r[i+1]);
-    }
-
-  /** @return number of ranges in the set. */
-  public int nranges()
-    { return sz>>>1; }
-
-  /** @return true if no entries are stored, else false. */
-  public boolean isEmpty()
-    { return sz==0; }
-
-  /** @return first number in range iv. */
-  public long ivbegin(int iv)
-    { return r[2*iv]; }
-  /** @return one-past-last number in range iv. */
-  public long ivend(int iv)
-    { return r[2*iv+1]; }
-
-  /** Remove all entries in the set. */
-  public void clear()
-    { sz=0; }
-
-  /** Push a single entry at the end of the entry vector. */
-  private void pushv(long v)
-    { ensureCapacity(sz+1); r[sz++]=v; }
-
-  /** Estimate a good strategy for set operations involving two RangeSets. */
-  private static int strategy (int sza, int szb)
-    {
-    final double fct1 = 1.;
-    final double fct2 = 1.;
-    int slo = sza<szb ? sza : szb,
-        shi = sza<szb ? szb : sza;
-    double cost1 = fct1 * (sza+szb);
-    double cost2 = fct2 * slo * Math.max(1.,HealpixUtils.ilog2(shi));
-    return (cost1<=cost2) ? 1 : (slo==sza) ? 2 : 3;
-    }
-
-  private static boolean generalAllOrNothing1 (RangeSet a, RangeSet b,
-    boolean flip_a, boolean flip_b)
-    {
-    boolean state_a=flip_a, state_b=flip_b, state_res=state_a||state_b;
-    int ia=0, ea=a.sz, ib=0, eb=b.sz;
-    boolean runa = ia!=ea, runb = ib!=eb;
-    while(runa||runb)
-      {
-      long va = runa ? a.r[ia] : 0L,
-           vb = runb ? b.r[ib] : 0L;
-      boolean adv_a = runa && (!runb || (va<=vb)),
-              adv_b = runb && (!runa || (vb<=va));
-      if (adv_a) { state_a=!state_a; ++ia; runa = ia!=ea; }
-      if (adv_b) { state_b=!state_b; ++ib; runb = ib!=eb; }
-      if ((state_a||state_b)!=state_res)
-        return false;
-      }
-    return true;
-    }
-
-  private static boolean generalAllOrNothing2 (RangeSet a, RangeSet b,
-    boolean flip_a, boolean flip_b)
-    {
-    int iva = flip_a ? 0 : -1;
-    while (iva<a.sz)
-      {
-      if (iva==-1) // implies that flip_a==false
-        { if ((!flip_b)||(b.r[0]<a.r[0])) return false; }
-      else if (iva==a.sz-1) // implies that flip_a==false
-        { if ((!flip_b)||(b.r[b.sz-1]>a.r[a.sz-1])) return false; }
-      else
-        {
-        int ivb=b.iiv(a.r[iva]);
-        if ((ivb!=b.sz-1)&&(b.r[ivb+1]<a.r[iva+1])) return false;
-        if (flip_b==((ivb&1)==0)) return false;
-        }
-      iva+=2;
-      }
-    return true;
-    }
-
-  private static boolean generalAllOrNothing (RangeSet a, RangeSet b,
-    boolean flip_a, boolean flip_b)
-    {
-    if (a.isEmpty())
-      return flip_a ? true : b.isEmpty();
-    if (b.isEmpty())
-      return flip_b ? true : a.isEmpty();
-    int strat = strategy (a.nranges(), b.nranges());
-    return (strat==1) ? generalAllOrNothing1(a,b,flip_a,flip_b) :
-             ((strat==2) ? generalAllOrNothing2(a,b,flip_a,flip_b)
-                         : generalAllOrNothing2(b,a,flip_b,flip_a));
-    }
-
-  /** Internal helper function for constructing unions, intersections
-      and differences of two RangeSets. */
-  private static RangeSet generalUnion1 (RangeSet a, RangeSet b,
-    boolean flip_a, boolean flip_b)
-    {
-    RangeSet res = new RangeSet();
-
-    boolean state_a=flip_a, state_b=flip_b, state_res=state_a||state_b;
-    int ia=0, ea=a.sz, ib=0, eb=b.sz;
-    boolean runa = ia!=ea, runb = ib!=eb;
-    while(runa||runb)
-      {
-      long va = runa ? a.r[ia] : 0L,
-           vb = runb ? b.r[ib] : 0L;
-      boolean adv_a = runa && (!runb || (va<=vb)),
-              adv_b = runb && (!runa || (vb<=va));
-      if (adv_a) { state_a=!state_a; ++ia; runa = ia!=ea; }
-      if (adv_b) { state_b=!state_b; ++ib; runb = ib!=eb; }
-      if ((state_a||state_b)!=state_res)
-        { res.pushv(adv_a ? va : vb); state_res = !state_res; }
-      }
-    return res;
-    }
-  /** Internal helper function for constructing unions, intersections
-      and differences of two RangeSets. */
-  private static RangeSet generalUnion2 (RangeSet a, RangeSet b,
-    boolean flip_a, boolean flip_b)
-    {
-    RangeSet res = new RangeSet();
-    int iva = flip_a ? 0 : -1;
-    while (iva<a.sz)
-      {
-      int ivb = (iva==-1) ? -1 : b.iiv(a.r[iva]);
-      boolean state_b = flip_b^((ivb&1)==0);
-      if ((iva>-1) && (!state_b)) res.pushv(a.r[iva]);
-      while((ivb<b.sz-1)&&((iva==a.sz-1)||(b.r[ivb+1]<a.r[iva+1])))
-        { ++ivb; state_b=!state_b; res.pushv(b.r[ivb]); }
-      if ((iva<a.sz-1)&&(!state_b)) res.pushv(a.r[iva+1]);
-      iva+=2;
-      }
-    return res;
-    }
-  private static RangeSet generalUnion (RangeSet a, RangeSet b,
-    boolean flip_a, boolean flip_b)
-    {
-    if (a.isEmpty())
-      return flip_a ? new RangeSet() : new RangeSet(b);
-    if (b.isEmpty())
-      return flip_b ? new RangeSet() : new RangeSet(a);
-    int strat = strategy (a.nranges(), b.nranges());
-    return (strat==1) ? generalUnion1(a,b,flip_a,flip_b) :
-             ((strat==2) ? generalUnion2(a,b,flip_a,flip_b)
-                         : generalUnion2(b,a,flip_b,flip_a));
-    }
-
-  /** Return the union of this RangeSet and other. */
-  public RangeSet union (RangeSet other)
-    { return generalUnion (this,other,false,false); }
-  /** Return the intersection of this RangeSet and other. */
-  public RangeSet intersection (RangeSet other)
-    { return generalUnion (this,other,true,true); }
-  /** Return the difference of this RangeSet and other. */
-  public RangeSet difference (RangeSet other)
-    { return generalUnion (this,other,true,false); }
-
-  /** Returns true if a is contained in the set, else false. */
-  public boolean contains (long a)
-    { return ((iiv(a)&1)==0); }
-  /** Returns true if all numbers [a;b[ are contained in the set, else false. */
-  public boolean contains (long a,long b)
-    {
-    int res=iiv(a);
-    if ((res&1)!=0) return false;
-    return (b<=r[res+1]);
-    }
-  @Deprecated
-  public boolean containsAll (long a,long b)
-    { return contains(a,b); }
-  /** Returns true if any of the numbers [a;b[ are contained in the set,
-      else false. */
-  public boolean overlaps (long a,long b)
-    {
-    int res=iiv(a);
-    if ((res&1)==0) return true;
-    if (res==sz-1) return false; // beyond the end of the set
-    return (r[res+1]<b);
-    }
-  @Deprecated
-  public boolean containsAny (long a,long b)
-    { return overlaps(a,b); }
-  /** Returns true if the set completely contains "other", else false. */
-  public boolean contains (RangeSet other)
-    { return generalAllOrNothing(this,other,false,true); }
-  @Deprecated
-  public boolean containsAll (RangeSet other)
-    { return contains(other); }
-  /** Returns true if there is overlap between the set and "other",
-      else false. */
-  public boolean overlaps (RangeSet other)
-    { return !generalAllOrNothing(this,other,true,true); }
-  @Deprecated
-  public boolean containsAny (RangeSet other)
-    { return overlaps(other); }
-  /** Returns true the object represents an identical set of ranges as obj. */
-  public boolean equals(Object obj) {
-    if (this == obj)
-      return true;
-    if ((obj==null) || (!(obj instanceof RangeSet)))
-      return false;
-    RangeSet other = (RangeSet) obj;
-    if (other.sz!=sz) return false;
-    for (int i=0; i<sz; ++i)
-      if (other.r[i]!=r[i]) return false;
-    return true;
-    }
-  public int hashCode()
-    {
-    int result = Integer.valueOf(sz).hashCode();
-    for (int i=0; i<sz; ++i)
-      result = 31 * result + Long.valueOf(r[sz]).hashCode();
-    return result;
-    }
-
-  /** @return total number of values (not ranges) in the set. */
-  public long nval()
-    {
-    long res = 0;
-    for (int i=0; i<sz; i+=2)
-      res+=r[i+1]-r[i];
-    return res;
-    }
-
-  /** Internal helper function for building unions and differences of the
-      RangeSet with a single range. */
-  private void addRemove (long a, long b, int v)
-    {
-    int pos1=iiv(a), pos2=iiv(b);
-    if ((pos1>=0) && (r[pos1]==a)) --pos1;
-    // first to delete is at pos1+1; last is at pos2
-    boolean insert_a = (pos1&1)==v;
-    boolean insert_b = (pos2&1)==v;
-    int rmstart=pos1+1+(insert_a ? 1 : 0);
-    int rmend  =pos2-(insert_b?1:0);
-
-    if (((rmend-rmstart)&1)==0)
-      throw new IllegalArgumentException("cannot happen: "+rmstart+" "+rmend);
-
-    if (insert_a && insert_b && (pos1+1>pos2)) // insert
-      {
-      ensureCapacity(sz+2);
-      System.arraycopy(r,pos1+1,r,pos1+3,sz-pos1-1); // move to right
-      r[pos1+1]=a;
-      r[pos1+2]=b;
-      sz+=2;
-      }
-    else
-      {
-      if (insert_a) r[pos1+1]=a;
-      if (insert_b) r[pos2]=b;
-      if (rmstart!=rmend+1)
-        System.arraycopy(r,rmend+1,r,rmstart,sz-rmend-1); // move to left
-      sz-=rmend-rmstart+1;
-      }
-    }
-
-  /** After this operation, the RangeSet contains the intersection of itself and
-      [a;b[. */
-  public void intersect (long a, long b)
-    {
-    int pos1=iiv(a), pos2=iiv(b);
-    if ((pos2>=0) && (r[pos2]==b)) --pos2;
-    // delete all up to pos1 (inclusive); and starting from pos2+1
-    boolean insert_a = (pos1&1)==0;
-    boolean insert_b = (pos2&1)==0;
-
-    // cut off end
-    sz=pos2+1;
-    if (insert_b) r[sz++]=b;
-
-    // erase start
-    if (insert_a) r[pos1--]=a;
-    if (pos1>=0)
-      System.arraycopy(r,pos1+1,r,0,sz-pos1-1); // move to left
-
-    sz-=pos1+1;
-    if ((sz&1)!=0)
-      throw new IllegalArgumentException("cannot happen");
-    }
-
-  /** After this operation, the RangeSet contains the union of itself and
-      [a;b[. */
-  public void add (long a, long b)
-    { if ((sz==0)||(a>=r[sz-1])) append(a,b); else addRemove(a,b,1); }
-  /** After this operation, the RangeSet contains the union of itself and
-      [a;a+1[. */
-  public void add (long a)
-    { if ((sz==0)||(a>=r[sz-1])) append(a,a+1); else addRemove(a,a+1,1); }
-  /** After this operation, the RangeSet contains the difference of itself and
-      [a;b[. */
-  public void remove (long a, long b)
-    { addRemove(a,b,0); }
-  /** After this operation, the RangeSet contains the difference of itself and
-      [a;a+1[. */
-  public void remove (long a)
-    { addRemove(a,a+1,0); }
-
-  /** Creates an array containing all the numbers in the RangeSet.
-      Not recommended, because the arrays can become prohibitively large.
-      It is preferrable to use a ValueIterator or explicit loops. */
-  public long[] toArray(){
-    long[] res = new long[(int)nval()];
-    int ofs=0;
-    for (int i=0; i<sz; i+=2)
-      for (long j=r[i]; j<r[i+1]; ++j)
-        res[ofs++]=j;
-    return res;
-    }
-  public static RangeSet fromArray(long[]v){
-    RangeSet res = new RangeSet();
-    for (int i=0; i<v.length; i++)
-      res.append(v[i]);
-    return res;
-    }
-
-  public String toString()
-    {
-    StringBuilder s = new StringBuilder();
-    s.append("{ ");
-    for (int i=0; i<sz; i+=2)
-      {
-      s.append("[").append(r[i]).append(";").append(r[i + 1]).append("[");
-      if (i<sz-2) s.append(",");
-      }
-    s.append(" }");
-    return s.toString();
-    }
-
-  /** Returns a ValueIterator, which iterates over all individual numbers
-      in the RangeSet. */
-  public ValueIterator valueIterator()
-    {
-    if(sz == 0) return EMPTY_ITER;
-    return new ValueIterator()
-      {
-      int pos = 0;
-      long value = (sz>0) ? r[0] : 0;
-
-      public boolean hasNext()
-        { return (pos<sz); }
-
-      public long next() {
-        if (pos>sz)
-          throw new NoSuchElementException();
-        long ret = value;
-        if (++value==r[pos+1])
-          {
-          pos+=2;
-          if (pos<sz)
-            value = r[pos];
-          }
-        return ret;
-        }
-      };
-    }
-
-  /** Returns a compressed representation of the RangeSet, using interpolative
-      coding. */
-  public byte[] toCompressed() throws Exception
-    { return Compressor.interpol_encode (r, 0, sz); }
-  /** Returns a RangeSet obtained by decompressing a byte array which was
-      originally generated by toCompressed(). */
-  public static RangeSet fromCompressed (byte[] data) throws Exception
-    { return new RangeSet(Compressor.interpol_decode(data)); }
-  }
diff -Nru healpix-java-3.40/src/healpix/essentials/Scheme.java healpix-java-3.50/src/healpix/essentials/Scheme.java
--- healpix-java-3.40/src/healpix/essentials/Scheme.java	2012-05-21 09:06:23.000000000 -0400
+++ healpix-java-3.50/src/healpix/essentials/Scheme.java	1969-12-31 19:00:00.000000000 -0500
@@ -1,9 +0,0 @@
-package healpix.essentials;
-
-/** The Healpix pixel ordering scheme. */
-public enum Scheme {
-  /** RING ordering. */
-  RING,
-  /** NESTED ordering. */
-  NESTED
-}
diff -Nru healpix-java-3.40/src/healpix/essentials/test/CompressorTest.java healpix-java-3.50/src/healpix/essentials/test/CompressorTest.java
--- healpix-java-3.40/src/healpix/essentials/test/CompressorTest.java	2015-07-05 02:10:50.000000000 -0400
+++ healpix-java-3.50/src/healpix/essentials/test/CompressorTest.java	1969-12-31 19:00:00.000000000 -0500
@@ -1,46 +0,0 @@
-/*
- *  This file is part of Healpix Java.
- *
- *  This code 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 code 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 code; 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.sourceforge.net
- */
-package healpix.essentials.test;
-
-import healpix.essentials.Compressor;
-import junit.framework.TestCase;
-import java.io.*;
-import java.util.Random;
-
-/** Tests for the linear interpolative coding compression
-
-    @copyright 2015 Max-Planck-Society
-    @author Martin Reinecke */
-public class CompressorTest extends TestCase {
-
-  public void testCompressDecompress() throws Exception
-    {
-    int num=100000;
-    Random randomGenerator = new Random();
-    long[] input=new long[num];
-    input[0]=0;
-    for (int i=1; i<num; ++i) input[i]=input[i-1]+1+randomGenerator.nextInt(100);
-    byte[] compressed=Compressor.interpol_encode(input,0,input.length);
-    long[] output=Compressor.interpol_decode(compressed);
-    assertEquals("inconsistency",input.length,output.length);
-    for (int i=0; i<output.length; ++i)
-      assertEquals("inconsistency",input[i],output[i]);
-    }
-}
diff -Nru healpix-java-3.40/src/healpix/essentials/test/FastMathPerfTest.java healpix-java-3.50/src/healpix/essentials/test/FastMathPerfTest.java
--- healpix-java-3.40/src/healpix/essentials/test/FastMathPerfTest.java	2015-07-05 02:10:50.000000000 -0400
+++ healpix-java-3.50/src/healpix/essentials/test/FastMathPerfTest.java	1969-12-31 19:00:00.000000000 -0500
@@ -1,104 +0,0 @@
-package healpix.essentials.test;
-
-import junit.framework.TestCase;
-import java.text.DecimalFormat;
-import static healpix.essentials.FastMath.*;
-
-/** FastMath benchmarking code
-
-    @copyright 2014 Max-Planck-Society
-    @author Martin Reinecke */
-public class FastMathPerfTest extends TestCase
-  {
-  static private final DecimalFormat form = new DecimalFormat("##0.00");
-  final int ncomp=10000000;
-
-  public void test_perf_math()
-    {
-    System.out.println("Rough performance test of math functions");
-    long cnt, tstart;
-    double dummy=0, di, time;
-    di=1./ncomp;
-    tstart = System.nanoTime();
-    cnt=0;
-    for (double i=0; i<1; i+=di)
-       { dummy+=Math.sqrt(i); ++cnt; }
-    time = 1e-9*(System.nanoTime()-tstart);
-    System.out.println("sqrt: " + form.format(cnt/time*1e-6) + "MOps/s");
-    di=4*Math.PI/ncomp;
-    tstart = System.nanoTime();
-    cnt=0;
-    for (double i=-2*Math.PI; i<2*Math.PI; i+=di)
-      { dummy+=Math.sin(i); ++cnt; }
-    time = 1e-9*(System.nanoTime()-tstart);
-    System.out.println("sin : " + form.format(cnt/time*1e-6) + "MOps/s");
-    tstart = System.nanoTime();
-    cnt=0;
-    for (double i=-2*Math.PI; i<2*Math.PI; i+=di)
-      { dummy+=Math.cos(i); ++cnt; }
-    time = 1e-9*(System.nanoTime()-tstart);
-    System.out.println("cos : " + form.format(cnt/time*1e-6) + "MOps/s");
-    di=2./ncomp;
-    tstart = System.nanoTime();
-    cnt=0;
-    for (double i=-1; i<1; i+=di)
-      { dummy+=Math.acos(i); ++cnt; }
-    time = 1e-9*(System.nanoTime()-tstart);
-    System.out.println("acos: " + form.format(cnt/time*1e-6) + "MOps/s");
-    di=1000./ncomp;
-    tstart = System.nanoTime();
-    cnt=0;
-    for (double i=-500; i<500; i+=di)
-      { dummy+=Math.atan(i); ++cnt; }
-    time = 1e-9*(System.nanoTime()-tstart);
-    System.out.println("atan: " + form.format(cnt/time*1e-6) + "MOps/s");
-    di=1000./ncomp;
-    tstart = System.nanoTime();
-    cnt=0;
-    for (double i=-500; i<500; i+=di)
-      { dummy+=Math.atan2(i,2.9); ++cnt; }
-    time = 1e-9*(System.nanoTime()-tstart);
-    System.out.println("atan2: " + form.format(cnt/time*1e-6) + "MOps/s");
-    di=1000./ncomp;
-    }
-  public void test_perf_fastmath()
-    {
-    System.out.println("Rough performance test of fast math functions");
-    long cnt,tstart;
-    double dummy=0, di, time;
-    di=4*Math.PI/ncomp;
-    tstart = System.nanoTime();
-    cnt=0;
-    for (double i=-2*Math.PI; i<2*Math.PI; i+=di)
-      { dummy+=sin(i); ++cnt; }
-    time = 1e-9*(System.nanoTime()-tstart);
-    System.out.println("sin : " + form.format(cnt/time*1e-6) + "MOps/s");
-    tstart = System.nanoTime();
-    cnt=0;
-    for (double i=-2*Math.PI; i<2*Math.PI; i+=di)
-      { dummy+=cos(i); ++cnt; }
-    time = 1e-9*(System.nanoTime()-tstart);
-    System.out.println("cos : " + form.format(cnt/time*1e-6) + "MOps/s");
-    di=2./ncomp;
-    tstart = System.nanoTime();
-    cnt=0;
-    for (double i=-1; i<1; i+=di)
-      { dummy+=acos(i); ++cnt; }
-    time = 1e-9*(System.nanoTime()-tstart);
-    System.out.println("acos: " + form.format(cnt/time*1e-6) + "MOps/s");
-    di=1000./ncomp;
-    tstart = System.nanoTime();
-    cnt=0;
-    for (double i=-500; i<500; i+=di)
-      { dummy+=atan(i); ++cnt; }
-    time = 1e-9*(System.nanoTime()-tstart);
-    System.out.println("atan: " + form.format(cnt/time*1e-6) + "MOps/s");
-    di=1000./ncomp;
-    tstart = System.nanoTime();
-    cnt=0;
-    for (double i=-500; i<500; i+=di)
-      { dummy+=atan2(i,2.9); ++cnt; }
-    time = 1e-9*(System.nanoTime()-tstart);
-    System.out.println("atan2: " + form.format(cnt/time*1e-6) + "MOps/s");
-    }
-  }
diff -Nru healpix-java-3.40/src/healpix/essentials/test/FastMathTest.java healpix-java-3.50/src/healpix/essentials/test/FastMathTest.java
--- healpix-java-3.40/src/healpix/essentials/test/FastMathTest.java	2012-05-21 09:06:23.000000000 -0400
+++ healpix-java-3.50/src/healpix/essentials/test/FastMathTest.java	1969-12-31 19:00:00.000000000 -0500
@@ -1,111 +0,0 @@
-package healpix.essentials.test;
-
-import junit.framework.TestCase;
-import java.text.DecimalFormat;
-import static healpix.essentials.FastMath.*;
-
-/** A class to perform correctness and speed tests for FastMath class
- *
- * @author Naoki Shibata
- */
-public class FastMathTest extends TestCase
-  {
-  private static final double p0=+0.0, m0=-0.0, pinf=Double.POSITIVE_INFINITY,
-    minf=Double.NEGATIVE_INFINITY, nan=Double.NaN;
-
-  private static boolean isPlusZero(double x)
-    { return x == 0 && Math.copySign(1, x) == 1; }
-  private static boolean isMinusZero(double x)
-    { return x == 0 && Math.copySign(1, x) == -1; }
-
-  private static boolean cmpDenorm(double x, double y) {
-    if (Double.isNaN(x) && Double.isNaN(y)) return true;
-    if (x == pinf && y == pinf) return true;
-    if (x == minf && y == minf) return true;
-    if (!Double.isNaN(x) && !Double.isNaN(y) &&
-        !Double.isInfinite(x) && !Double.isInfinite(y))
-      return true;
-    return false;
-    }
-
-  private static void ulptest (double v1, double v2, double ulp)
-    { assertTrue ("inconsistency",Math.abs((v1-v2)/Math.ulp(v2))<=ulp); }
-
-  private static void check1 (double d)
-    {
-    ulptest (sin(d),Math.sin(d),2.);
-    ulptest (cos(d),Math.cos(d),2.);
-    ulptest (atan(d),Math.atan(d),2.);
-    }
-  private static void check2 (double d)
-    {
-    ulptest (asin(d),Math.asin(d),3.);
-    ulptest (acos(d),Math.acos(d),2.);
-    }
-
-  public void testmain() throws Exception
-    {
-    assertEquals("inconsistency", Math.PI,(atan2(p0, m0)));
-    assertEquals("inconsistency",-Math.PI,(atan2(m0, m0)));
-    assertTrue("inconsistency",isPlusZero(atan2(p0, p0)));
-    assertTrue("inconsistency",isMinusZero(atan2(m0, p0)));
-    assertEquals("inconsistency",3*Math.PI/4,atan2(pinf, minf));
-    assertEquals("inconsistency",-3*Math.PI/4,atan2(minf, minf));
-    assertEquals("inconsistency",Math.PI/4,atan2(pinf, pinf));
-    assertEquals("inconsistency",-Math.PI/4,atan2(minf, pinf));
-    assertTrue("inconsistency",Double.isNaN(atan2(nan,nan)));
-
-    double[] a = { 100000.5, 100000, 3, 2.5, 2, 1.5, 1.0, 0.5 };
-    double[] b = { nan, pinf, minf };
-    double[] c = { nan, pinf, minf, 2, -2 };
-
-    for(int i=0;i<a.length;i++)
-      {
-      assertEquals("inconsistency",Math.PI,atan2(p0, -a[i]));
-      assertEquals("inconsistency",-Math.PI,atan2(m0, -a[i]));
-      assertEquals("inconsistency",-Math.PI/2,atan2(-a[i], p0));
-      assertEquals("inconsistency",-Math.PI/2,atan2(-a[i], m0));
-      assertEquals("inconsistency",Math.PI/2,atan2(a[i], p0));
-      assertEquals("inconsistency",Math.PI/2,atan2(a[i], m0));
-      assertEquals("inconsistency",Math.PI/2,atan2(pinf,a[i]));
-      assertEquals("inconsistency",Math.PI/2,atan2(pinf,-a[i]));
-      assertEquals("inconsistency",-Math.PI/2,atan2(minf,a[i]));
-      assertEquals("inconsistency",-Math.PI/2,atan2(minf,-a[i]));
-      assertEquals("inconsistency",Math.PI,atan2(a[i],minf));
-      assertEquals("inconsistency",-Math.PI,atan2(-a[i],minf));
-      assertEquals("inconsistency",p0,atan2(a[i],pinf));
-      assertEquals("inconsistency",m0,atan2(-a[i],pinf));
-      assertTrue("inconsistency",Double.isNaN(atan2(a[i],nan)));
-      assertTrue("inconsistency",Double.isNaN(atan2(-a[i],nan)));
-      assertTrue("inconsistency",Double.isNaN(atan2(nan,a[i])));
-      assertTrue("inconsistency",Double.isNaN(atan2(nan,-a[i])));
-      }
-
-    for(int i=0;i<b.length;i++)
-      {
-      assertTrue("inconsistency",cmpDenorm(sin(b[i]), Math.sin(b[i])));
-      assertTrue("inconsistency",cmpDenorm(cos(b[i]), Math.cos(b[i])));
-      assertTrue("inconsistency",cmpDenorm(atan(b[i]), Math.atan(b[i])));
-      }
-    for(int i=0;i<c.length;i++)
-      {
-      assertTrue("inconsistency",cmpDenorm(asin(c[i]), Math.asin(c[i])));
-      assertTrue("inconsistency",cmpDenorm(acos(c[i]), Math.acos(c[i])));
-      }
-
-    for(double d = -10;d < 10;d += 0.000001)
-      check1(d);
-    for(double d = -10000;d < 10000;d += 0.001)
-      check1(d);
-
-    for(double d = -1;d < 1;d += 0.0000001)
-      check2(d);
-
-    for(double y = -10;y < 10;y += 0.01)
-        for(double x = -10;x < 10;x += 0.01)
-          ulptest (atan2(y,x),Math.atan2(y,x),2.);
-    for(double y = -1000;y < 1000;y += 1.01)
-        for(double x = -1000;x < 1000;x += 1.01)
-          ulptest (atan2(y,x),Math.atan2(y,x),2.);
-    }
-  }
diff -Nru healpix-java-3.40/src/healpix/essentials/test/FitsUtilTest.java healpix-java-3.50/src/healpix/essentials/test/FitsUtilTest.java
--- healpix-java-3.40/src/healpix/essentials/test/FitsUtilTest.java	2015-07-05 02:10:50.000000000 -0400
+++ healpix-java-3.50/src/healpix/essentials/test/FitsUtilTest.java	1969-12-31 19:00:00.000000000 -0500
@@ -1,64 +0,0 @@
-/*
- *  This file is part of Healpix Java.
- *
- *  This code 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 code 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 code; 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.sourceforge.net
- */
-package healpix.essentials.test;
-
-import healpix.essentials.*;
-
-import junit.framework.TestCase;
-import java.util.UUID;
-import java.io.File;
-
-/** Tests for the FitsUtil class
-
-    @copyright 2014 Max-Planck-Society
-    @author Martin Reinecke */
-public class FitsUtilTest extends TestCase
-  {
-  public void testHPmapf() throws Exception
-    {
-    String name = UUID.randomUUID().toString()+".fits";
-    HealpixMapFloat hpmf = new HealpixMapFloat(128,Scheme.NESTED);
-    for (long i=0; i<hpmf.getNpix(); ++i)
-      hpmf.setPixel(i,(float)i);
-    FitsUtil.writeFloatMap(hpmf,name);
-    hpmf.setNsideAndScheme (64, Scheme.RING);
-    hpmf=FitsUtil.getFloatMap(name,2,1);
-    new File(name).delete();
-    assertEquals("Scheme problem",Scheme.NESTED,hpmf.getScheme());
-    assertEquals("Nside problem",128,hpmf.getNside());
-    for (long i=0; i<hpmf.getNpix(); ++i)
-      assertEquals("Value problem",(float)i,hpmf.getPixel(i));
-    }
-  public void testHPmapd() throws Exception
-    {
-    String name = UUID.randomUUID().toString()+".fits";
-    HealpixMapDouble hpmd = new HealpixMapDouble(128,Scheme.NESTED);
-    for (long i=0; i<hpmd.getNpix(); ++i)
-      hpmd.setPixel(i,(double)i);
-    FitsUtil.writeDoubleMap(hpmd,name);
-    hpmd.setNsideAndScheme (64, Scheme.RING);
-    hpmd=FitsUtil.getDoubleMap(name,2,1);
-    new File(name).delete();
-    assertEquals("Scheme problem",Scheme.NESTED,hpmd.getScheme());
-    assertEquals("Nside problem",128,hpmd.getNside());
-    for (long i=0; i<hpmd.getNpix(); ++i)
-      assertEquals("Value problem",(double)i,hpmd.getPixel(i));
-    }
-  }
diff -Nru healpix-java-3.40/src/healpix/essentials/test/FxyfTest.java healpix-java-3.50/src/healpix/essentials/test/FxyfTest.java
--- healpix-java-3.40/src/healpix/essentials/test/FxyfTest.java	2015-07-05 02:10:50.000000000 -0400
+++ healpix-java-3.50/src/healpix/essentials/test/FxyfTest.java	1969-12-31 19:00:00.000000000 -0500
@@ -1,49 +0,0 @@
-/*
- *  This file is part of Healpix Java.
- *
- *  This code 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 code 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 code; 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.sourceforge.net
- */
-package healpix.essentials.test;
-
-import junit.framework.TestCase;
-import java.util.Random;
-
-import healpix.essentials.*;
-
-/** Tests for the Fxyf class
-
-    @copyright 2015 Max-Planck-Society
-    @author Martin Reinecke */
-public class FxyfTest extends TestCase {
-
-  public void testFxyf() throws Exception
-    {
-    System.out.println("Testing Fxyf");
-    for (int i=0; i<12; ++i)
-      for (int j=0; j<=100; ++j)
-        for (int k=0; k<=100; ++k)
-          {
-          double fx=(0.01*j)*(1-1e-14)+.5e-14,
-                 fy=(0.01*k)*(1-1e-14)+.5e-14;
-          Fxyf res=new Fxyf(new Fxyf(fx,fy,i).toVec3());
-          assertEquals (res.face,i);
-          assertEquals (res.fx,fx,5e-15);
-          assertEquals (res.fy,fy,5e-15);
-          }
-    }
-
-  }
diff -Nru healpix-java-3.40/src/healpix/essentials/test/HealpixBasePerfTest.java healpix-java-3.50/src/healpix/essentials/test/HealpixBasePerfTest.java
--- healpix-java-3.40/src/healpix/essentials/test/HealpixBasePerfTest.java	2015-07-05 02:10:50.000000000 -0400
+++ healpix-java-3.50/src/healpix/essentials/test/HealpixBasePerfTest.java	1969-12-31 19:00:00.000000000 -0500
@@ -1,282 +0,0 @@
-/*
- *  This file is part of Healpix Java.
- *
- *  This code 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 code 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 code; 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.sourceforge.net
- */
-package healpix.essentials.test;
-
-import junit.framework.TestCase;
-import java.text.DecimalFormat;
-
-import healpix.essentials.*;
-
-/** Benchmarks for the HealpixBase class
-
-    @copyright 2014 Max-Planck-Society
-    @author Martin Reinecke */
-public class HealpixBasePerfTest extends TestCase
-  {
-  static private final DecimalFormat form = new DecimalFormat("##0.00");
-  static private final int nsteps=100000; // influences number of performance tests
-
-  private double subtest_perf_neighbours(String name, Scheme scheme)
-    throws Exception
-    {
-    long cnt=0;
-    double dummy=0;
-    long tstart = System.nanoTime();
-    int omax=HealpixBase.order_max;
-    for (int order=0; order<=omax; ++order)
-      {
-      HealpixBase base = new HealpixBase (1L<<order,scheme);
-      long dpix=Math.max(base.getNpix()/nsteps,1L);
-      for (long pix=0; pix<base.getNpix(); pix+=dpix)
-        {
-        long nres[] = base.neighbours(pix);
-        dummy+=nres[0];
-        ++cnt;
-        }
-      }
-    double time = 1e-9*(System.nanoTime()-tstart);
-    System.out.println(name + ": " + form.format(cnt/time*1e-6) + "MOps/s");
-    return dummy;
-    }
-
-  private double subtest_perf_pix2ang(String name, Scheme scheme)
-    throws Exception
-    {
-    long cnt=0;
-    double dummy=0;
-    long tstart = System.nanoTime();
-    int omax=HealpixBase.order_max;
-    for (int order=0; order<=omax; ++order)
-      {
-      HealpixBase base = new HealpixBase (1L<<order,scheme);
-      long dpix=Math.max(base.getNpix()/nsteps,1L);
-      for (long pix=0; pix<base.getNpix(); pix+=dpix)
-        {
-        Pointing p=base.pix2ang(pix);
-        dummy+=p.theta+p.phi;
-        ++cnt;
-        }
-      }
-    double time = 1e-9*(System.nanoTime()-tstart);
-    System.out.println(name + ": " + form.format(cnt/time*1e-6) + "MOps/s");
-    return dummy;
-    }
-
-  private double subtest_perf_pix2vec(String name, Scheme scheme)
-    throws Exception
-    {
-    long cnt=0;
-    double dummy=0;
-    long tstart = System.nanoTime();
-    int omax=HealpixBase.order_max;
-    for (int order=0; order<=omax; ++order)
-      {
-      HealpixBase base = new HealpixBase (1L<<order,scheme);
-      long dpix=Math.max(base.getNpix()/nsteps,1L);
-      for (long pix=0; pix<base.getNpix(); pix+=dpix)
-        {
-        Vec3 v=base.pix2vec(pix);
-        dummy+=v.x+v.y+v.z;
-        ++cnt;
-        }
-      }
-    double time = 1e-9*(System.nanoTime()-tstart);
-    System.out.println(name + ": " + form.format(cnt/time*1e-6) + "MOps/s");
-    return dummy;
-    }
-
-  private double subtest_perf_pix2zphi(String name, Scheme scheme)
-    throws Exception
-    {
-    long cnt=0;
-    double dummy=0;
-    long tstart = System.nanoTime();
-    int omax=HealpixBase.order_max;
-    for (int order=0; order<=omax; ++order)
-      {
-      HealpixBase base = new HealpixBase (1L<<order,scheme);
-      long dpix=Math.max(base.getNpix()/nsteps,1L);
-      for (long pix=0; pix<base.getNpix(); pix+=dpix)
-        {
-        Zphi blah=base.pix2zphi(pix);
-        dummy+=blah.z;
-        ++cnt;
-        }
-      }
-    double time = 1e-9*(System.nanoTime()-tstart);
-    System.out.println(name + ": " + form.format(cnt/time*1e-6) + "MOps/s");
-    return dummy;
-    }
-
-  private double subtest_perf_ring2nest() throws Exception
-    {
-    long cnt=0;
-    double dummy=0;
-    long tstart = System.nanoTime();
-    int omax=HealpixBase.order_max;
-    for (int order=0; order<=omax; ++order)
-      {
-      HealpixBase base = new HealpixBase (1L<<order,Scheme.RING);
-      long dpix=Math.max(base.getNpix()/nsteps,1L);
-      for (long pix=0; pix<base.getNpix(); pix+=dpix)
-        {
-        dummy+=base.ring2nest(pix);
-        ++cnt;
-        }
-      }
-    double time = 1e-9*(System.nanoTime()-tstart);
-    System.out.println("ring2nest       : " + form.format(cnt/time*1e-6) + "MOps/s");
-    return dummy;
-    }
-
-  private double subtest_perf_nest2ring() throws Exception
-    {
-    long cnt=0;
-    double dummy=0;
-    long tstart = System.nanoTime();
-    int omax=HealpixBase.order_max;
-    for (int order=0; order<=omax; ++order)
-      {
-      HealpixBase base = new HealpixBase (1L<<order,Scheme.RING);
-      long dpix=Math.max(base.getNpix()/nsteps,1L);
-      for (long pix=0; pix<base.getNpix(); pix+=dpix)
-        {
-        dummy+=base.nest2ring(pix);
-        ++cnt;
-        }
-      }
-    double time = 1e-9*(System.nanoTime()-tstart);
-    System.out.println("nest2ring       : " + form.format(cnt/time*1e-6) + "MOps/s");
-    return dummy;
-    }
-
-  private double subtest_perf_ang2pix(String name, Scheme scheme)
-    throws Exception
-    {
-    long cnt=0;
-    double dummy=0;
-    long tstart = System.nanoTime();
-    int omax=HealpixBase.order_max;
-    double dth=Math.PI/Math.sqrt(nsteps);
-    double dph=Constants.twopi/Math.sqrt(nsteps);
-    for (int order=0; order<=omax; ++order)
-      {
-      HealpixBase base = new HealpixBase (1L<<order,scheme);
-      for (double theta=0; theta<Math.PI; theta+=dth)
-        for (double phi=0; phi<2*Math.PI; phi+=dph)
-          {
-          dummy+=base.ang2pix(new Pointing(theta+1e-15*phi,phi));
-          ++cnt;
-          }
-      }
-    double time = 1e-9*(System.nanoTime()-tstart);
-    System.out.println(name+": " + form.format(cnt/time*1e-6) + "MOps/s");
-    return dummy;
-    }
-
-  private double subtest_perf_zphi2pix(String name, Scheme scheme)
-    throws Exception
-    {
-    long cnt=0;
-    double dummy=0;
-    long tstart = System.nanoTime();
-    int omax=HealpixBase.order_max;
-    double dz=2./Math.sqrt(nsteps);
-    double dph=Constants.twopi/Math.sqrt(nsteps);
-    for (int order=0; order<=omax; ++order)
-      {
-      HealpixBase base = new HealpixBase (1L<<order,scheme);
-      for (double z=-1; z<1; z+=dz)
-        for (double phi=0; phi<Constants.twopi; phi+=dph)
-          {
-          dummy+=base.zphi2pix(new Zphi(z,phi));
-          ++cnt;
-          }
-      }
-    double time = 1e-9*(System.nanoTime()-tstart);
-    System.out.println(name+": " + form.format(cnt/time*1e-6) + "MOps/s");
-    return dummy;
-    }
-
-  private double subtest_perf_query_disc(String name,
-    Scheme scheme) throws Exception
-    {
-    long cnt=0;
-    double dummy=0;
-    HealpixBase base = new HealpixBase (1024,scheme);
-    long tstart = System.nanoTime();
-    for (int m=0; m<1000; ++m)
-      {
-      RangeSet lrs=base.queryDisc(new Pointing(new Vec3(1,0,0)),Constants.halfpi/9.);
-      dummy+=lrs.nranges();
-      ++cnt;
-      }
-    double time = 1e-9*(System.nanoTime()-tstart);
-    System.out.println(name+": " + form.format(cnt/time*1e-3) + "kOps/s");
-    return dummy;
-    }
-
-  private double subtest_perf_query_polygon(String name,
-    Scheme scheme) throws Exception
-    {
-    long cnt=0;
-    double dummy=0;
-    HealpixBase base = new HealpixBase (1024,scheme);
-    Pointing[] corner = new Pointing[4];
-    corner[0]=new Pointing(new Vec3(1,0.01,0.01));
-    corner[1]=new Pointing(new Vec3(1,1,-0.3));
-    corner[2]=new Pointing(new Vec3(0.01,1,0.01));
-    corner[3]=new Pointing(new Vec3(0.01,0.01,1));
-    long tstart = System.nanoTime();
-    for (int m=0; m<1000; ++m)
-      {
-      RangeSet lrs=base.queryPolygon(corner);
-      dummy+=lrs.nranges();
-      ++cnt;
-      }
-    double time = 1e-9*(System.nanoTime()-tstart);
-    System.out.println(name+": " + form.format(cnt/time*1e-3) + "kOps/s");
-    return dummy;
-    }
-
-  public void test_perf() throws Exception
-    {
-    System.out.println("Performance tests of HealpixBase methods");
-    double d=0;
-    d+=subtest_perf_neighbours("neighbours(NEST)",Scheme.NESTED);
-    d+=subtest_perf_neighbours("neighbours(RING)",Scheme.RING);
-    d+=subtest_perf_pix2ang   ("pix2ang   (NEST)",Scheme.NESTED);
-    d+=subtest_perf_pix2ang   ("pix2ang   (RING)",Scheme.RING);
-    d+=subtest_perf_ang2pix   ("ang2pix   (NEST)",Scheme.NESTED);
-    d+=subtest_perf_ang2pix   ("ang2pix   (RING)",Scheme.RING);
-    d+=subtest_perf_pix2vec   ("pix2vec   (NEST)",Scheme.NESTED);
-    d+=subtest_perf_pix2vec   ("pix2vec   (RING)",Scheme.RING);
-    d+=subtest_perf_pix2zphi  ("pix2zphi  (NEST)",Scheme.NESTED);
-    d+=subtest_perf_pix2zphi  ("pix2zphi  (RING)",Scheme.RING);
-    d+=subtest_perf_zphi2pix  ("zphi2pix  (NEST)",Scheme.NESTED);
-    d+=subtest_perf_zphi2pix  ("zphi2pix  (RING)",Scheme.RING);
-    d+=subtest_perf_ring2nest();
-    d+=subtest_perf_nest2ring();
-    d+=subtest_perf_query_disc("disc      (NEST)",Scheme.NESTED);
-    d+=subtest_perf_query_disc("disc      (RING)",Scheme.RING);
-    d+=subtest_perf_query_polygon("polygon   (NEST)",Scheme.NESTED);
-    d+=subtest_perf_query_polygon("polygon   (RING)",Scheme.RING);
-    }
-  }
diff -Nru healpix-java-3.40/src/healpix/essentials/test/HealpixBaseTest.java healpix-java-3.50/src/healpix/essentials/test/HealpixBaseTest.java
--- healpix-java-3.40/src/healpix/essentials/test/HealpixBaseTest.java	2015-09-12 05:25:53.000000000 -0400
+++ healpix-java-3.50/src/healpix/essentials/test/HealpixBaseTest.java	1969-12-31 19:00:00.000000000 -0500
@@ -1,353 +0,0 @@
-/*
- *  This file is part of Healpix Java.
- *
- *  This code 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 code 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 code; 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.sourceforge.net
- */
-package healpix.essentials.test;
-
-import junit.framework.TestCase;
-import java.util.Random;
-import java.text.DecimalFormat;
-
-import healpix.essentials.*;
-
-/** @author Martin Reinecke */
-public class HealpixBaseTest extends TestCase {
-
-  static private final int nsamples=10000; // influences number of correctness tests
-  static private final DecimalFormat form = new DecimalFormat("##0.00");
-
-  private Zphi random_zphi(Random rng)
-    { return new Zphi(2*rng.nextDouble()-1,2*Math.PI*rng.nextDouble()); }
-
-  private Pointing random_dir(Random rng)
-    { return new Pointing(Math.acos(2*rng.nextDouble()-1),2*Math.PI*rng.nextDouble()); }
-
-  public void test_boundaries()throws Exception
-    {
-    System.out.println("Testing whether the boundary shapes look sane");
-
-    for (int nside=1; nside<=5; ++nside)
-      {
-      HealpixBase base=new HealpixBase(nside,Scheme.RING);
-      for (int pix=0; pix<base.getNpix(); ++pix)
-        {
-        for (int res=1; res<=50; res+=7)
-          {
-          Vec3[] points = base.boundaries(pix,res);
-          double dmin=1e30, dmax=-1e30;
-          for (int i=0; i<points.length; ++i)
-            {
-            double dv=(points[i].sub(points[(i+1)%points.length])).length();
-            assertTrue("error in boundaries",dv!=0);
-            dmin = Math.min(dv,dmin);
-            dmax = Math.max(dv,dmax);
-            }
-          assertTrue("error in boundaries",dmax/dmin<=2);
-          }
-        }
-      }
-    }
-
-  public void test_accuracy()throws Exception
-    {
-    System.out.println("Testing accuracy near the poles");
-
-    for (int order=0; order<=HealpixBase.order_max; ++order)
-      {
-      HealpixBase base = new HealpixBase (1L<<order,Scheme.RING);
-      assertTrue("incorrect pix2ang",base.pix2ang(1).theta>0.0);
-      }
-    }
-
-  public void test_ringnestring()throws Exception
-    {
-    System.out.println("Testing identity ring2nest(nest2ring(i))==i");
-    Random rng = new Random(5);
-
-    for (int order=0; order<=HealpixBase.order_max; ++order)
-      {
-      HealpixBase base = new HealpixBase (1L<<order,Scheme.RING);
-      for (int m=0; m<nsamples; ++m)
-        {
-        long pix = (long)(rng.nextDouble()*base.getNpix());
-        assertEquals ("ringnestring problem",
-          base.ring2nest(base.nest2ring(pix)),pix);
-        }
-      }
-    }
-
-  public void test_pixzphipix()throws Exception
-    {
-    System.out.println("Testing identity pix2zphi(zphi2pix(i))==i");
-    int omax=HealpixBase.order_max;
-    Random rng = new Random(5);
-    for (int order=0; order<=omax; ++order)
-      {
-      HealpixBase base1 = new HealpixBase (1L<<order,Scheme.RING),
-                  base2 = new HealpixBase (1L<<order,Scheme.NESTED);
-      for (int m=0; m<nsamples; ++m)
-        {
-        long pix = (long)(rng.nextDouble()*base1.getNpix());
-        assertEquals ("pixzphipix problem",
-          pix, base1.zphi2pix(base1.pix2zphi(pix)));
-        assertEquals ("pixzphipix problem",
-          pix, base2.zphi2pix(base2.pix2zphi(pix)));
-        }
-      }
-    for (long nside=3; nside<(1L<<omax); nside+=nside/2+1)
-      {
-      HealpixBase base = new HealpixBase (nside,Scheme.RING);
-      for (int m=0; m<nsamples; ++m)
-        {
-        long pix = (long)(rng.nextDouble()*base.getNpix());
-        assertEquals ("pixzphipix problem",
-          pix, base.zphi2pix(base.pix2zphi(pix)));
-        }
-      }
-    }
-
-  public void test_zphipixzphi() throws Exception
-    {
-    System.out.println
-      ("Testing near-identity zphi2pix(pix2zphi(i))approx i");
-    int omax=HealpixBase.order_max;
-    Random rng = new Random(5);
-    for (int order=0; order<=omax; ++order)
-      {
-      HealpixBase base1 = new HealpixBase (1L<<order,Scheme.RING),
-                  base2 = new HealpixBase (1L<<order,Scheme.NESTED);
-      double mincos = Math.min (Math.cos(base1.maxPixrad()),0.999999999999999);
-      for (int m=0; m<nsamples; ++m)
-        {
-        Zphi zp1 = random_zphi(rng);
-        Zphi zp2 = base1.pix2zphi(base1.zphi2pix(zp1));
-        double cd1 = HealpixUtils.cosdist_zphi(zp1.z,zp1.phi,zp2.z,zp2.phi);
-        assertTrue("zphipixzphi problem "+cd1+" "+mincos,cd1>=mincos);
-        zp2 = base2.pix2zphi(base2.zphi2pix(zp1));
-        cd1 = HealpixUtils.cosdist_zphi(zp1.z,zp1.phi,zp2.z,zp2.phi);
-        assertTrue("zphipixzphi problem",cd1>=mincos);
-        }
-      }
-    for (long nside=3; nside<(1L<<omax); nside+=nside/2+1)
-      {
-      HealpixBase base = new HealpixBase (nside,Scheme.RING);
-      double mincos = Math.min (Math.cos(base.maxPixrad()),0.999999999999999);
-      for (int m=0; m<nsamples; ++m)
-        {
-        Zphi zp1 = random_zphi(rng);
-        Zphi zp2 = base.pix2zphi(base.zphi2pix(zp1));
-        double cd1 = HealpixUtils.cosdist_zphi(zp1.z,zp1.phi,zp2.z,zp2.phi);
-        assertTrue("zphipixzphi problem",cd1>=mincos);
-        }
-      }
-    }
-
-  public void test_neighbours() throws Exception
-    {
-    System.out.println("Testing neighbour function");
-    int omax=HealpixBase.order_max;
-    Random rng = new Random(5);
-    for (int order=0; order<=omax; ++order)
-      {
-      HealpixBase base1 = new HealpixBase (1L<<order,Scheme.RING),
-                  base2 = new HealpixBase (1L<<order,Scheme.NESTED);
-      double maxang = 2.01*base1.maxPixrad();
-      for (int m=0; m<nsamples; ++m)
-        {
-        long pix = (long)(rng.nextDouble()*base1.getNpix());
-        Vec3 v = base1.pix2vec(pix);
-        long [] nb = base1.neighbours(pix);
-        long [] nb2 = base2.neighbours(base2.ring2nest(pix));
-        int nnb=0;
-        for (int n=0; n<8; ++n)
-          {
-          if (nb[n]<0)
-            assertTrue("neighbour problem 1",nb2[n]<0);
-          else
-            {
-            ++nnb;
-            assertEquals("neighbour problem 2",base1.ring2nest(nb[n]),nb2[n]);
-            assertTrue("neighbour problem 3",base1.pix2vec(nb[n]).angle(v)<maxang);
-            }
-          }
-        assertTrue("neighbour problem 4 "+order+" "+nnb,(nnb>=7)||((order==0)&&(nnb>=6)));
-        }
-      }
-    for (long nside=3; nside<(1L<<omax); nside+=nside/2+1)
-      {
-      HealpixBase base = new HealpixBase (nside,Scheme.RING);
-      double maxang = 2.01*base.maxPixrad();
-      for (int m=0; m<nsamples; ++m)
-        {
-        long pix = (long)(rng.nextDouble()*base.getNpix());
-        Vec3 v = base.pix2vec(pix);
-        long[] nb = base.neighbours(pix);
-        int nnb=0;
-        for (int n=0; n<8; ++n)
-          if (nb[n]>=0)
-            {
-            ++nnb;
-            assertTrue("neighbour problem 5",base.pix2vec(nb[n]).angle(v)<maxang);
-            }
-        assertTrue("neighbour problem 6",nnb>=7);
-        }
-      }
-    }
-  public void test_query_disc_strict() throws Exception
-    {
-    System.out.println("Testing non-inclusive queryDisc()");
-    Random rng = new Random(5);
-    for (int order=0; order<=5; ++order)
-      {
-      HealpixBase base = new HealpixBase (1L<<order,Scheme.NESTED);
-      boolean[] map = new boolean[(int)base.getNpix()];
-      Vec3[] vmap = new Vec3[(int)base.getNpix()];
-      for (int m=0; m<base.getNpix(); ++m)
-        {
-        map[m]=false;
-        vmap[m]=base.pix2vec(m);
-        }
-      for (int m=0; m<nsamples; ++m)
-        {
-        Pointing ptg = random_dir (rng);
-        double rad = Math.PI * rng.nextDouble();
-        RangeSet rs = base.queryDisc(ptg,rad);
-        Vec3 vptg = new Vec3(ptg);
-        double cosrad=Math.cos(rad);
-        for (int i=0; i<rs.nranges(); ++i)
-          for (long j=rs.ivbegin(i); j<rs.ivend(i); ++j)
-            map[(int)j]=true;
-        for (int i=0; i<base.getNpix(); ++i)
-          {
-          boolean inside = vmap[i].dot(vptg)>cosrad;
-          assertFalse ("query_disc_strict problem",inside^map[i]);
-          }
-        for (int i=0; i<rs.nranges(); ++i)
-          for (long j=rs.ivbegin(i); j<rs.ivend(i); ++j)
-            map[(int)j]=false;
-        }
-      }
-    }
-
-  public void test_query_disc() throws Exception
-    {
-    System.out.println("Testing queryDisc() empirically");
-    int omax=17;
-    Random rng = new Random(5);
-    for (int order=0; order<=omax; ++order)
-      {
-      HealpixBase rbase = new HealpixBase (1L<<order,Scheme.RING),
-                  nbase = new HealpixBase (1L<<order,Scheme.NESTED);
-      int niter=Math.max(1,Math.min(nsamples/1000,100000>>order));
-      for (int m=0; m<niter; ++m)
-        {
-        Pointing ptg = random_dir (rng);
-        double rad = Math.PI * rng.nextDouble();
-        RangeSet rs = rbase.queryDisc(ptg,rad);
-        long nval = rs.nval();
-        rs = nbase.queryDisc(ptg,rad);
-        assertEquals("queryDisc problem 1", nval,rs.nval());
-        rs = rbase.queryDiscInclusive(ptg,rad,4);
-        long nv1 = rs.nval();
-        rs = nbase.queryDiscInclusive(ptg,rad,4);
-        long nv2 = rs.nval();
-        assertTrue("queryDisc problem 2", nv1>=nv2);
-        assertTrue("queryDisc problem 3", nv2>=nval);
-        }
-      }
-    }
-
-  public void testQueryPolygon() throws Exception
-    {
-    System.out.println("Testing queryPolygon()");
-    HealpixBase base = new HealpixBase(1024,Scheme.NESTED);
-    Pointing[] corner = new Pointing[4];
-    corner[0]=new Pointing(new Vec3(1,0.01,0.01));
-    corner[1]=new Pointing(new Vec3(1,1,-0.3));
-    corner[2]=new Pointing(new Vec3(0.01,1,0.01));
-    corner[3]=new Pointing(new Vec3(0.01,0.01,1));
-    RangeSet lrs=base.queryPolygon(corner);
-    assertEquals("QueryPolygon problem",lrs.nval(),1696714);
-    lrs=base.queryPolygonInclusive(corner,4);
-    assertEquals("QueryPolygon problem",lrs.nval(),1700206);
-    base = new HealpixBase(1024,Scheme.RING);
-    lrs=base.queryPolygon(corner);
-    assertEquals("QueryPolygon problem",lrs.nval(),1696714);
-    lrs=base.queryPolygonInclusive(corner,4);
-    assertEquals("QueryPolygon problem",lrs.nval(),1700206);
-    }
-
-  public void testQueryPolygon2() throws Exception
-    {
-    System.out.println("Testing queryPolygon() empirically");
-    int omax=17;
-    Random rng = new Random(5);
-    for (int order=0; order<=omax; ++order)
-      {
-      HealpixBase rbase = new HealpixBase (1L<<order,Scheme.RING),
-                  nbase = new HealpixBase (1L<<order,Scheme.NESTED);
-      int niter=Math.max(1,Math.min(nsamples/1000,100000>>order));
-      for (int m=0; m<niter; ++m)
-        {
-        Pointing[] corner = new Pointing[3];
-        corner[0]=random_dir(rng);
-        corner[1]=random_dir(rng);
-        corner[2]=random_dir(rng);
-        RangeSet rs = rbase.queryPolygon(corner);
-        long nval = rs.nval();
-        rs = nbase.queryPolygon(corner);
-        assertEquals("queryPolygon problem 1", nval,rs.nval());
-        rs = rbase.queryPolygonInclusive(corner,4);
-        long nv1 = rs.nval();
-        rs = nbase.queryPolygonInclusive(corner,4);
-        long nv2 = rs.nval();
-        assertTrue("queryPolygon problem 2", nv1>=nv2);
-        assertTrue("queryPolygon problem 3", nv2>=nval);
-        }
-      }
-    }
-
-  public void testSmallPoly()  throws Exception
-    {
-    System.out.println("Testing small polygon");
-    HealpixBase base = new HealpixBase(1024,Scheme.NESTED);
-    Pointing[] corner = new Pointing[4];
-    corner[0]=new Pointing(2.7190983373838,1.50840508184223);
-    corner[1]=new Pointing(2.7190980835706067,1.5084057923700163);
-    corner[2]=new Pointing(2.719101654815075,1.5084144044115078);
-    corner[3]=new Pointing(2.719101908630556,1.5084136938829422);
-    RangeSet lrs=base.queryPolygon(corner);
-    }
-
-  public void test() throws Exception
-    {
-    int nside=256;
-    HealpixBase base  = new HealpixBase(nside,Scheme.NESTED);
-    HealpixBase base2 = new HealpixBase(nside,Scheme.RING);
-    for (int i=0; i<12*nside*nside; ++i)
-      {
-      assertEquals ("pixel mismatch_nest",i,base.ang2pix(base.pix2ang(i)));
-      assertEquals ("pixel mismatch_nest",i,base.vec2pix(base.pix2vec(i)));
-      assertEquals ("pixel mismatch_ring",i,base2.ang2pix(base2.pix2ang(i)));
-      assertEquals ("pixel mismatch_ring",i,base2.vec2pix(base2.pix2vec(i)));
-      assertEquals ("pixel mismatch",i,base.ring2nest(base2.ang2pix(base.pix2ang(i))));
-      assertEquals ("pixel mismatch_ringnestring",i,base.ring2nest(base.nest2ring(i)));
-      }
-    }
-
-  }
diff -Nru healpix-java-3.40/src/healpix/essentials/test/HealpixMapTest.java healpix-java-3.50/src/healpix/essentials/test/HealpixMapTest.java
--- healpix-java-3.40/src/healpix/essentials/test/HealpixMapTest.java	2015-07-05 02:10:50.000000000 -0400
+++ healpix-java-3.50/src/healpix/essentials/test/HealpixMapTest.java	1969-12-31 19:00:00.000000000 -0500
@@ -1,51 +0,0 @@
-/*
- *  This file is part of Healpix Java.
- *
- *  This code 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 code 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 code; 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.sourceforge.net
- */
-package healpix.essentials.test;
-
-import junit.framework.TestCase;
-import java.util.Random;
-import java.text.DecimalFormat;
-
-import healpix.essentials.*;
-
-/** Tests for the HealpixMap class
-
-    @copyright 2014 Max-Planck-Society
-    @author Martin Reinecke */
-public class HealpixMapTest extends TestCase {
-
-  public void test_swapScheme()throws Exception
-    {
-    System.out.println("Testing swapScheme()");
-
-    for (int order=0; order<=8; ++order)
-      {
-      HealpixMapFloat map = new HealpixMapFloat (1L<<order,Scheme.RING);
-      for (int i=0; i<map.getNpix(); ++i)
-        map.setPixel(i,i);
-      map.swapScheme();
-      for (int i=0; i<map.getNpix(); ++i)
-        assertEquals("inconsistency",map.nest2ring(i),(int)map.getPixel(i));
-      map.swapScheme();
-      for (int i=0; i<map.getNpix(); ++i)
-        assertEquals("inconsistency",i,(int)map.getPixel(i));
-      }
-    }
-  }
diff -Nru healpix-java-3.40/src/healpix/essentials/test/HealpixProcTest.java healpix-java-3.50/src/healpix/essentials/test/HealpixProcTest.java
--- healpix-java-3.40/src/healpix/essentials/test/HealpixProcTest.java	2015-07-05 02:10:50.000000000 -0400
+++ healpix-java-3.50/src/healpix/essentials/test/HealpixProcTest.java	1969-12-31 19:00:00.000000000 -0500
@@ -1,238 +0,0 @@
-/*
- *  This file is part of Healpix Java.
- *
- *  This code 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 code 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 code; 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.sourceforge.net
- */
-package healpix.essentials.test;
-
-import junit.framework.TestCase;
-import java.util.Random;
-import java.text.DecimalFormat;
-
-import healpix.essentials.*;
-
-/** Tests for the HealpixProc class
-
-    @copyright 2014 Max-Planck-Society
-    @author Martin Reinecke */
-public class HealpixProcTest extends TestCase {
-
-  static private final int nsamples=10000; // influences number of correctness tests
-  static private final DecimalFormat form = new DecimalFormat("##0.00");
-
-  private Zphi random_zphi(Random rng)
-    { return new Zphi(2*rng.nextDouble()-1,2*Math.PI*rng.nextDouble()); }
-
-  private Pointing random_dir(Random rng)
-    { return new Pointing(Math.acos(2*rng.nextDouble()-1),2*Math.PI*rng.nextDouble()); }
-
-  public void test_accuracy()throws Exception
-    {
-    System.out.println("Testing accuracy near the poles");
-
-    for (int order=0; order<=HealpixBase.order_max; ++order)
-      assertTrue("incorrect pix2ang",
-        HealpixProc.pix2angRing(order,1).theta>0.0);
-    }
-
-  public void test_ringnestring()throws Exception
-    {
-    System.out.println("Testing identity ring2nest(nest2ring(i))==i");
-    Random rng = new Random(5);
-
-    for (int o=0; o<=HealpixBase.order_max; ++o)
-      {
-      for (int m=0; m<nsamples; ++m)
-        {
-        long pix = (long)(rng.nextDouble()*HealpixProc.order2Npix(o));
-        assertEquals ("ringnestring problem",
-          HealpixProc.ring2nest(o,HealpixProc.nest2ring(o,pix)),pix);
-        }
-      }
-    }
-
-  public void test_pixangpix()throws Exception
-    {
-    System.out.println("Testing identity pix2ang(ang2pix(i))==i");
-    int omax=HealpixBase.order_max;
-    Random rng = new Random(5);
-    for (int o=0; o<=omax; ++o)
-      {
-      for (int m=0; m<nsamples; ++m)
-        {
-        long pix = (long)(rng.nextDouble()*HealpixProc.order2Npix(o));
-        assertEquals ("pixangpix problem",
-          pix, HealpixProc.ang2pixNest(o,HealpixProc.pix2angNest(o,pix)));
-        assertEquals ("pixangpix problem",
-          pix, HealpixProc.ang2pixRing(o,HealpixProc.pix2angRing(o,pix)));
-        }
-      }
-    }
-
-  public void test_neighbours() throws Exception
-    {
-    System.out.println("Testing neighbour function");
-    int omax=HealpixBase.order_max;
-    Random rng = new Random(5);
-    for (int o=0; o<=omax; ++o)
-      {
-      double maxang = 2.01*HealpixProc.maxPixrad(o);
-      for (int m=0; m<nsamples; ++m)
-        {
-        long pix = (long)(rng.nextDouble()*HealpixProc.order2Npix(o));
-        Vec3 v = HealpixProc.pix2vecRing(o,pix);
-        long [] nb = HealpixProc.neighboursRing(o,pix);
-        long [] nb2 = HealpixProc.neighboursNest(o,HealpixProc.ring2nest(o,pix));
-        int nnb=0;
-        for (int n=0; n<8; ++n)
-          {
-          if (nb[n]<0)
-            assertTrue("neighbour problem 1",nb2[n]<0);
-          else
-            {
-            ++nnb;
-            assertEquals("neighbour problem 2",HealpixProc.ring2nest(o,nb[n]),nb2[n]);
-            assertTrue("neighbour problem 3",HealpixProc.pix2vecRing(o,nb[n]).angle(v)<maxang);
-            }
-          }
-        assertTrue("neighbour problem 4 "+o+" "+nnb,(nnb>=7)||((o==0)&&(nnb>=6)));
-        }
-      }
-    }
-
-  public void test_query_disc_strict() throws Exception
-    {
-    System.out.println("Testing non-inclusive queryDisc()");
-    Random rng = new Random(5);
-    for (int o=0; o<=5; ++o)
-      {
-      int npix=(int)HealpixProc.order2Npix(o);
-      boolean[] map = new boolean[npix];
-      Vec3[] vmap = new Vec3[npix];
-      for (int m=0; m<npix; ++m)
-        {
-        map[m]=false;
-        vmap[m]=HealpixProc.pix2vecRing(o,m);
-        }
-      for (int m=0; m<nsamples; ++m)
-        {
-        Pointing ptg = random_dir (rng);
-        double rad = Math.PI * rng.nextDouble();
-        RangeSet rs = HealpixProc.queryDiscRing(o,ptg,rad);
-        Vec3 vptg = new Vec3(ptg);
-        double cosrad=Math.cos(rad);
-        for (int i=0; i<rs.nranges(); ++i)
-          for (long j=rs.ivbegin(i); j<rs.ivend(i); ++j)
-            map[(int)j]=true;
-        for (int i=0; i<npix; ++i)
-          {
-          boolean inside = vmap[i].dot(vptg)>cosrad;
-          assertFalse ("query_disc_strict problem",inside^map[i]);
-          }
-        for (int i=0; i<rs.nranges(); ++i)
-          for (long j=rs.ivbegin(i); j<rs.ivend(i); ++j)
-            map[(int)j]=false;
-        }
-      }
-    }
-
-  public void test_query_disc() throws Exception
-    {
-    System.out.println("Testing queryDisc() empirically");
-    int omax=17;
-    Random rng = new Random(5);
-    for (int o=0; o<=omax; ++o)
-      {
-      int niter=Math.max(1,Math.min(nsamples/1000,100000>>o));
-      for (int m=0; m<niter; ++m)
-        {
-        Pointing ptg = random_dir (rng);
-        double rad = Math.PI * rng.nextDouble();
-        RangeSet rs = HealpixProc.queryDiscRing(o,ptg,rad);
-        long nval = rs.nval();
-        rs = HealpixProc.queryDiscNest(o,ptg,rad);
-        assertEquals("queryDisc problem 1", nval,rs.nval());
-        rs = HealpixProc.queryDiscInclusiveRing(o,ptg,rad,4);
-        long nv1 = rs.nval();
-        rs = HealpixProc.queryDiscInclusiveNest(o,ptg,rad,4);
-        long nv2 = rs.nval();
-        assertTrue("queryDisc problem 2", nv1>=nv2);
-        assertTrue("queryDisc problem 3", nv2>=nval);
-        }
-      }
-    }
-
-  public void testQueryPolygon() throws Exception
-    {
-    System.out.println("Testing queryPolygon()");
-    Pointing[] corner = new Pointing[4];
-    corner[0]=new Pointing(new Vec3(1,0.01,0.01));
-    corner[1]=new Pointing(new Vec3(1,1,-0.3));
-    corner[2]=new Pointing(new Vec3(0.01,1,0.01));
-    corner[3]=new Pointing(new Vec3(0.01,0.01,1));
-    RangeSet lrs=HealpixProc.queryPolygonNest(10,corner);
-    assertEquals("QueryPolygon problem",lrs.nval(),1696714);
-    lrs=HealpixProc.queryPolygonInclusiveNest(10,corner,4);
-    assertEquals("QueryPolygon problem",lrs.nval(),1700206);
-    lrs=HealpixProc.queryPolygonRing(10,corner);
-    assertEquals("QueryPolygon problem",lrs.nval(),1696714);
-    lrs=HealpixProc.queryPolygonInclusiveRing(10,corner,4);
-    assertEquals("QueryPolygon problem",lrs.nval(),1700206);
-    }
-
-  public void testQueryPolygon2() throws Exception
-    {
-    System.out.println("Testing queryPolygon() empirically");
-    int omax=17;
-    Random rng = new Random(5);
-    for (int o=0; o<=omax; ++o)
-      {
-      int niter=Math.max(1,Math.min(nsamples/1000,100000>>o));
-      for (int m=0; m<niter; ++m)
-        {
-        Pointing[] corner = new Pointing[3];
-        corner[0]=random_dir(rng);
-        corner[1]=random_dir(rng);
-        corner[2]=random_dir(rng);
-        RangeSet rs = HealpixProc.queryPolygonRing(o,corner);
-        long nval = rs.nval();
-        rs = HealpixProc.queryPolygonNest(o,corner);
-        assertEquals("queryPolygon problem 1", nval,rs.nval());
-        rs = HealpixProc.queryPolygonInclusiveRing(o,corner,4);
-        long nv1 = rs.nval();
-        rs = HealpixProc.queryPolygonInclusiveNest(o,corner,4);
-        long nv2 = rs.nval();
-        assertTrue("queryPolygon problem 2", nv1>=nv2);
-        assertTrue("queryPolygon problem 3", nv2>=nval);
-        }
-      }
-    }
-
-  public void test() throws Exception
-    {
-    int o=8;
-    for (int i=0; i<HealpixProc.order2Npix(o); ++i)
-      {
-      assertEquals ("pixel mismatch_nest",i,HealpixProc.ang2pixNest(o,HealpixProc.pix2angNest(o,i)));
-      assertEquals ("pixel mismatch_nest",i,HealpixProc.vec2pixNest(o,HealpixProc.pix2vecNest(o,i)));
-      assertEquals ("pixel mismatch_ring",i,HealpixProc.ang2pixRing(o,HealpixProc.pix2angRing(o,i)));
-      assertEquals ("pixel mismatch_ring",i,HealpixProc.vec2pixRing(o,HealpixProc.pix2vecRing(o,i)));
-      assertEquals ("pixel mismatch",i,HealpixProc.ring2nest(o,HealpixProc.ang2pixRing(o,HealpixProc.pix2angNest(o,i))));
-      assertEquals ("pixel mismatch_ringnestring",i,HealpixProc.ring2nest(o,HealpixProc.nest2ring(o,i)));
-      }
-    }
-  }
diff -Nru healpix-java-3.40/src/healpix/essentials/test/MocQueryTest.java healpix-java-3.50/src/healpix/essentials/test/MocQueryTest.java
--- healpix-java-3.40/src/healpix/essentials/test/MocQueryTest.java	2015-07-14 05:06:15.000000000 -0400
+++ healpix-java-3.50/src/healpix/essentials/test/MocQueryTest.java	1969-12-31 19:00:00.000000000 -0500
@@ -1,369 +0,0 @@
-/*
- *  This file is part of Healpix Java.
- *
- *  This code 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 code 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 code; 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.sourceforge.net
- */
-package healpix.essentials.test;
-
-import healpix.essentials.*;
-import junit.framework.TestCase;
-import java.io.*;
-import java.util.Arrays;
-import java.util.ArrayList;
-
-/** Tests for the MocQuery class
-
-    @copyright 2015 Max-Planck-Society
-    @author Martin Reinecke */
-public class MocQueryTest extends TestCase
-  {
-  private ArrayList<Vec3> rawToPoly(double[] inp) throws Exception
-    {
-    HealpixUtils.check((inp.length>=6)&&((inp.length&1)==0),
-      "bad input array");
-    ArrayList<Vec3> res = new ArrayList<Vec3>();
-    for (int i=0; i<inp.length; i+=2)
-      res.add(new Vec3(new Pointing(Math.PI/2 - Math.toRadians(inp[i+1]),
-        Math.toRadians(inp[i]))));
-    return res;
-    }
-  private void checkPoly(ArrayList<Vec3> poly, int o1, int o2, String out)
-    throws Exception
-    {
-    Moc moc = MocQuery.queryGeneralPolygonInclusive (poly,o1,o1);
-    if (out!="")
-      MocFitsIO.mocToFits(moc,out+"_inc_"+o1+".fits");
-    for (int o=o1+1; o<=o2; ++o)
-      {
-      Moc moc2 = MocQuery.queryGeneralPolygonInclusive (poly,o1,o2);
-      assertTrue("inconsistency",moc.contains(moc2));
-      if (out!="")
-        MocFitsIO.mocToFits(moc2,out+"_inc_"+o+".fits");
-      moc=moc2;
-      }
-    Moc moc2 = MocQuery.queryGeneralPolygon(poly,o1);
-    if (out!="")
-      MocFitsIO.mocToFits(moc2,out+".fits");
-    assertTrue("inconsistency",moc.contains(moc2));
-    }
-  public void test1() throws Exception
-    {
-    double[] polyraw=new double[]{
-      83.6479647404001,  22.06796566083695,
-      83.57919759304697, 22.014902754311912,
-      83.54565527259793, 22.05666932013043,
-      83.54535325267885, 22.05666728060237,
-      83.54535545323692, 22.056387364445676,
-      83.54535985432697, 22.05582753212609,
-      83.54536865640274, 22.05470786746255,
-      83.54537525786826, 22.05386811894398,
-      83.53952949498002, 21.952773396955234,
-      83.63157603991105, 21.995362438376056,
-      83.64144959973622, 21.965751089665403,
-      83.69912966373616, 22.00612703969729 };
-
-    checkPoly(rawToPoly(polyraw),13,15,"");
-    }
-  public void test2() throws Exception
-    {
-    double[] polyraw=new double[]{
-      83.69572488226052, 22.01842407483951,
-      83.66469321144844, 22.05155150183524,
-      83.66439120028902, 22.051549680680765,
-      83.62952475535761, 22.02838142338798,
-      83.58771024980035, 22.04715033027345,
-      83.5874082491367,  22.04714836793211,
-      83.58741036646086, 22.0468684509572,
-      83.58741671838312, 22.046028700022926,
-      83.57147626994606, 21.99805614401068,
-      83.59369254263831, 21.934377044862455,
-      83.59369043939574, 21.93465696148893,
-      83.59368833614487, 21.934936878119167,
-      83.59338236664615, 21.935494760357145,
-      83.59338026277467, 21.93577467699384,
-      83.64687451268995, 21.966904215256918,
-      83.60550939897153, 22.00919444338953,
-      83.66653272555045, 22.004534367269507,
-      83.69542484507058, 22.018142392123163 };
-
-    checkPoly(rawToPoly(polyraw),13,15,"");
-    }
-
-  public void test3() throws Exception
-    {
-    ArrayList<Vec3> vert=new ArrayList<Vec3>();
-    vert.add(new Vec3(new Pointing(1.1523428941043317,1.000795791041251)));
-    vert.add(new Vec3(new Pointing(1.1523106929911657,1.0008281306683644)));
-    vert.add(new Vec3(new Pointing(1.1521818924889993,1.0009574985526972)));
-    vert.add(new Vec3(new Pointing(1.1519887035905163,1.001151578519077)));
-    vert.add(new Vec3(new Pointing(1.151859918897493,1.0012809839336458)));
-    vert.add(new Vec3(new Pointing(1.1514894198468866,1.001263637028638)));
-    vert.add(new Vec3(new Pointing(1.1513659202048774,1.0012578536443903)));
-    vert.add(new Vec3(new Pointing(1.1511859573237597,1.0011139425394953)));
-    vert.add(new Vec3(new Pointing(1.1510060020113047,1.0009700085527964)));
-    vert.add(new Vec3(new Pointing(1.1508556031353578,1.0008613172356937)));
-    vert.add(new Vec3(new Pointing(1.150673007120061,1.0007849744501682)));
-    vert.add(new Vec3(new Pointing(1.1503938085112773,1.0008057187152946)));
-    vert.add(new Vec3(new Pointing(1.150205908484378,1.0008646491036832)));
-    vert.add(new Vec3(new Pointing(1.149953611594119,1.000988341677547)));
-    vert.add(new Vec3(new Pointing(1.1497335179693469,1.0010796806589697)));
-    vert.add(new Vec3(new Pointing(1.1494247698862567,1.0010651879076278)));
-    vert.add(new Vec3(new Pointing(1.1492448165599576,1.0009211385295873)));
-    vert.add(new Vec3(new Pointing(1.149000469199188,1.0008418420185987)));
-    vert.add(new Vec3(new Pointing(1.1485894925444542,1.000279935669881)));
-    vert.add(new Vec3(new Pointing(1.1486539077047668,1.0002151640462313)));
-    vert.add(new Vec3(new Pointing(1.1490324086471566,1.0000296562389843)));
-    vert.add(new Vec3(new Pointing(1.1492203271505665,0.9999707639528252)));
-    vert.add(new Vec3(new Pointing(1.1495639559481354,0.9998853760122856)));
-    vert.add(new Vec3(new Pointing(1.149848517849616,0.9997294255486839)));
-    vert.add(new Vec3(new Pointing(1.1499773768285775,0.9995999921162992)));
-    vert.add(new Vec3(new Pointing(1.1501062421175312,0.9994705737522844)));
-    vert.add(new Vec3(new Pointing(1.1501733657022064,0.9993382245815566)));
-    vert.add(new Vec3(new Pointing(1.150157309455921,0.9989646985587307)));
-    vert.add(new Vec3(new Pointing(1.1502783613271745,0.9982588937208289)));
-    vert.add(new Vec3(new Pointing(1.150367358658019,0.9975854875791592)));
-    vert.add(new Vec3(new Pointing(1.1503145561122339,0.9966002329829549)));
-    vert.add(new Vec3(new Pointing(1.1501837017642849,0.9960177261452899)));
-    vert.add(new Vec3(new Pointing(1.1500880289072624,0.9953352142578803)));
-    vert.add(new Vec3(new Pointing(1.1498339618638964,0.9947464292684306)));
-    vert.add(new Vec3(new Pointing(1.1496599663238942,0.9944665891792631)));
-    vert.add(new Vec3(new Pointing(1.1495211017074738,0.9940867625529576)));
-    vert.add(new Vec3(new Pointing(1.1494032633666398,0.993945254823653)));
-    vert.add(new Vec3(new Pointing(1.1492854324600088,0.9938037321908275)));
-    vert.add(new Vec3(new Pointing(1.1491647775622915,0.9937298631728655)));
-    vert.add(new Vec3(new Pointing(1.1489093237140704,0.9939204821489465)));
-    vert.add(new Vec3(new Pointing(1.1487240963858985,0.9939111896936369)));
-    vert.add(new Vec3(new Pointing(1.148418211419246,0.9938280074878991)));
-    vert.add(new Vec3(new Pointing(1.148203527561705,0.9937833060402974)));
-    vert.add(new Vec3(new Pointing(1.1480562505373242,0.9936062948138628)));
-    vert.add(new Vec3(new Pointing(1.1479678899060295,0.9935000768652547)));
-    vert.add(new Vec3(new Pointing(1.1479089851456499,0.9934292602260698)));
-    vert.add(new Vec3(new Pointing(1.1478263164713338,0.9931876107503619)));
-    vert.add(new Vec3(new Pointing(1.147658188833066,0.9927719711268423)));
-    vert.add(new Vec3(new Pointing(1.147605019627341,0.9925656960713723)));
-    vert.add(new Vec3(new Pointing(1.147513838399067,0.9925271325090353)));
-    vert.add(new Vec3(new Pointing(1.1469790356795493,0.9927375232998785)));
-    vert.add(new Vec3(new Pointing(1.1467586597155184,0.9928281691313717)));
-    vert.add(new Vec3(new Pointing(1.1466646212864107,0.9928573452285496)));
-    vert.add(new Vec3(new Pointing(1.146570583168876,0.9928865238140747)));
-    vert.add(new Vec3(new Pointing(1.1464822508174166,0.9927802065018877)));
-    vert.add(new Vec3(new Pointing(1.1464233649158908,0.9927093236024059)));
-    vert.add(new Vec3(new Pointing(1.1463350395636842,0.9926029922143758)));
-    vert.add(new Vec3(new Pointing(1.1464082297063476,0.9923351250888106)));
-    vert.add(new Vec3(new Pointing(1.1465403155639036,0.9921381737414078)));
-    vert.add(new Vec3(new Pointing(1.146801650920068,0.9918120793817878)));
-    vert.add(new Vec3(new Pointing(1.146992632145478,0.9916860897831967)));
-    vert.add(new Vec3(new Pointing(1.147336526500701,0.9916018945040467)));
-    vert.add(new Vec3(new Pointing(1.1475540582351127,0.991579108720834)));
-    vert.add(new Vec3(new Pointing(1.148297344412475,0.9908370227283142)));
-    vert.add(new Vec3(new Pointing(1.14831771135701,0.9903631889078771)));
-    vert.add(new Vec3(new Pointing(1.1483410904887272,0.9898216751345671)));
-    vert.add(new Vec3(new Pointing(1.14817642568152,0.9893381849506938)));
-    vert.add(new Vec3(new Pointing(1.1478619397258643,0.9887449725688633)));
-    vert.add(new Vec3(new Pointing(1.1476621504872502,0.9883612311158905)));
-    vert.add(new Vec3(new Pointing(1.1473389454791498,0.987970892009681)));
-    vert.add(new Vec3(new Pointing(1.1470745474697959,0.9876514390156884)));
-    vert.add(new Vec3(new Pointing(1.1467220762850698,0.9872253830842613)));
-    vert.add(new Vec3(new Pointing(1.1465134990729606,0.9870445283107344)));
-    vert.add(new Vec3(new Pointing(1.1463576636239432,0.9870701715700294)));
-    vert.add(new Vec3(new Pointing(1.1461311065061512,0.987295784658764)));
-    vert.add(new Vec3(new Pointing(1.145969291549504,0.9874569649988388)));
-    vert.add(new Vec3(new Pointing(1.1456780489082319,0.9877471487418389)));
-    vert.add(new Vec3(new Pointing(1.1453544826095992,0.9880696643744283)));
-    vert.add(new Vec3(new Pointing(1.1451309779989192,0.9882276968098427)));
-    vert.add(new Vec3(new Pointing(1.1449223325837785,0.9880468062013319)));
-    vert.add(new Vec3(new Pointing(1.144684321314146,0.9878303468533963)));
-    vert.add(new Vec3(new Pointing(1.1444786880119573,0.9875815784705101)));
-    vert.add(new Vec3(new Pointing(1.1444055321874065,0.9871359210384268)));
-    vert.add(new Vec3(new Pointing(1.1443527978610553,0.9869292081606309)));
-    vert.add(new Vec3(new Pointing(1.1443588066568586,0.9867935954286845)));
-    vert.add(new Vec3(new Pointing(1.1443294428641322,0.9867580408743656)));
-    vert.add(new Vec3(new Pointing(1.1441178863108807,0.9866447588708069)));
-    vert.add(new Vec3(new Pointing(1.143627025593574,0.9865504721602422)));
-    vert.add(new Vec3(new Pointing(1.1430714198687517,0.9865206748900628)));
-    vert.add(new Vec3(new Pointing(1.142486453971728,0.9864552736851653)));
-    vert.add(new Vec3(new Pointing(1.1421130353865951,0.9865032583536448)));
-    vert.add(new Vec3(new Pointing(1.1418013514800418,0.9865545719393494)));
-    vert.add(new Vec3(new Pointing(1.1415280685012117,0.9864378231638371)));
-    vert.add(new Vec3(new Pointing(1.1413195436592867,0.9862564662025781)));
-    vert.add(new Vec3(new Pointing(1.1411140566169835,0.9860071695710151)));
-    vert.add(new Vec3(new Pointing(1.1410583793726072,0.9858680266790968)));
-    vert.add(new Vec3(new Pointing(1.1411585594318707,0.9857032675075046)));
-    vert.add(new Vec3(new Pointing(1.1415471911174158,0.9853159421723982)));
-    vert.add(new Vec3(new Pointing(1.1417091373202277,0.9851545968685336)));
-    vert.add(new Vec3(new Pointing(1.141935878135893,0.9849287531836823)));
-    vert.add(new Vec3(new Pointing(1.1421919741278386,0.9847385729150904)));
-    vert.add(new Vec3(new Pointing(1.1427212823451636,0.9846653708690231)));
-    vert.add(new Vec3(new Pointing(1.1429388730086534,0.9846432208437782)));
-    vert.add(new Vec3(new Pointing(1.1431888603402285,0.9845888377168718)));
-    vert.add(new Vec3(new Pointing(1.143221257341095,0.9845566013231962)));
-    vert.add(new Vec3(new Pointing(1.1431393920272823,0.9843141087835374)));
-    vert.add(new Vec3(new Pointing(1.142940242012983,0.9839291446460309)));
-    vert.add(new Vec3(new Pointing(1.1427704685698539,0.9835797337470248)));
-    vert.add(new Vec3(new Pointing(1.1426917873195213,0.9832693018292363)));
-    vert.add(new Vec3(new Pointing(1.142613142293535,0.9829588475331977)));
-    vert.add(new Vec3(new Pointing(1.1426935245487904,0.9825551447276581)));
-    vert.add(new Vec3(new Pointing(1.1428587549013667,0.9823262384230973)));
-    vert.add(new Vec3(new Pointing(1.1432802997807938,0.9819076068355195)));
-    vert.add(new Vec3(new Pointing(1.1435428818201463,0.981582241584326)));
-    vert.add(new Vec3(new Pointing(1.1438023569877103,0.9813247693528765)));
-    vert.add(new Vec3(new Pointing(1.1440879942426359,0.981170799141964)));
-    vert.add(new Vec3(new Pointing(1.1443087617014966,0.9810812052364875)));
-    vert.add(new Vec3(new Pointing(1.1444939405572025,0.9810915890969772)));
-    vert.add(new Vec3(new Pointing(1.1446435321631656,0.9812019262076423)));
-    vert.add(new Vec3(new Pointing(1.1449657419610033,0.9815937325674373)));
-    vert.add(new Vec3(new Pointing(1.145170814762998,0.9818430040096161)));
-    vert.add(new Vec3(new Pointing(1.145405212420505,0.9821278286770655)));
-    vert.add(new Vec3(new Pointing(1.1455810307686392,0.982341407316913)));
-    vert.add(new Vec3(new Pointing(1.1456396407122253,0.9824125926080799)));
-    vert.add(new Vec3(new Pointing(1.1457568663384885,0.9825549518114552)));
-    vert.add(new Vec3(new Pointing(1.1458447905784235,0.982661711260155)));
-    vert.add(new Vec3(new Pointing(1.146056176224855,0.9827752848212115)));
-    vert.add(new Vec3(new Pointing(1.1464203363305736,0.982931223860804)));
-    vert.add(new Vec3(new Pointing(1.1465700046565381,0.983041338988599)));
-    vert.add(new Vec3(new Pointing(1.146931084242241,0.9832649203344934)));
-    vert.add(new Vec3(new Pointing(1.147304554977569,0.983217580321881)));
-    vert.add(new Vec3(new Pointing(1.14755456833011,0.983163460791517)));
-    vert.add(new Vec3(new Pointing(1.1476518102952684,0.9830670054161794)));
-    vert.add(new Vec3(new Pointing(1.147911138996274,0.9828098319777566)));
-    vert.add(new Vec3(new Pointing(1.1480146153175843,0.9825780284118409)));
-    vert.add(new Vec3(new Pointing(1.1478512630860116,0.982093928824457)));
-    vert.add(new Vec3(new Pointing(1.1477465895705665,0.981680894029768)));
-    vert.add(new Vec3(new Pointing(1.1477037064890643,0.9812712698299393)));
-    vert.add(new Vec3(new Pointing(1.1476901713851657,0.980897208503522)));
-    vert.add(new Vec3(new Pointing(1.147738413955949,0.9805266127850084)));
-    vert.add(new Vec3(new Pointing(1.1479718818582025,0.9801664735990022)));
-    vert.add(new Vec3(new Pointing(1.148205397839398,0.9798064091969002)));
-    vert.add(new Vec3(new Pointing(1.1483708576902831,0.9795782695316553)));
-    vert.add(new Vec3(new Pointing(1.1487928200059858,0.9791611823574279)));
-    vert.add(new Vec3(new Pointing(1.1493382912635042,0.9787512843635041)));
-    vert.add(new Vec3(new Pointing(1.1502609222180684,0.9788716216588957)));
-    vert.add(new Vec3(new Pointing(1.1504396821178993,0.9790173766494347)));
-    vert.add(new Vec3(new Pointing(1.1507908399518807,0.9794440181022032)));
-    vert.add(new Vec3(new Pointing(1.1509893471305994,0.9798280210118206)));
-    vert.add(new Vec3(new Pointing(1.1511815695494167,0.9803471360053592)));
-    vert.add(new Vec3(new Pointing(1.1513477656945341,0.9807630544316528)));
-    vert.add(new Vec3(new Pointing(1.1516604798024512,0.98135646536512)));
-    vert.add(new Vec3(new Pointing(1.1517033801181038,0.981765361770002)));
-    vert.add(new Vec3(new Pointing(1.1517170406506425,0.9821387451013951)));
-    vert.add(new Vec3(new Pointing(1.1515842233393097,0.9823346503008543)));
-    vert.add(new Vec3(new Pointing(1.1513896921866162,0.9825271705205277)));
-    vert.add(new Vec3(new Pointing(1.1511627565046656,0.9827518193104232)));
-    vert.add(new Vec3(new Pointing(1.1508710094941494,0.9830407197788995)));
-    vert.add(new Vec3(new Pointing(1.1506441165054242,0.9832654717657893)));
-    vert.add(new Vec3(new Pointing(1.150482061529942,0.9834260365777083)));
-    vert.add(new Vec3(new Pointing(1.1503524244193444,0.9835545050450514)));
-    vert.add(new Vec3(new Pointing(1.1502258785647448,0.983615364692989)));
-    vert.add(new Vec3(new Pointing(1.150040689827067,0.9836052230787131)));
-    vert.add(new Vec3(new Pointing(1.1497289561324662,0.9836559547866632)));
-    vert.add(new Vec3(new Pointing(1.1496348192975478,0.9836847052609023)));
-    vert.add(new Vec3(new Pointing(1.1494727890458836,0.9838453720714817)));
-    vert.add(new Vec3(new Pointing(1.1494049018076335,0.9839772939956009)));
-    vert.add(new Vec3(new Pointing(1.149324740233309,0.9843798294222985)));
-    vert.add(new Vec3(new Pointing(1.1492739766976383,0.9848178951560865)));
-    vert.add(new Vec3(new Pointing(1.1492880620951265,0.9851916630592842)));
-    vert.add(new Vec3(new Pointing(1.1494023951081926,0.9854012904878543)));
-    vert.add(new Vec3(new Pointing(1.149519781095103,0.9855432489469033)));
-    vert.add(new Vec3(new Pointing(1.1497839272856774,0.9858626006164312)));
-    vert.add(new Vec3(new Pointing(1.1501482692615095,0.986017767907073)));
-    vert.add(new Vec3(new Pointing(1.1506158045877952,0.9859411952965156)));
-    vert.add(new Vec3(new Pointing(1.1510863719564317,0.9857970535978254)));
-    vert.add(new Vec3(new Pointing(1.1514010989298469,0.9856784621213586)));
-    vert.add(new Vec3(new Pointing(1.1517158310959092,0.9855599035665571)));
-    vert.add(new Vec3(new Pointing(1.1520923005998371,0.9854447044733927)));
-    vert.add(new Vec3(new Pointing(1.152556811551436,0.9854358697505938)));
-    vert.add(new Vec3(new Pointing(1.152936329868326,0.9852531893604244)));
-    vert.add(new Vec3(new Pointing(1.1534980080389958,0.9851480997557343)));
-    vert.add(new Vec3(new Pointing(1.1542448858126413,0.9850530625072047)));
-    vert.add(new Vec3(new Pointing(1.1548713566503563,0.9848839302619462)));
-    vert.add(new Vec3(new Pointing(1.155238694559804,0.9849714230186063)));
-    vert.add(new Vec3(new Pointing(1.155511913488695,0.9850876232716619)));
-    vert.add(new Vec3(new Pointing(1.1556879733525678,0.9852999969140172)));
-    vert.add(new Vec3(new Pointing(1.1559784112498703,0.9857213321874994)));
-    vert.add(new Vec3(new Pointing(1.1559865844022958,0.9862288863472906)));
-    vert.add(new Vec3(new Pointing(1.1560385791492556,0.9871444375227638)));
-    vert.add(new Vec3(new Pointing(1.1560116805212006,0.9877515244318255)));
-    vert.add(new Vec3(new Pointing(1.1558379990039347,0.9881818725706057)));
-    vert.add(new Vec3(new Pointing(1.155543873841697,0.9885383490226638)));
-    vert.add(new Vec3(new Pointing(1.1552557042400238,0.9887599602232404)));
-    vert.add(new Vec3(new Pointing(1.1549352096290768,0.9890137597369755)));
-    vert.add(new Vec3(new Pointing(1.1546147391191914,0.9892676311236104)));
-    vert.add(new Vec3(new Pointing(1.1542354927708685,0.9894508532485825)));
-    vert.add(new Vec3(new Pointing(1.1538621301597058,0.9894990936671686)));
-    vert.add(new Vec3(new Pointing(1.1536181187451178,0.9894187147674598)));
-    vert.add(new Vec3(new Pointing(1.1533447121031735,0.9893029412643478)));
-    vert.add(new Vec3(new Pointing(1.1529537305101472,0.9890455986187472)));
-    vert.add(new Vec3(new Pointing(1.1524980830083356,0.9888524937214215)));
-    vert.add(new Vec3(new Pointing(1.1523481741773312,0.9887430639190622)));
-    vert.add(new Vec3(new Pointing(1.1520629738824093,0.988897439436812)));
-    vert.add(new Vec3(new Pointing(1.1518395192779805,0.9890550816485132)));
-    vert.add(new Vec3(new Pointing(1.1515513932259047,0.9892771221299574)));
-    vert.add(new Vec3(new Pointing(1.1513250228779512,0.9895024356245301)));
-    vert.add(new Vec3(new Pointing(1.1510957407699558,0.9897953995250245)));
-    vert.add(new Vec3(new Pointing(1.1508988210950766,0.9900562178915127)));
-    vert.add(new Vec3(new Pointing(1.150763665085474,0.9903202764372446)));
-    vert.add(new Vec3(new Pointing(1.1507843367123325,0.990558526439852)));
-    vert.add(new Vec3(new Pointing(1.1507992237525468,0.9909320025905168)));
-    vert.add(new Vec3(new Pointing(1.1508522671724446,0.9911380213792874)));
-    vert.add(new Vec3(new Pointing(1.1509376417668262,0.9913118073666528)));
-    vert.add(new Vec3(new Pointing(1.1510230276226834,0.9914855800960104)));
-    vert.add(new Vec3(new Pointing(1.1511701646336845,0.9916624962872871)));
-    vert.add(new Vec3(new Pointing(1.1513467444499845,0.9918747650352789)));
-    vert.add(new Vec3(new Pointing(1.151493907126133,0.9920516301034698)));
-    vert.add(new Vec3(new Pointing(1.15167051772407,0.9922638375354705)));
-    vert.add(new Vec3(new Pointing(1.1517825427272692,0.9925404659613722)));
-    vert.add(new Vec3(new Pointing(1.1518945962236837,0.9928170667717601)));
-    vert.add(new Vec3(new Pointing(1.151944936626454,0.9930905238387734)));
-    vert.add(new Vec3(new Pointing(1.1519364038488704,0.9932932756669433)));
-    vert.add(new Vec3(new Pointing(1.1519545044629247,0.9935989574717053)));
-    vert.add(new Vec3(new Pointing(1.1518899290891478,0.9936634411834805)));
-    vert.add(new Vec3(new Pointing(1.1518576419864373,0.9936956844356148)));
-    vert.add(new Vec3(new Pointing(1.1515670755926695,0.9939859156123069)));
-    vert.add(new Vec3(new Pointing(1.1514056634584344,0.9941471877691483)));
-    vert.add(new Vec3(new Pointing(1.151209167317511,0.9944083526588667)));
-    vert.add(new Vec3(new Pointing(1.1510098905412778,0.9947371775119466)));
-    vert.add(new Vec3(new Pointing(1.1509074670044037,0.9949692293531077)));
-    vert.add(new Vec3(new Pointing(1.1507939027845748,0.9954717874109883)));
-    vert.add(new Vec3(new Pointing(1.1507154681212395,0.9958744790360815)));
-    vert.add(new Vec3(new Pointing(1.150728328381526,0.9963155562525036)));
-    vert.add(new Vec3(new Pointing(1.1507145219246022,0.9966536818156724)));
-    vert.add(new Vec3(new Pointing(1.150698010346289,0.9970594382294491)));
-    vert.add(new Vec3(new Pointing(1.1507515235186312,0.9972653214392541)));
-    vert.add(new Vec3(new Pointing(1.15074330622707,0.9974681979653209)));
-    vert.add(new Vec3(new Pointing(1.150794120124925,0.9977416918927585)));
-    vert.add(new Vec3(new Pointing(1.1508449617882088,0.9980151735411477)));
-    vert.add(new Vec3(new Pointing(1.150810006084698,0.9981151193696918)));
-    vert.add(new Vec3(new Pointing(1.1508045689258863,0.9982503689627922)));
-    vert.add(new Vec3(new Pointing(1.1507669084789147,0.9984179465727627)));
-    vert.add(new Vec3(new Pointing(1.1507882982747644,0.9986561219049502)));
-    vert.add(new Vec3(new Pointing(1.1508097091375338,0.9988942928018621)));
-    vert.add(new Vec3(new Pointing(1.1508955843794588,0.9990677867461779)));
-    vert.add(new Vec3(new Pointing(1.1509814707456794,0.9992412674747779)));
-    vert.add(new Vec3(new Pointing(1.1510968986908656,0.999450015299713)));
-    vert.add(new Vec3(new Pointing(1.1511559609826625,0.9995205731460943)));
-    vert.add(new Vec3(new Pointing(1.151370737557223,0.9995646668380104)));
-    vert.add(new Vec3(new Pointing(1.1514620182432866,0.9996028778795772)));
-    vert.add(new Vec3(new Pointing(1.1515855148424001,0.9996087523184793)));
-    vert.add(new Vec3(new Pointing(1.1516794788958802,0.9995793575868965)));
-    vert.add(new Vec3(new Pointing(1.15174122717978,0.9995822953104395)));
-    vert.add(new Vec3(new Pointing(1.1518647237644064,0.9995881703312073)));
-    vert.add(new Vec3(new Pointing(1.151894256435611,0.9996234359315822)));
-    vert.add(new Vec3(new Pointing(1.1519855379350588,0.9996616359063851)));
-    vert.add(new Vec3(new Pointing(1.152015071556617,0.9996968986628608)));
-    checkPoly(vert,13,17,"");
-    }
-  }
diff -Nru healpix-java-3.40/src/healpix/essentials/test/MocTest.java healpix-java-3.50/src/healpix/essentials/test/MocTest.java
--- healpix-java-3.40/src/healpix/essentials/test/MocTest.java	2015-07-05 02:56:22.000000000 -0400
+++ healpix-java-3.50/src/healpix/essentials/test/MocTest.java	1969-12-31 19:00:00.000000000 -0500
@@ -1,117 +0,0 @@
-/*
- *  This file is part of Healpix Java.
- *
- *  This code 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 code 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 code; 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.sourceforge.net
- */
-package healpix.essentials.test;
-
-import healpix.essentials.*;
-import junit.framework.TestCase;
-import java.io.*;
-import java.util.Random;
-import java.util.Arrays;
-
-/** Tests for the Moc class
-
-    @copyright 2015 Max-Planck-Society
-    @author Martin Reinecke */
-public class MocTest extends TestCase
-  {
-  private static Moc randomMoc(int num, long start, int dist)
-    {
-    Random rng = new Random();
-    Moc moc = new Moc();
-    long curval=start+(1L<<58);
-    for (int i=0; i<num; ++i)
-      {
-      long v1=curval+1+rng.nextInt(dist);
-      long v2=v1+1+rng.nextInt(dist);
-      moc.addPixelRange(29,v1,v2);
-      curval=v2;
-      }
-    return moc;
-    }
-
-  public void testSimple() throws Exception
-    {
-    Moc moc=new Moc();
-    moc.addPixelRange(0,4,5);
-    moc.addPixelRange(0,6,7);
-    moc.addPixelRange(2,4,17);
-    moc.addPixelRange(10,3000000,3000001);
-
-    assertEquals("inconsistency",moc,moc.complement().complement());
-    assertEquals("inconsistency",moc,MocStringIO.mocFromString(" 0/4, 6 2/ \t 4 -16 10/3000000 \t\n "));
-    assertEquals("inconsistency",moc,MocStringIO.mocFromString("0/6 2/ 5 2/4 2/6- 16 0/4  10/3000000"));
-    assertEquals("inconsistency",moc,MocStringIO.mocFromString
-      ("{\"0\":[6] , \"2\": [5 ], \"2\":[  4,6,7,8,9,10,11,12,13,14,15,16], \"0\":[4],  \"10\":[3000000]}"));
-    assertEquals("inconsistency",moc,MocStringIO.mocFromString(MocStringIO.mocToStringASCII(moc)));
-    assertEquals("inconsistency",moc,MocStringIO.mocFromString(MocStringIO.mocToStringJSON(moc)));
-    assertEquals("inconsistency",moc,Moc.fromUniq(moc.toUniq()));
-    assertEquals("inconsistency",moc.maxOrder(),10);
-    Moc xtmp = moc.degradedToOrder(8,false);
-    assertTrue("inconsistency",moc.contains(xtmp));
-    assertFalse("inconsistency",xtmp.contains(moc));
-    assertTrue("inconsistency",xtmp.overlaps(moc));
-    xtmp=moc.degradedToOrder(8,true);
-    assertFalse("inconsistency",moc.contains(xtmp));
-    assertTrue("inconsistency",xtmp.contains(moc));
-    assertEquals("inconsistency",moc,Moc.fromCompressed(moc.toCompressed()));
-    }
-
-  public void testPeano() throws Exception
-    {
-    HealpixBase base = new HealpixBase (8192,Scheme.NESTED);
-    RangeSet lrs=base.queryDisc(new Pointing(new Vec3(1,0,0)),Constants.halfpi/9.);
-    Moc moc=new Moc(lrs,13);
-
-     long[] arr=moc.toUniq();
-    for (int i=0; i<arr.length; ++i)
-      {
-      int order=HealpixUtils.uniq2order(arr[i]);
-      long shift=1L<<(2*order+2);
-      arr[i]=HealpixUtils.nest2peano(arr[i]-shift,order)+shift;
-      }
-    Arrays.sort(arr);
-    Moc pmoc=Moc.fromUniq(arr);
-    arr=pmoc.toUniq();
-    for (int i=0; i<arr.length; ++i)
-      {
-      int order=HealpixUtils.uniq2order(arr[i]);
-      long shift=1L<<(2*order+2);
-      arr[i]=HealpixUtils.peano2nest(arr[i]-shift,order)+shift;
-      }
-    Arrays.sort(arr);
-    Moc moc2=Moc.fromUniq(arr);
-    assertEquals(moc,moc2);
-    }
-
-  public void testOps() throws Exception
-    {
-    int niter = 100;
-    Moc full = MocStringIO.mocFromString("0/0-11");
-    Moc empty = MocStringIO.mocFromString("");
-    for (int iter=0; iter<niter; ++iter)
-      {
-      Moc a = randomMoc(1000, 0, 100);
-      assertEquals(a.complement().complement(),a);
-      assertFalse(a.overlaps(a.complement()));
-      assertEquals(a.union(a.complement()),full);
-      assertEquals(a.intersection(a.complement()),empty);
-      }
-    }
-  }
diff -Nru healpix-java-3.40/src/healpix/essentials/test/RangeSetTest.java healpix-java-3.50/src/healpix/essentials/test/RangeSetTest.java
--- healpix-java-3.40/src/healpix/essentials/test/RangeSetTest.java	2015-07-05 02:10:50.000000000 -0400
+++ healpix-java-3.50/src/healpix/essentials/test/RangeSetTest.java	1969-12-31 19:00:00.000000000 -0500
@@ -1,317 +0,0 @@
-/*
- *  This file is part of Healpix Java.
- *
- *  This code 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 code 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 code; 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.sourceforge.net
- */
-package healpix.essentials.test;
-
-import healpix.essentials.RangeSet;
-import junit.framework.TestCase;
-import java.io.*;
-import java.util.Random;
-
-/** Tests for the RangeSet class
-
-    @copyright 2014 Max-Planck-Society
-    @author Martin Reinecke */
-public class RangeSetTest extends TestCase {
-
-  private static RangeSet randomRangeSet(Random rng, int num, long start,
-    int dist)
-    {
-    RangeSet rs = new RangeSet(num);
-    long curval=start;
-    for (int i=0; i<num; ++i)
-      {
-      long v1=curval+1+rng.nextInt(dist);
-      long v2=v1+1+rng.nextInt(dist);
-      rs.append(v1,v2);
-      curval=v2;
-      }
-    return rs;
-    }
-
-  public void testAppend()
-    {
-    RangeSet b = new RangeSet();
-    b.append(1,11);
-    assertEquals(b,new RangeSet(new long[]{1,11}));
-    b.append(10,15);
-    assertEquals(b,new RangeSet(new long[]{1,15}));
-    b.append(1,15);
-    assertEquals(b,new RangeSet(new long[]{1,15}));
-    b.append(7,15);
-    assertEquals(b,new RangeSet(new long[]{1,15}));
-    b.append(30,41);
-    assertEquals(b,new RangeSet(new long[]{1,15,30,41}));
-    try
-      {
-      b.append(29,31);
-      fail("Should have raised an IllegalArgumentException");
-      }
-    catch (IllegalArgumentException expected) {}
-    }
-  public void testContains()
-    {
-    RangeSet b=new RangeSet(new long[]{1,11,30,41});
-    assertTrue(!b.contains(0));
-    assertTrue(b.contains(1));
-    assertTrue(b.contains(5));
-    assertTrue(b.contains(10));
-    assertTrue(!b.contains(11));
-    assertTrue(!b.contains(29));
-    assertTrue(b.contains(30));
-    assertTrue(b.contains(35));
-    assertTrue(b.contains(40));
-    assertTrue(!b.contains(41));
-    }
-  public void testAdd()
-    {
-    RangeSet b = new RangeSet();
-    b.add(5, 11);
-    assertEquals(b,new RangeSet(new long[]{5,11}));
-    b.add(1, 7);
-    assertEquals(b,new RangeSet(new long[]{1,11}));
-    b.add(1, 11);
-    assertEquals(b,new RangeSet(new long[]{1,11}));
-    b.add(30, 41);
-    assertEquals(b,new RangeSet(new long[]{1,11,30,41}));
-    b.add(1, 11);
-    assertEquals(b,new RangeSet(new long[]{1,11,30,41}));
-    b.add(-1,0);
-    assertEquals(b,new RangeSet(new long[]{-1,0,1,11,30,41}));
-    b.add(-2,-1);
-    assertEquals(b,new RangeSet(new long[]{-2,0,1,11,30,41}));
-    b.add(-2,-1);
-    assertEquals(b,new RangeSet(new long[]{-2,0,1,11,30,41}));
-    b.add(2, 11);
-    assertEquals(b,new RangeSet(new long[]{-2,0,1,11,30,41}));
-    b.add(1, 10);
-    assertEquals(b,new RangeSet(new long[]{-2,0,1,11,30,41}));
-    b.add(15, 21);
-    assertEquals(b,new RangeSet(new long[]{-2,0,1,11,15,21,30,41}));
-    }
-  public void testRemove()
-    {
-    RangeSet b = new RangeSet(new long[]{0,11,20,31});
-    b.remove(5,25);
-    assertEquals(b,new RangeSet(new long[]{0,5,25,31}));
-    b.remove(31,32);
-    assertEquals(b,new RangeSet(new long[]{0,5,25,31}));
-    b.remove(35,38);
-    assertEquals(b,new RangeSet(new long[]{0,5,25,31}));
-    b.remove(-90,-80);
-    assertEquals(b,new RangeSet(new long[]{0,5,25,31}));
-    b.remove(27,29);
-    assertEquals(b,new RangeSet(new long[]{0,5,25,27,29,31}));
-    b.remove(25,26);
-    assertEquals(b,new RangeSet(new long[]{0,5,26,27,29,31}));
-    b.remove(4,6);
-    assertEquals(b,new RangeSet(new long[]{0,4,26,27,29,31}));
-    b.remove(-20,40);
-    assertEquals(b,new RangeSet(new long[]{}));
-    b.remove(-20,40);
-    assertEquals(b,new RangeSet(new long[]{}));
-    }
-  public void testIntersect2()
-    {
-    RangeSet b = new RangeSet(new long[]{0,11,20,31});
-    b.intersect(2,29);
-    assertEquals(b,new RangeSet(new long[]{2,11,20,29}));
-    b.intersect(-8,50);
-    assertEquals(b,new RangeSet(new long[]{2,11,20,29}));
-    b.intersect(2,50);
-    assertEquals(b,new RangeSet(new long[]{2,11,20,29}));
-    b.intersect(2,29);
-    assertEquals(b,new RangeSet(new long[]{2,11,20,29}));
-    b.intersect(-18,29);
-    assertEquals(b,new RangeSet(new long[]{2,11,20,29}));
-    b.intersect(3,11);
-    assertEquals(b,new RangeSet(new long[]{3,11}));
-    b = new RangeSet(new long[]{0,11,20,31});
-    b.intersect(3,15);
-    assertEquals(b,new RangeSet(new long[]{3,11}));
-    b = new RangeSet(new long[]{0,11,20,31});
-    b.intersect(17,30);
-    assertEquals(b,new RangeSet(new long[]{20,30}));
-    b = new RangeSet(new long[]{0,11,20,31});
-    b.intersect(11,20);
-    assertEquals(b,new RangeSet(new long[]{}));
-    b = new RangeSet(new long[]{0,11,20,31});
-    b.intersect(-8,-7);
-    assertEquals(b,new RangeSet(new long[]{}));
-    b = new RangeSet(new long[]{0,11,20,31});
-    b.intersect(31,35);
-    assertEquals(b,new RangeSet(new long[]{}));
-    }
-  public void testUnion()
-    {
-    assertEquals(new RangeSet(new long[]{1,11,20,31,40,56}),
-                 new RangeSet(new long[]{20,31,40,51}).union
-                 (new RangeSet(new long[]{1,11,45,56})));
-    assertEquals(new RangeSet(new long[]{1,11,45,56}),
-                 new RangeSet(new long[]{}).union
-                 (new RangeSet(new long[]{1,11,45,56})));
-    assertEquals(new RangeSet(new long[]{1,11,45,56}),
-                 new RangeSet(new long[]{1,11,45,56}).union
-                 (new RangeSet(new long[]{})));
-    }
-
-  public void testIntersect()
-    {
-    assertEquals(new RangeSet(new long[]{22,24,45,51}),
-                 new RangeSet(new long[]{20,31,40,51}).intersection
-                 (new RangeSet(new long[]{1,11,22,24,45,56})));
-    assertEquals(new RangeSet(new long[]{20,31,40,51,90,101,110,121,200,201}),
-                 new RangeSet(new long[]{10,101,110,121,200,221}).intersection
-                 (new RangeSet(new long[]{20,31,40,51,90,201})));
-    assertEquals(new RangeSet(new long[]{}),
-                 new RangeSet(new long[]{20,31,40,51}).intersection
-                 (new RangeSet(new long[]{})));
-    assertEquals(new RangeSet(new long[]{}),
-                 new RangeSet(new long[]{}).intersection
-                 (new RangeSet(new long[]{20,31,40,51})));
-    }
-  public void testDifference()
-    {
-    assertEquals(new RangeSet(new long[]{20,31,40,45}),
-                 new RangeSet(new long[]{20,31,40,51}).difference
-                 (new RangeSet(new long[]{1,11,45,56})));
-    assertEquals(new RangeSet(new long[]{}),
-                 new RangeSet(new long[]{}).difference
-                 (new RangeSet(new long[]{1,11,45,56})));
-    assertEquals(new RangeSet(new long[]{1,11,45,56}),
-                 new RangeSet(new long[]{1,11,45,56}).difference
-                 (new RangeSet(new long[]{})));
-    }
-
-  public void testContainsRS()
-    {
-    RangeSet b = new RangeSet(new long[]{20,31,40,51});
-
-    assertFalse(b.contains(0,11));
-    assertFalse(b.contains(10,21));
-    assertFalse(b.contains(19,20));
-    assertTrue(b.contains(20,21));
-    assertTrue(b.contains(21,22));
-    assertTrue(b.contains(20,31));
-    assertFalse(b.contains(25,36));
-    assertTrue(b.contains(30,31));
-    assertFalse(b.contains(31,32));
-    assertFalse(b.contains(35,38));
-    assertFalse(b.contains(35,46));
-    assertTrue(b.contains(40,41));
-    assertFalse(b.contains(45,56));
-    assertFalse(b.contains(60,71));
-    }
-  public void testContainsRS2()
-    {
-    RangeSet b = new RangeSet(new long[]{20,31,40,51});
-
-    assertTrue(b.contains(new RangeSet(new long[]{20,31,40,51})));
-    assertTrue(b.contains(new RangeSet(new long[]{20,21})));
-    assertTrue(b.contains(new RangeSet(new long[]{50,51})));
-    assertFalse(b.contains(new RangeSet(new long[]{19,31,40,51})));
-    assertFalse(b.contains(new RangeSet(new long[]{20,31,40,52})));
-    assertFalse(b.contains(new RangeSet(new long[]{20,51})));
-    assertFalse(b.contains(new RangeSet(new long[]{0,1})));
-    assertFalse(b.contains(new RangeSet(new long[]{0,20,31,40,51,100})));
-    }
-  public void testOverlaps()
-    {
-    RangeSet b = new RangeSet(new long[]{20,31,40,51});
-
-    assertFalse(b.overlaps(0,11));
-    assertTrue(b.overlaps(10,21));
-    assertFalse(b.overlaps(19,20));
-    assertTrue(b.overlaps(20,21));
-    assertTrue(b.overlaps(21,22));
-    assertTrue(b.overlaps(20,31));
-    assertTrue(b.overlaps(25,36));
-    assertTrue(b.overlaps(30,37));
-    assertFalse(b.overlaps(31,32));
-    assertFalse(b.overlaps(35,38));
-    assertTrue(b.overlaps(35,46));
-    assertTrue(b.overlaps(40,41));
-    assertTrue(b.overlaps(45,56));
-    assertFalse(b.overlaps(60,71));
-    }
-  public void testOverlaps2()
-    {
-    RangeSet b = new RangeSet(new long[]{20,31,40,51});
-
-    assertTrue(b.overlaps(new RangeSet(new long[]{20,31,40,51})));
-    assertTrue(b.overlaps(new RangeSet(new long[]{20,21})));
-    assertTrue(b.overlaps(new RangeSet(new long[]{50,51})));
-    assertTrue(b.overlaps(new RangeSet(new long[]{19,31,40,51})));
-    assertTrue(b.overlaps(new RangeSet(new long[]{20,31,40,52})));
-    assertTrue(b.overlaps(new RangeSet(new long[]{20,51})));
-    assertFalse(b.overlaps(new RangeSet(new long[]{0,1})));
-    assertFalse(b.overlaps(new RangeSet(new long[]{0,20,31,40,51,100})));
-    }
-
-  public void testIterator()
-    {
-    RangeSet b = new RangeSet(new long[]{20,31,40,51});
-    RangeSet.ValueIterator it =b.valueIterator();
-    for (int i=0; i<b.nranges(); ++i)
-      for (long j=b.ivbegin(i); j<b.ivend(i); ++j)
-        {
-        assertTrue(it.hasNext());
-        assertEquals("value mismatch", j, it.next());
-        }
-    assertFalse(it.hasNext());
-    }
-
-  public void testCompress() throws Exception
-    {
-    RangeSet r = new RangeSet(new long[]{10,20,30,40,50,51});
-    assertEquals(r,RangeSet.fromCompressed(r.toCompressed()));
-    }
-
-  private static void rsOps(RangeSet a, RangeSet b) throws Exception
-    {
-    assertFalse(b.overlaps(a.difference(b)));
-    assertTrue(a.union(b).nval()>=a.nval());
-    assertTrue(a.union(b).nval()>=b.nval());
-    assertTrue(a.intersection(b).nval()<=a.nval());
-    assertTrue(a.intersection(b).nval()<=b.nval());
-    assertTrue(a.union(b).contains(a));
-    assertTrue(a.union(b).contains(b));
-    assertFalse(a.difference(b).overlaps(b));
-    assertFalse(b.difference(a).overlaps(a));
-    assertEquals(a.union(b).nval(),a.nval()+b.nval()-a.intersection(b).nval());
-    assertEquals(a.union(b).difference(a.intersection(b)).nval(),
-                 a.union(b).nval()-a.intersection(b).nval());
-    assertEquals(a,RangeSet.fromCompressed(a.toCompressed()));
-    }
-
-  public static void testOps() throws Exception
-    {
-    int niter = 100;
-    Random rng = new Random(42);
-    for (int iter=0; iter<niter; ++iter)
-      {
-      RangeSet a = randomRangeSet(rng, 1000, 0, 100);
-      RangeSet b = randomRangeSet(rng, 1000, 0, 100);
-      RangeSet c = randomRangeSet(rng, 10, 10000, 100);
-      rsOps(a,b);
-      rsOps(a,c);
-      rsOps(c,a);
-      }
-    }
-  }
diff -Nru healpix-java-3.40/src/healpix/essentials/Vec3.java healpix-java-3.50/src/healpix/essentials/Vec3.java
--- healpix-java-3.40/src/healpix/essentials/Vec3.java	2015-04-01 08:52:19.000000000 -0400
+++ healpix-java-3.50/src/healpix/essentials/Vec3.java	1969-12-31 19:00:00.000000000 -0500
@@ -1,175 +0,0 @@
-/*
- *  This file is part of Healpix Java.
- *
- *  This code 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 code 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 code; 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.sourceforge.net
- */
-
-package healpix.essentials;
-
-/** Cartesian 3-vector.
-    Instead of using the javax.vecmath.Vector3d class, this separate class was
-    implemented for two reasons: first, to avoid the external dependency from
-    vecmath.jar, and also because the function Vector3d.angle(Vector3d v1) is
-    too inaccurate for usage in Healpix for very small angles.
-
-    @copyright (C) 2011-2015 Max-Planck-Society
-    @author Martin Reinecke */
-public class Vec3
-  {
-  public double x, y, z;
-
-  /** Default constructor. */
-  public Vec3() {}
-
-  public Vec3 (Vec3 v)
-    { x=v.x; y=v.y; z=v.z; }
-  /** Creation from individual components */
-  public Vec3 (double x1, double y1, double z1)
-    { x=x1; y=y1; z=z1; }
-  /** Conversion from {@link Pointing} */
-  public Vec3 (Pointing ptg)
-    {
-    double sth = FastMath.sin(ptg.theta);
-    x=sth*FastMath.cos(ptg.phi);
-    y=sth*FastMath.sin(ptg.phi);
-    z=FastMath.cos(ptg.theta);
-    }
-  /** Conversion from {@link Zphi} */
-  public Vec3 (Zphi zphi)
-    {
-    double sth = Math.sqrt((1.0-zphi.z)*(1.0+zphi.z));
-    x=sth*FastMath.cos(zphi.phi);
-    y=sth*FastMath.sin(zphi.phi);
-    z=zphi.z;
-    }
-
-  public Vec3 (double[] arr)
-    {
-    if(arr.length!=3) throw new IllegalArgumentException("Wrong array size");
-    x = arr[0]; y = arr[1]; z = arr[2];
-    }
-
-  /** Vector length
-      @return the length of the vector. */
-  public final double length()
-    { return Math.sqrt(lengthSquared()); }
-
-  /** Squared vector length
-      @return the squared length of the vector. */
-  public final double lengthSquared()
-    { return x*x + y*y + z*z; }
-
-  /** Normalize the vector */
-  public void normalize()
-    {
-    double d = 1./length();
-    x *= d; y *= d; z *= d;
-    }
-  /** Return normalized vector */
-  public Vec3 norm()
-    {
-    double d = 1./length();
-    return new Vec3(x*d,y*d,z*d);
-    }
-
-  /** Angle between two vectors.
-      @param v1 another vector
-      @return the angle in radians between this vector and {@code v1};
-        constrained to the range [0,PI]. */
-  public final double angle(Vec3 v1)
-    { return FastMath.atan2(cross(v1).length(), dot(v1)); }
-
-  /** Vector cross product.
-      @param v another vector
-      @return the vector cross product between this vector and {@code v} */
-  public Vec3 cross(Vec3 v)
-    { return new Vec3(y*v.z - v.y*z, z*v.x - v.z*x, x*v.y - v.x*y); }
-
-  /** Vector scaling.
-    * @param n the scale number to be multiply to the coordinates {@code x,y,z}
-    * @return the vector with coordinates multiplied by {@code n}
-    */
-  public Vec3 mul(double n)
-    { return new Vec3(n*x, n*y, n*z); }
-
-  /** Invert the signs of all components */
-  public void flip()
-    { x=-x; y=-y; z=-z; }
-  public Vec3 flipped()
-    { return new Vec3(-x,-y,-z); }
-
-  /** Scale the vector by a given factor
-      @param n the scale factor */
-  public void scale(double n)
-    { x*=n; y*=n; z*=n; }
-
-  /** Computes the dot product of the this vector and {@code v1}.
-    * @param v1 another vector
-    * @return dot product */
-  public final double dot(Vec3 v1)
-    { return x*v1.x + y*v1.y + z*v1.z; }
-
-  /** Vector addition
-    * @param v the vector to be added
-    * @return addition result */
-  public Vec3 add(Vec3 v)
-    { return new Vec3(x+v.x, y+v.y, z+v.z); }
-
-  /** Vector subtraction
-    * @param v the vector to be subtracted
-    * @return subtraction result */
-  public Vec3 sub(Vec3 v)
-    { return new Vec3(x-v.x, y-v.y, z-v.z); }
-
-  public String toString()
-    {
-    StringBuilder s = new StringBuilder();
-    s.append("vec3(");s.append(x);
-    s.append(",");s.append(y);
-    s.append(",");s.append(z);
-    s.append(")");
-    return s.toString();
-    }
-
-  public double[] toArray()
-    { return new double[]{x,y,z}; }
-
-  public void toArray(double[] arr)
-    {
-    if(arr.length!=3) throw new IllegalArgumentException("wrong array size");
-    arr[0] = x; arr[1] = y; arr[2] = z;
-    }
-
-  public boolean equals(Object o)
-    {
-    if (this == o) return true;
-    if (o == null || getClass() != o.getClass()) return false;
-    Vec3 vec3 = (Vec3) o;
-    if (Double.compare(vec3.x, x) != 0) return false;
-    if (Double.compare(vec3.y, y) != 0) return false;
-    if (Double.compare(vec3.z, z) != 0) return false;
-    return true;
-    }
-
-  public int hashCode()
-    {
-    int result = Double.valueOf(x).hashCode();
-    result = 31 * result + Double.valueOf(y).hashCode();
-    result = 31 * result + Double.valueOf(z).hashCode();
-    return result;
-    }
-  }
diff -Nru healpix-java-3.40/src/healpix/essentials/Zphi.java healpix-java-3.50/src/healpix/essentials/Zphi.java
--- healpix-java-3.40/src/healpix/essentials/Zphi.java	2013-04-03 09:15:40.000000000 -0400
+++ healpix-java-3.50/src/healpix/essentials/Zphi.java	1969-12-31 19:00:00.000000000 -0500
@@ -1,77 +0,0 @@
-/*
- *  This file is part of Healpix Java.
- *
- *  This code 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 code 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 code; 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.sourceforge.net
- */
-
-package healpix.essentials;
-
-/** Class for storing a position on the unit sphere as a (z,phi)-tuple.
-
-    @copyright (C) 2011 Max-Planck-Society
-    @author Martin Reinecke */
-public final  class Zphi
-  {
-  /** Cosine of the colatitude, or z component of unit vector; Range [-1;1]. */
-  public double z;
-
-  /** Longitude in radians; Range [0; 2Pi]. */
-  public double phi;
-
-  /** Default constructor */
-  public Zphi() {}
-
-  /** Creation from individual components */
-  public Zphi (double z_, double phi_)
-    { z=z_; phi=phi_; }
-
-  /** Conversion from {@link Vec3} */
-  public Zphi (Vec3 v)
-    { z = v.z/v.length(); phi = FastMath.atan2(v.y,v.x); }
-
-  /** Conversion from {@link Pointing} */
-  public Zphi (Pointing ptg)
-    { z = FastMath.cos(ptg.theta); phi=ptg.phi; }
-
-  public String toString()
-    {
-    StringBuilder s = new StringBuilder();
-    s.append("zphi(");s.append(z);
-    s.append(",");s.append(phi);
-    s.append(")");
-    return s.toString();
-    }
-
-  public boolean equals(Object o)
-    {
-    if (this == o) return true;
-    if (o == null || getClass() != o.getClass()) return false;
-    Zphi zphi = (Zphi) o;
-    if (Double.compare(zphi.phi, phi) != 0) return false;
-    if (Double.compare(zphi.z, z) != 0) return false;
-    return true;
-    }
-
-  public int hashCode()
-    {
-    long temp = z != +0.0d ? Double.doubleToLongBits(z) : 0L;
-    int result = (int) (temp ^ (temp >>> 32));
-    temp = phi != +0.0d ? Double.doubleToLongBits(phi) : 0L;
-    result = 31 * result + (int) (temp ^ (temp >>> 32));
-    return result;
-    }
-  }
diff -Nru healpix-java-3.40/src/java/CHANGES healpix-java-3.50/src/java/CHANGES
--- healpix-java-3.40/src/java/CHANGES	1969-12-31 19:00:00.000000000 -0500
+++ healpix-java-3.50/src/java/CHANGES	2015-07-06 13:56:00.000000000 -0400
@@ -0,0 +1,48 @@
+New features and improvements introduced with the healpix.essentials package,
+compared to the HealpixIndex, Healpix and PixTools classes:
+
+- close similarities with Healpix_Base_T class from Healpix C++, which allows
+  simultaneous development and bug fixes for both.
+- support for arbitrary positive Nside values in RING scheme; no longer limited
+  to powers of 2
+- maximum supported Nside value: 2^29
+- significant performance improvements: most methods have been accelerated
+  by integral factors, some by more than an order of magnitude.
+- trigonometric functions are computed using an adapted version of Naoki
+  Shibata's SLEEF library (http://freecode.com/projects/sleef), which is
+  considerably faster than Java's own implementation.
+- re-implementation of queryDisc and queryPolygon:
+  * query methods return RangeSet objects which allow much more compact storage
+    of the result
+  * new native query methods for NESTED ordering; these are slower than those
+    for RING ordering, but much quicker than converting all pixels from a RING
+    result to NESTED.
+  * inclusive queries have been improved: several bugs were fixed, and the
+    number of false positives in the result has been reduced. Users can now
+    choose between quick inclusive queries returning more false positives,
+    and slower ones returning fewer false positives.
+- the HealpixProc class offers a procedural (instead of object-oriented)
+  interface to the HealpixBase functionality, which simplifies transition
+  for users of the "Healpix" and "PixTools" classes.
+  NOTE: this only works for Nside parameters which are powers of 2
+- many bug fixes
+- no external library dependencies, except for "nom.tam.fits" if FITS I/O is
+  required
+- the code base is thread-safe in the following sense:
+  * HealpixProc methods can be called concurrently
+  * HealpixBase methods can be called concurrently on different objects
+
+
+Changes after version 3.11:
+===========================
+
+RangeSet.size() -> RangeSet.nranges()
+RangeSet(int) constructor has new semantics; see documentation!
+
+Changes after version 3.20:
+===========================
+
+- deprecated parts of the library have been removed
+- MOC support (see http://ivoa.net/documents/MOC/ for high-level description)
+- queries for arbitrary polygons (using MOC)
+- new targets in build.xml which allow compilation without external JARs
diff -Nru healpix-java-3.40/src/java/COPYING healpix-java-3.50/src/java/COPYING
--- healpix-java-3.40/src/java/COPYING	1969-12-31 19:00:00.000000000 -0500
+++ healpix-java-3.50/src/java/COPYING	2012-05-25 05:37:08.000000000 -0400
@@ -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.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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.
+
+  <signature of Ty Coon>, 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.
Binary files /tmp/OBEHuXQOIZ/healpix-java-3.40/src/java/lib/junit-4.11.jar and /tmp/YjM3tADTtc/healpix-java-3.50/src/java/lib/junit-4.11.jar differ
Binary files /tmp/OBEHuXQOIZ/healpix-java-3.40/src/java/lib/nom-tam-fits-1.14.2.jar and /tmp/YjM3tADTtc/healpix-java-3.50/src/java/lib/nom-tam-fits-1.14.2.jar differ
diff -Nru healpix-java-3.40/src/java/README healpix-java-3.50/src/java/README
--- healpix-java-3.40/src/java/README	1969-12-31 19:00:00.000000000 -0500
+++ healpix-java-3.50/src/java/README	2015-03-30 16:18:36.000000000 -0400
@@ -0,0 +1,46 @@
+Installation of Healpix Java
+----------------------------
+requires a Java Development Kit and Apache Ant
+(see below Notes on installing Java, and on junit)
+% ant 
+
+for information on the build targets available:
+% ant -p
+
+Documentation
+-------------
+preinstalled in <HEALPIX>/doc/html/java/index.html
+
+% ant docs
+will generate
+<HEALPIX>/src/java/doc/index.html
+from the source files
+
+-----------------------------------------------------------------
+
+
+Installing Java
+===============
+
+Java Development Kit (JDK aka SDK): required to compile any Java code
+---------------------------------
+http://www.oracle.com/technetwork/java/index.html
+
+Java based build tool: Ant
+--------------------------
+http://ant.apache.org/bindownload.cgi
+It is also available thru fink for MacOS
+
+
+About Junit
+===========
+junit.jar is required for Java Healpix library installation.
+It is shipped with Healpix and available in 
+<HEALPIX>/src/java/lib/
+Just make sure that this path (or a path to any other junit.jar)
+is included in your CLASSPATH environment variable.
+Alternatively you can use ant's "-lib" option:
+  ant -lib lib/junit*.jar test
+
+Please contact healpix-support AT lists.sourceforge.net for any questions on the
+code or its installation.
diff -Nru healpix-java-3.40/src/java/src/healpix/essentials/CircleFinder.java healpix-java-3.50/src/java/src/healpix/essentials/CircleFinder.java
--- healpix-java-3.40/src/java/src/healpix/essentials/CircleFinder.java	1969-12-31 19:00:00.000000000 -0500
+++ healpix-java-3.50/src/java/src/healpix/essentials/CircleFinder.java	2015-08-05 05:00:40.000000000 -0400
@@ -0,0 +1,71 @@
+/*
+ *  This file is part of Healpix Java.
+ *
+ *  This code 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 code 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 code; 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.sourceforge.net
+ */
+
+package healpix.essentials;
+
+/** Finds the smallest enclosing cone for a point set on the sphere according to
+    Barequet & Elber: Information Processing Letters 93(2005), p.83.
+    All points are expected to be passed as unit vectors.
+    The enclosing cone must have an opening angle smaller than pi/2.
+
+    @copyright 2011 Max-Planck-Society
+    @author Martin Reinecke */
+final class CircleFinder
+  {
+  private Vec3 center;
+  private double cosrad;
+
+  private void getCircle (Vec3[] point, int q1, int q2)
+    {
+    center = point[q1].add(point[q2]); center.normalize();
+    cosrad = point[q1].dot(center);
+    for (int i=0; i<q1; ++i)
+      if (point[i].dot(center)<cosrad) // point outside the current circle
+        {
+        center=(point[q1].sub(point[i])).cross(point[q2].sub(point[i]));
+        center.normalize();
+        cosrad=point[i].dot(center);
+        if (cosrad<0)
+          { center.flip(); cosrad=-cosrad; }
+        }
+    }
+  private void getCircle (Vec3[] point, int q)
+    {
+    center = point[0].add(point[q]); center.normalize();
+    cosrad = point[0].dot(center);
+    for (int i=1; i<q; ++i)
+      if (point[i].dot(center)<cosrad) // point outside the current circle
+        getCircle(point,i,q);
+    }
+
+  public CircleFinder (Vec3[] point) throws Exception
+    {
+    int np=point.length;
+    HealpixUtils.check(np>=2,"too few points");
+    center = point[0].add(point[1]); center.normalize();
+    cosrad = point[0].dot(center);
+    for (int i=2; i<np; ++i)
+      if (point[i].dot(center)<cosrad) // point outside the current circle
+        getCircle(point,i);
+    }
+
+  public Vec3 getCenter() { return new Vec3(center); }
+  public double getCosrad() { return cosrad; }
+  }
diff -Nru healpix-java-3.40/src/java/src/healpix/essentials/Compressor.java healpix-java-3.50/src/java/src/healpix/essentials/Compressor.java
--- healpix-java-3.40/src/java/src/healpix/essentials/Compressor.java	1969-12-31 19:00:00.000000000 -0500
+++ healpix-java-3.50/src/java/src/healpix/essentials/Compressor.java	2015-03-30 16:19:17.000000000 -0400
@@ -0,0 +1,209 @@
+/*
+ *  This file is part of Healpix Java.
+ *
+ *  This code 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 code 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 code; 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.sourceforge.net
+ */
+
+package healpix.essentials;
+import java.io.ByteArrayOutputStream;
+
+/** Class for compressing/uncompressing monotonous integer sequences.
+    Implementation inspired by Moffat and Stuiver 2000: "Binary Interpolative
+    Coding for Effective Index Compression", Information Retrieval 3, 25
+
+    @copyright 2014 Max-Planck-Society
+    @author Martin Reinecke */
+public class Compressor
+  {
+//FIXME: move into separate class
+  private static final class obitstream
+    {
+    private long bitpos;
+    private int curval;
+    private ByteArrayOutputStream strm;
+
+    public obitstream()
+      {
+      bitpos=0;
+      curval=0;
+      strm=new ByteArrayOutputStream();
+      }
+    private void put_internal (long val, int bits)
+      {
+      int bitsleft = 8-(int)(bitpos&7);
+      if (bits<=bitsleft) // wbits==bits
+        {
+        curval |= ((val&((1L<<bits)-1))<<(bitsleft-bits));
+        bitpos+=bits;
+        if ((bitpos&7)==0) { strm.write(curval); curval=0; }
+        }
+      else // wbits==bitsleft
+        {
+        curval |= ((val>>>(bits-bitsleft))&((1<<bitsleft)-1));
+        bitpos+=bitsleft;
+        if ((bitpos&7)==0) { strm.write(curval); curval=0; }
+        put_internal(val,bits-bitsleft);
+        }
+      }
+
+    public void put (long val, int bits) throws Exception
+      {
+      if (bits==0) return;
+      HealpixUtils.check(bits<=63,"too many bits");
+      HealpixUtils.check(val-(val&((1L<<bits)-1))==0,
+        "value has too many bits");
+      put_internal(val,bits);
+      }
+
+    public byte[] getData() throws Exception
+      {
+      if ((bitpos&7)!=0) strm.write(curval);
+      return strm.toByteArray();
+      }
+    }
+
+//FIXME: move into separate class
+  private static final class ibitstream
+    {
+    private long bitpos;
+    private int curval;
+    private byte[] data;
+
+    public ibitstream(byte[] data_in) throws Exception
+      {
+      HealpixUtils.check(data_in.length>0,"empty input array");
+      bitpos=0;
+      data=data_in.clone();
+      }
+    private long get_internal (long val, int bits)
+      {
+      int bitsleft = 8-(int)(bitpos&7);
+      if (bitsleft==8)
+        {curval=data[(int)(bitpos>>>3)]; if (curval<0) curval+=256;}
+      if (bits<=bitsleft)
+        {
+        val |= ((curval>>>(bitsleft-bits))&((1L<<bits)-1));
+        bitpos+=bits;
+        }
+      else
+        {
+        val |= (curval&((1L<<bitsleft)-1))<<(bits-bitsleft);
+        bitpos+=bitsleft;
+        val=get_internal(val,bits-bitsleft);
+        }
+      return val;
+      }
+    public long get (int bits) throws Exception
+      {
+      if (bits==0) return 0L;
+      HealpixUtils.check(bits<=63,"too many bits");
+      HealpixUtils.check((bitpos+bits)<=8*(long)data.length,
+        "reading past end of stream");
+      long res=0L;
+      return get_internal(res,bits);
+      }
+    }
+
+  private static void interpol_encode2 (long[] data, int l, int r,
+    obitstream obs, int shift) throws Exception
+    {
+    if (r-l<=1) return;
+    int m=l+(r-l)/2;
+
+    long nval = ((data[r]-data[l])>>>shift) - (r-l) + 1;
+    if (nval<=1) return;
+
+    int nb = 1+HealpixUtils.ilog2(nval-1);
+    long val = (data[m]>>>shift)-((data[l]>>>shift)+(m-l));
+    long nshort=(1L<<nb)-nval;
+    if (val<nshort)
+      obs.put(val,nb-1);
+    else
+      obs.put(val+nshort,nb);
+    interpol_encode2(data,l,m,obs,shift);
+    interpol_encode2(data,m,r,obs,shift);
+    }
+
+  /** Return a byte array representing the compressed sequence
+      [data[begin]; data[end-1]] */
+  public static byte[] interpol_encode (long[] data, int begin, int end)
+    throws Exception
+    {
+    obitstream obs=new obitstream();
+    if (begin>=end) // empty range
+      { obs.put(0,8); return obs.getData(); }
+    HealpixUtils.check(data[begin]>=0,"numbers must be nonnegative");
+    long combo=data[begin];
+    for (int i=begin+1; i<end; ++i)
+      {
+      HealpixUtils.check(data[i-1]<data[i],"numbers not strictly increasing");
+      combo|=data[i];
+      }
+    //determine allowable right shift
+    int shift = Long.numberOfTrailingZeros(combo);
+
+    long maxnum=data[end-1]>>>shift;
+    if (end-begin>maxnum) maxnum = end-begin;
+    int maxbits=1+HealpixUtils.ilog2(maxnum);
+    obs.put(maxbits,8);
+    obs.put(shift,8);
+    obs.put(end-begin,maxbits);
+    obs.put(data[begin]>>>shift,maxbits);
+    if (end-begin==1) return obs.getData(); // a single data entry
+    obs.put(data[end-1]>>>shift,maxbits);
+    interpol_encode2(data,begin,end-1,obs,shift);
+    return obs.getData();
+    }
+
+  private static void interpol_decode2 (long[] data, int l, int r,
+    ibitstream ibs, int shift) throws Exception
+    {
+    if (r-l<=1) return;
+    int m=l+(r-l)/2;
+
+    long nval = ((data[r]-data[l])>>>shift) - (r-l) + 1;
+    long val=0;
+
+    if (nval>1)
+      {
+      int nb = 1+HealpixUtils.ilog2(nval-1);
+      long nshort=(1L<<nb)-nval;
+      val=ibs.get(nb-1);
+      if (val>=nshort)
+        val=(val<<1)+ ibs.get(1) - nshort;
+      }
+    data[m]=data[l]+(((m-l)+val)<<shift);
+
+    interpol_decode2(data,l,m,ibs,shift);
+    interpol_decode2(data,m,r,ibs,shift);
+    }
+
+  /** Return an array containing the number sequence decompressed from data. */
+  public static long[] interpol_decode (byte[] data) throws Exception
+    {
+    ibitstream ibs=new ibitstream(data);
+    int maxbits=(int)ibs.get(8);
+    if (maxbits==0) return new long[0];
+    int shift=(int)ibs.get(8);
+    long[] v=new long[(int)ibs.get(maxbits)];
+    v[0]=ibs.get(maxbits)<<shift;
+    if (v.length==1) return v;
+    v[v.length-1]=ibs.get(maxbits)<<shift;
+    interpol_decode2(v,0,v.length-1,ibs,shift);
+    return v;
+    }
+  }
diff -Nru healpix-java-3.40/src/java/src/healpix/essentials/Constants.java healpix-java-3.50/src/java/src/healpix/essentials/Constants.java
--- healpix-java-3.40/src/java/src/healpix/essentials/Constants.java	1969-12-31 19:00:00.000000000 -0500
+++ healpix-java-3.50/src/java/src/healpix/essentials/Constants.java	2013-04-03 09:15:40.000000000 -0400
@@ -0,0 +1,37 @@
+/*
+ *  This file is part of Healpix Java.
+ *
+ *  This code 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 code 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 code; 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.sourceforge.net
+ */
+
+package healpix.essentials;
+
+/** Some frequently used constants. */
+public class Constants
+  {
+  /** The Constant halfpi */
+  public static final double halfpi = Math.PI/2.;
+
+  public static final double inv_halfpi = 2./Math.PI;
+
+  /** The Constant twopi. */
+  public static final double twopi = 2*Math.PI;
+  public static final double inv_twopi = 1./(2*Math.PI);
+
+  /** The Constant twothird. */
+  public static final double twothird = 2./3.;
+  }
diff -Nru healpix-java-3.40/src/java/src/healpix/essentials/FastMath.java healpix-java-3.50/src/java/src/healpix/essentials/FastMath.java
--- healpix-java-3.40/src/java/src/healpix/essentials/FastMath.java	1969-12-31 19:00:00.000000000 -0500
+++ healpix-java-3.50/src/java/src/healpix/essentials/FastMath.java	2012-05-21 09:06:23.000000000 -0400
@@ -0,0 +1,168 @@
+package healpix.essentials;
+
+/* Subset of the SLEEF Java library by Naoki Shibata. The code in this file is
+   released to the Public Domain. */
+
+/**
+ * FastMath class is a Java implementation of the
+ * <a href="http://freecode.com/projects/sleef">SLEEF</a>
+ * library. Some of the methods can be used as substitutions of the
+ * corresponding methods in Math class. They have slightly less
+ * accuracy, and some methods are faster compared to those methods in
+ * Math class. Please note that the methods in the standard Math class
+ * are JNI methods, and the SLEEF library is specialized for SIMD
+ * operations.
+ */
+public final class FastMath {
+  private static final double mulsign(double x, double y)
+    { return Math.copySign(1, y) * x; }
+
+  /** Checks if the argument is a NaN or not. */
+  private static final boolean isnan(double d)
+    { return d != d; }
+
+  /** Checks if the argument is either positive or negative infinity. */
+  private static final boolean isinf(double d)
+    { return Math.abs(d) == Double.POSITIVE_INFINITY; }
+
+  private static final double sign(double d) { return Math.copySign(1, d); }
+
+  private static final double atanhelper(double s)
+    {
+    double t = s * s;
+    double u = -1.88796008463073496563746e-05;
+    u = u * t + (0.000209850076645816976906797);
+    u = u * t + (-0.00110611831486672482563471);
+    u = u * t + (0.00370026744188713119232403);
+    u = u * t + (-0.00889896195887655491740809);
+    u = u * t + (0.016599329773529201970117);
+    u = u * t + (-0.0254517624932312641616861);
+    u = u * t + (0.0337852580001353069993897);
+    u = u * t + (-0.0407629191276836500001934);
+    u = u * t + (0.0466667150077840625632675);
+    u = u * t + (-0.0523674852303482457616113);
+    u = u * t + (0.0587666392926673580854313);
+    u = u * t + (-0.0666573579361080525984562);
+    u = u * t + (0.0769219538311769618355029);
+    u = u * t + (-0.090908995008245008229153);
+    u = u * t + (0.111111105648261418443745);
+    u = u * t + (-0.14285714266771329383765);
+    u = u * t + (0.199999999996591265594148);
+    u = u * t + (-0.333333333333311110369124);
+
+    return u * t * s + s;
+    }
+
+  private static final double atan2k(double y, double x)
+    {
+    double q = 0.;
+
+    if (x < 0) { x = -x; q = -2.; }
+    if (y > x) { double t = x; x = y; y = -t; q += 1.; }
+
+    return atanhelper(y/x) + q*(Math.PI/2);
+    }
+
+  /** This method calculates the arc tangent of y/x in radians, using
+      the signs of the two arguments to determine the quadrant of the
+      result. The results may have maximum error of 2 ulps. */
+  public static final double atan2(double y, double x)
+    {
+    double r = atan2k(Math.abs(y), x);
+
+    r = mulsign(r, x);
+    if (isinf(x) || x == 0)
+      r = Math.PI/2 - (isinf(x) ? (sign(x) * (Math.PI  /2)) : 0);
+    if (isinf(y)          )
+      r = Math.PI/2 - (isinf(x) ? (sign(x) * (Math.PI*1/4)) : 0);
+    if (            y == 0)
+      r = (sign(x) == -1 ? Math.PI : 0);
+    return isnan(x) || isnan(y) ? Double.NaN : mulsign(r, y);
+    }
+
+  /** This method calculates the arc sine of x in radians. The return
+      value is in the range [-pi/2, pi/2]. The results may have
+      maximum error of 3 ulps. */
+  public static double asin(double d)
+    { return mulsign(atan2k(Math.abs(d), Math.sqrt((1+d)*(1-d))), d); }
+
+  /** This method calculates the arc cosine of x in radians. The
+      return value is in the range [0, pi]. The results may have
+      maximum error of 3 ulps. */
+  public static double acos(double d) {
+    return mulsign(atan2k(Math.sqrt((1+d)*(1-d)), Math.abs(d)), d)
+      + (d<0 ? Math.PI : 0);
+  }
+
+  /** Returns the arc tangent of an angle. The results may have
+      maximum error of 2 ulps. */
+  public static final double atan(double s)
+    {
+    int q = 0;
+    if (s < 0) { s = -s; q = 2; }
+    if (s > 1) { s = 1.0 / s; q |= 1; }
+
+    double t=atanhelper(s);
+
+    if ((q & 1) != 0) t = 1.570796326794896557998982 - t;
+    if ((q & 2) != 0) t = -t;
+
+    return t;
+    }
+
+  private static final double PI4_A = .7853981554508209228515625;
+  private static final double PI4_B
+    = .794662735614792836713604629039764404296875e-8;
+  private static final double PI4_C
+    = .306161699786838294306516483068750264552437361480769e-16;
+  private static final double M_1_PI = 0.3183098861837906715377675267450287;
+
+  private final static double sincoshelper(double d)
+    {
+    double s = d * d;
+    double u = -7.97255955009037868891952e-18;
+    u = u*s +2.81009972710863200091251e-15;
+    u = u*s -7.64712219118158833288484e-13;
+    u = u*s +1.60590430605664501629054e-10;
+    u = u*s -2.50521083763502045810755e-08;
+    u = u*s +2.75573192239198747630416e-06;
+    u = u*s -0.000198412698412696162806809;
+    u = u*s +0.00833333333333332974823815;
+    u = u*s -0.166666666666666657414808;
+    return s*u*d + d;
+    }
+
+  /** Returns the trigonometric sine of an angle. The results may
+      have maximum error of 2 ulps. */
+  public static final double sin(double d)
+    {
+    double u = d * M_1_PI;
+    long q = (long)(u < 0 ? u - 0.5 : u + 0.5);
+
+    double x=4.*q;
+    d -= x*PI4_A;
+    d -= x*PI4_B;
+    d -= x*PI4_C;
+
+    if ((q&1) != 0) d = -d;
+
+    return sincoshelper(d);
+    }
+
+  /** Returns the trigonometric cosine of an angle. The results may
+      have maximum error of 2 ulps. */
+  public static final double cos(double d)
+    {
+    double u = d*M_1_PI - 0.5;
+    long q = 1+2*(long)(u < 0 ? u - 0.5 : u + 0.5);
+
+    double x=2.*q;
+    d -= x*PI4_A;
+    d -= x*PI4_B;
+    d -= x*PI4_C;
+
+    if ((q&2) == 0) d = -d;
+
+    return sincoshelper(d);
+    }
+  }
diff -Nru healpix-java-3.40/src/java/src/healpix/essentials/FitsUtil.java healpix-java-3.50/src/java/src/healpix/essentials/FitsUtil.java
--- healpix-java-3.40/src/java/src/healpix/essentials/FitsUtil.java	1969-12-31 19:00:00.000000000 -0500
+++ healpix-java-3.50/src/java/src/healpix/essentials/FitsUtil.java	2016-03-21 18:45:42.000000000 -0400
@@ -0,0 +1,170 @@
+/*
+ *  This file is part of Healpix Java.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+package healpix.essentials;
+
+import java.io.FileOutputStream;
+
+import nom.tam.fits.BasicHDU;
+import nom.tam.fits.BinaryTable;
+import nom.tam.fits.BinaryTableHDU;
+import nom.tam.fits.Fits;
+import nom.tam.fits.FitsFactory;
+import nom.tam.fits.Header;
+import nom.tam.util.BufferedDataOutputStream;
+
+/** Basic FITS I/O support for Healpix maps.
+
+    @copyright 2011 Max-Planck-Society
+    @author Martin Reinecke */
+public class FitsUtil
+  {
+  private static String getKey (Header head, String key) throws Exception
+    {
+    String upkey = key.toUpperCase();
+    if (head.containsKey(upkey))
+      return head.findCard(upkey).getValue().trim();
+    else if (head.containsKey("HIERARCH."+key))
+      return head.findCard("HIERARCH."+key).getValue().trim();
+    else
+      HealpixUtils.check(false,"key not found: "+key);
+    return null;
+    }
+
+  private static Scheme getScheme(Header head) throws Exception
+    {
+    String fscheme=getKey(head,"Ordering");
+    HealpixUtils.check((fscheme.equals("RING")) || (fscheme.equals("NESTED")),
+      "unsupported ordering scheme");
+    return (fscheme.equals("RING")) ? Scheme.RING : Scheme.NESTED;
+    }
+
+  public static HealpixMapFloat getFloatMap(String filename, int hdu, int col)
+    throws Exception
+    {
+    FitsFactory.setUseHierarch(true);
+    FitsFactory.setUseAsciiTables(false);
+    FitsFactory.setLongStringsEnabled(true);
+    BasicHDU<?> bhdu = (new Fits(filename)).getHDU(hdu-1);
+    Header head = bhdu.getHeader();
+
+    Scheme scheme = getScheme(head);
+    int nside = Integer.parseInt(getKey(head,"Nside"));
+
+    Object tmp = ((BinaryTable)bhdu.getData()).getFlattenedColumn(col-1);
+    float[] data=null;
+    if (tmp instanceof float[])
+      data = (float[])tmp;
+    else if (tmp instanceof double[])
+      {
+      double[] tmp2 = (double[])tmp;
+      data = new float[tmp2.length];
+      for (int i=0; i<tmp2.length; ++i)
+        data[i] = (float)tmp2[i];
+      }
+    else
+      HealpixUtils.check(false,"unsupported data format");
+
+    HealpixUtils.check(nside*nside*12==data.length,
+      "inconsistent Nside and column length");
+    return new HealpixMapFloat(data, scheme);
+    }
+  public static HealpixMapDouble getDoubleMap(String filename, int hdu, int col)
+    throws Exception
+    {
+    FitsFactory.setUseHierarch(true);
+    FitsFactory.setUseAsciiTables(false);
+    FitsFactory.setLongStringsEnabled(true);
+    BasicHDU<?> bhdu = (new Fits(filename)).getHDU(hdu-1);
+    Header head = bhdu.getHeader();
+
+    Scheme scheme = getScheme(head);
+    int nside = Integer.parseInt(getKey(head,"Nside"));
+
+    Object tmp = ((BinaryTable)bhdu.getData()).getFlattenedColumn(col-1);
+    double[] data=null;
+    if (tmp instanceof double[])
+      data = (double[])tmp;
+    else if (tmp instanceof float[])
+      {
+      float[] tmp2 = (float[])tmp;
+      data = new double[tmp2.length];
+      for (int i=0; i<tmp2.length; ++i)
+        data[i] = tmp2[i];
+      }
+    else
+      HealpixUtils.check(false,"unsupported data format");
+
+    HealpixUtils.check(nside*nside*12==data.length,
+      "inconsistent Nside and column length");
+    return new HealpixMapDouble(data, scheme);
+    }
+
+  public static void writeFloatMap(HealpixMapFloat map, String filename)
+    throws Exception
+    {
+    FitsFactory.setUseHierarch(true);
+    FitsFactory.setUseAsciiTables(false);
+    Fits f = new Fits();
+    Object[] table = new Object[1];
+    table[0] = map.getData();
+
+    f.addHDU(Fits.makeHDU(table));
+    BinaryTableHDU bhdu = (BinaryTableHDU) f.getHDU(1);
+
+    bhdu.setColumnName(0, "data", "values");
+
+    bhdu.addValue("PIXTYPE", "HEALPIX", "This is a HEALPix map");
+    bhdu.addValue("NSIDE", map.getNside(), "HEALPix NSIDE parameter");
+    bhdu.addValue("ORDERING", map.getScheme().toString().toUpperCase(),
+      "HEALPix ordering scheme");
+
+    FileOutputStream fos = new FileOutputStream(filename);
+    BufferedDataOutputStream s = new BufferedDataOutputStream(fos);
+
+    f.write(s);
+    s.flush();
+    s.close();
+    }
+  public static void writeDoubleMap(HealpixMapDouble map, String filename)
+    throws Exception
+    {
+    FitsFactory.setUseHierarch(true);
+    FitsFactory.setUseAsciiTables(false);
+    Fits f = new Fits();
+    Object[] table = new Object[1];
+    table[0] = map.getData();
+
+    f.addHDU(Fits.makeHDU(table));
+    BinaryTableHDU bhdu = (BinaryTableHDU) f.getHDU(1);
+
+    bhdu.setColumnName(0, "data", "values");
+
+    bhdu.addValue("PIXTYPE", "HEALPIX", "This is a HEALPix map");
+    bhdu.addValue("NSIDE", map.getNside(), "HEALPix NSIDE parameter");
+    bhdu.addValue("ORDERING", map.getScheme().toString().toUpperCase(),
+      "HEALPix ordering scheme");
+
+    FileOutputStream fos = new FileOutputStream(filename);
+    BufferedDataOutputStream s = new BufferedDataOutputStream(fos);
+
+    f.write(s);
+    s.flush();
+    s.close();
+    }
+  }
diff -Nru healpix-java-3.40/src/java/src/healpix/essentials/Fxyf.java healpix-java-3.50/src/java/src/healpix/essentials/Fxyf.java
--- healpix-java-3.40/src/java/src/healpix/essentials/Fxyf.java	1969-12-31 19:00:00.000000000 -0500
+++ healpix-java-3.50/src/java/src/healpix/essentials/Fxyf.java	2013-04-03 09:15:40.000000000 -0400
@@ -0,0 +1,114 @@
+/*
+ *  This file is part of Healpix Java.
+ *
+ *  This code 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 code 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 code; 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.sourceforge.net
+ */
+
+package healpix.essentials;
+
+/** Class describing a location on the sphere
+
+    @copyright 2012 Max-Planck-Society
+    @author Martin Reinecke */
+public final class Fxyf extends HealpixTables
+  {
+  /** x-coordinate within the basis pixel, range [0.0;1.0] */
+  public double fx;
+  /** y-coordinate within the basis pixel, range [0.0;1.0] */
+  public double fy;
+  /** index of the HEALPix basis pixel, range [0;11] */
+  public int face;
+  public Fxyf (double x, double y, int f)
+    { fx=x; fy=y; face=f; }
+
+  protected Fxyf(Hploc loc)
+    {
+    double z=loc.z, phi=loc.phi;
+
+    double za = Math.abs(z);
+    double tt = HealpixUtils.fmodulo((phi*Constants.inv_halfpi),4.0);// in [0,4)
+
+    if (za<=Constants.twothird) // Equatorial region
+      {
+      double temp1 = 0.5+tt;
+      double temp2 = z*0.75;
+      double jp = temp1-temp2; // index of  ascending edge line
+      double jm = temp1+temp2; // index of descending edge line
+      long ifp = (long)jp;  // in {0,4}
+      long ifm = (long)jm;
+      long face_num = (ifp==ifm) ? (ifp|4) : ((ifp<ifm) ? ifp : (ifm+8));
+      fx = HealpixUtils.fmodulo(jm,1.);
+      fy = 1.-HealpixUtils.fmodulo(jp,1.);
+      face = (int)face_num;
+      }
+    else // polar region, za > 2/3
+      {
+      int ntt = Math.min(3,(int)tt);
+      double tp = tt-ntt;
+      double tmp = ((za<0.99)||(!loc.have_sth)) ?
+                    Math.sqrt(3*(1-za)) :
+                    loc.sth/Math.sqrt((1.+za)/3.);
+
+      double jp = tp*tmp; // increasing edge line index
+      double jm = (1.0-tp)*tmp; // decreasing edge line index
+      if (jp>=1.) jp = 1.; // for points too close to the boundary
+      if (jm>=1.) jm = 1.;
+      if (z>=0)
+        { fx=1.-jm; fy=1.-jp; face=ntt; }
+      else
+        { fx=jp; fy=jm; face=ntt+8; }
+      }
+    }
+
+  public Fxyf(Vec3 v)
+    { this(new Hploc(v)); }
+
+  protected Hploc toHploc()
+    {
+    Hploc loc = new Hploc();
+    double jr = jrll[face] - fx - fy;
+
+    double nr;
+    if (jr<1)
+      {
+      nr = jr;
+      double tmp = nr*nr/3.;
+      loc.z = 1 - tmp;
+      if (loc.z>0.99) { loc.sth=Math.sqrt(tmp*(2.-tmp)); loc.have_sth=true; }
+      }
+    else if (jr>3)
+      {
+      nr = 4-jr;
+      double tmp = nr*nr/3.;
+      loc.z = tmp - 1;
+      if (loc.z<-0.99) { loc.sth=Math.sqrt(tmp*(2.-tmp)); loc.have_sth=true; }
+      }
+    else
+      {
+      nr = 1;
+      loc.z = (2-jr)*2./3.;
+      }
+
+    double tmp=jpll[face]*nr+fx-fy;
+    if (tmp<0) tmp+=8;
+    if (tmp>=8) tmp-=8;
+    loc.phi = (nr<1e-15) ? 0 : (0.5*Constants.halfpi*tmp)/nr;
+    return loc;
+    }
+  public Vec3 toVec3()
+    { return toHploc().toVec3(); }
+  }
diff -Nru healpix-java-3.40/src/java/src/healpix/essentials/HealpixBase.java healpix-java-3.50/src/java/src/healpix/essentials/HealpixBase.java
--- healpix-java-3.40/src/java/src/healpix/essentials/HealpixBase.java	1969-12-31 19:00:00.000000000 -0500
+++ healpix-java-3.50/src/java/src/healpix/essentials/HealpixBase.java	2015-09-12 05:25:53.000000000 -0400
@@ -0,0 +1,1297 @@
+/*
+ *  This file is part of Healpix Java.
+ *
+ *  This code 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 code 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 code; 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.sourceforge.net
+ */
+
+package healpix.essentials;
+
+import java.util.Arrays;
+
+/** Basic opersations related to the HEALPix pixelisation.
+    This class is conceptually very similar the the Healpix_Base class
+    of Healpix_cxx. It supports the NESTED scheme for nside parameters which are
+    powers of 2, and the RING scheme for arbitrary positive nside parameters.
+    The maximum supported nside parameter is 2^29.
+
+    @copyright 2011, 2012 Max-Planck-Society
+    @author Martin Reinecke */
+public class HealpixBase extends HealpixTables
+  {
+  protected final class Xyf
+    {
+    public int ix, iy, face;
+    public Xyf () {}
+    public Xyf (int x, int y, int f)
+      { ix=x; iy=y; face=f; }
+    }
+
+  private final class RingInfoSmall
+    {
+    long startpix, ringpix;
+    boolean shifted;
+    }
+
+  /** Maximum order parameter */
+  public static final int order_max=29;
+  /** Maximum Nside parameter; equivalent to 2^{@code order_max}. */
+  public static final long ns_max=1L<<order_max;
+
+  /** The order of the map; -1 when {@code nside} is not a power of 2. */
+  protected int order;
+
+  /** The Nside parameter. */
+  protected long nside;
+
+  protected long nl2, nl3, nl4, npface, npix, ncap;
+  protected double fact1, fact2;
+
+  /** The ordering scheme. */
+  protected Scheme scheme;
+
+  private static long spread_bits (int v)
+    {
+    return (long)(utab[ v      &0xff])      | ((long)(utab[(v>>> 8)&0xff])<<16)
+        | ((long)(utab[(v>>>16)&0xff])<<32) | ((long)(utab[(v>>>24)&0xff])<<48);
+    }
+  private static int compress_bits (long v)
+    {
+    long raw = v&0x5555555555555555L;
+    raw |= raw>>>15;
+    int raw1 = (int)(raw&0xffffL), raw2 = (int)((raw>>>32)&0xffffL);
+    return ctab[raw1&0xff]      | (ctab[raw1>>>8]<< 4)
+        | (ctab[raw2&0xff]<<16) | (ctab[raw2>>>8]<<20);
+    }
+
+  private Xyf nest2xyf(long ipix)
+    {
+    long pix=ipix&(npface-1);
+    return new Xyf (compress_bits(pix), compress_bits(pix>>>1),
+                    (int)(ipix>>>(2*order)));
+    }
+
+  private long xyf2nest(int ix, int iy, int face_num)
+    {
+    return ((long)(face_num)<<(2*order)) +
+      spread_bits(ix) + (spread_bits(iy)<<1);
+    }
+
+  private long xyf2ring(int ix, int iy, int face_num)
+    {
+    long jr = ((long)jrll[face_num]*nside) - (long)ix - (long)iy  - 1L;
+
+    RingInfoSmall ris = get_ring_info_small(jr);
+    long nr=ris.ringpix>>>2, kshift=ris.shifted ? 0:1;
+
+    long jp = (jpll[face_num]*nr + (long)ix - (long)iy + 1L + kshift) / 2L;
+    if (jp>nl4)
+      jp-=nl4;
+    else
+      if (jp<1) jp+=nl4;
+
+    return ris.startpix + jp - 1L;
+    }
+
+  protected Xyf ring2xyf(long pix)
+    {
+    Xyf ret = new Xyf();
+    long iring, iphi, kshift, nr;
+
+    if (pix<ncap) // North Polar cap
+      {
+      iring = (1+HealpixUtils.isqrt(1L+2L*pix))>>>1; //counted from North pole
+      iphi = (pix+1) - 2*iring*(iring-1);
+      kshift = 0;
+      nr = iring;
+      ret.face=(int)((iphi-1)/nr);
+      }
+    else if (pix<(npix-ncap)) // Equatorial region
+      {
+      long ip = pix - ncap;
+      long tmp = (order>=0) ? ip>>>(order+2) : ip/nl4;
+      iring = tmp+nside;
+      iphi = ip-tmp*nl4 + 1;
+      kshift = (iring+nside)&1;
+      nr = nside;
+      long ire = iring-nside+1,
+           irm = nl2+2-ire;
+      long ifm = iphi - (ire>>>1) + nside -1,
+           ifp = iphi - (irm>>>1) + nside -1;
+      if (order>=0)
+        { ifm >>>= order; ifp >>>= order; }
+      else
+        { ifm /= nside; ifp /= nside; }
+      ret.face = (int)((ifp==ifm) ? (ifp|4) : ((ifp<ifm) ? ifp : (ifm+8)));
+      }
+    else // South Polar cap
+      {
+      long ip = npix - pix;
+      iring = (1+HealpixUtils.isqrt(2L*ip-1L))>>>1; //counted from South pole
+      iphi  = 4L*iring + 1 - (ip - 2L*iring*(iring-1L));
+      kshift = 0;
+      nr = iring;
+      iring = 2L*nl2-iring;
+      ret.face = 8 + (int)((iphi-1)/nr);
+      }
+
+    long irt = iring - ((long)jrll[ret.face]*nside) + 1L;
+    long ipt = 2L*iphi- (long)jpll[ret.face]*nr - kshift -1L;
+    if (ipt>=nl2) ipt-=8L*nside;
+
+    ret.ix = (int)(( ipt-irt)>>>1);
+    ret.iy = (int)((-ipt-irt)>>>1);
+
+    return ret;
+    }
+
+  protected Xyf pix2xyf (long pix)
+    { return (scheme==Scheme.RING) ? ring2xyf(pix) : nest2xyf(pix); }
+
+  protected long xyf2pix (int ix, int iy, int face_num)
+    {
+    return (scheme==Scheme.RING) ?
+      xyf2ring(ix,iy,face_num) : xyf2nest(ix,iy,face_num);
+    }
+  protected long xyf2pix (Xyf xyf)
+    {
+    return (scheme==Scheme.RING) ?
+      xyf2ring(xyf.ix,xyf.iy,xyf.face) : xyf2nest(xyf.ix,xyf.iy,xyf.face);
+    }
+
+  /** Calculates the map order from its Nside parameter.
+      @param nside the Nside parameter
+      @return the map order corresponding to {@code nside}; -1 if
+        {@code nside} is not a power of 2. */
+  public static int nside2order(long nside) throws Exception
+    {
+    HealpixUtils.check (nside>0,"nside must be positive");
+    return ((nside&(nside-1))!=0) ? -1 : HealpixUtils.ilog2(nside);
+    }
+
+  /** Calculates the Nside parameter from the number of pixels.
+      @param npix the number of pixels
+      @return the computed Nside parameter */
+  public static long npix2Nside(long npix) throws Exception
+    {
+    HealpixUtils.check (npix>0,"npix must be positive");
+    long nside = HealpixUtils.isqrt(npix/12);
+    HealpixUtils.check(12*nside*nside==npix,"npix is not 12*nside*nside");
+    HealpixUtils.check(nside<=ns_max,"nside is too large");
+    return nside;
+    }
+  /** Calculates the number of pixels from the Nside parameter.
+      @param nside the Nside parameter
+      @return the computed number of pixels */
+  public static long nside2Npix(long nside) throws Exception
+    {
+    HealpixUtils.check (nside>0,"nside must be positive");
+    HealpixUtils.check(nside<=ns_max,"nside is too large");
+    return 12*nside*nside;
+    }
+
+  /** Calculates the number of pixels from the order parameter.
+      @param order the order parameter
+      @return the computed number of pixels */
+  public static long order2Npix(int order) throws Exception
+    {
+    HealpixUtils.check (order>=0,"order must be nonnegative");
+    HealpixUtils.check(order<=order_max,"order is too large");
+    return 12*(1L<<(2*order));
+    }
+
+  /** Adjusts the object to nside_in.
+      @param nside_in the new Nside parameter */
+  public void setNside (long nside_in) throws Exception
+    {
+    if (nside==nside_in) return;
+    nside=nside_in;
+    HealpixUtils.check(nside<=ns_max && nside>0,
+      "Nside must be between 1 and " + ns_max);
+
+    order = nside2order(nside);
+    if (scheme==Scheme.NESTED && order<0)
+      throw new Exception("Nside must be a power of 2 for NESTED scheme");
+    nl2 = 2*nside;
+    nl3 = 3*nside;
+    nl4 = 4*nside;
+    npface = nside*nside;
+    ncap = 2*nside*(nside-1); // pixels in each polar cap
+    npix = 12*npface;
+    fact2 = 4.0/npix;
+    fact1 = (nside<<1)*fact2;
+    }
+
+  /** Adjusts the object to nside_in and scheme_in.
+      @param nside_in the new Nside parameter
+      @param scheme_in the new ordering scheme */
+  public void setNsideAndScheme (long nside_in, Scheme scheme_in)
+    throws Exception
+    {
+    if ((scheme==scheme_in) && (nside==nside_in)) return;
+    HealpixUtils.check (((nside_in&(nside_in-1))==0)||(scheme_in==Scheme.RING),
+      "Nside must be a power of 2 for NESTED scheme");
+    scheme=scheme_in;
+    setNside(nside_in);
+    }
+
+  /** Initializes the object to Nside=1 and scheme=NESTED. */
+  public HealpixBase()
+    {
+    try
+      { nside=0; setNsideAndScheme(1,Scheme.NESTED); }
+    catch(Exception Ex) {/*cannot happen*/}
+    }
+
+  /** Initializes the object to a user-supplied Nside and ordering scheme.
+      @param nside_in the Nside parameter
+      @param scheme_in the ordering scheme */
+  public HealpixBase(long nside_in, Scheme scheme_in) throws Exception
+    { nside=nside_in-1; setNsideAndScheme(nside_in, scheme_in); }
+
+  /** Returns the current ordering scheme.
+      @return the current ordering scheme */
+  public Scheme getScheme()
+    { return scheme; }
+
+  /** Returns the current Nside parameter.
+      @return the current Nside parameter */
+  public int getNside()
+    { return (int)nside; }
+
+  /** Returns the total number of pixels in the pixelisation.
+      @return the current total number of pixels */
+  public long getNpix()
+    { return npix; }
+
+  /** Adjusts the object to scheme.
+      @param scheme_in the new ordering scheme */
+  public void setScheme(Scheme scheme_in) throws Exception
+    {
+    if (scheme_in==Scheme.NESTED && order<0)
+      throw new Exception("Nside must be a power of 2 for NESTED scheme");
+    scheme = scheme_in;
+    }
+
+  /** Returns the current order parameter.
+      @return the current map order parameter. */
+  public int getOrder()
+    { return order; }
+
+  /** Returns the pixel which contains the supplied Pointing.
+      @param ptg the requested location on the sphere.
+      @return the pixel number containing the location. */
+  public long ang2pix(Pointing ptg) throws Exception
+    { return loc2pix(new Hploc(ptg)); }
+
+  /** Returns the Pointing corresponding to the center of the supplied pixel.
+      @param pix the requested pixel number.
+      @return the pixel's center coordinates. */
+  public Pointing pix2ang(long pix) throws Exception
+    { return pix2loc(pix).toPointing(); }
+
+  /** Returns the pixel which contains the supplied Vec3.
+      @param vec the requested location on the sphere (need not be normalized).
+      @return the pixel number containing the location. */
+  public long vec2pix(Vec3 vec) throws Exception
+    { return loc2pix(new Hploc(vec)); }
+
+  /** Returns the normalized 3-vector corresponding to the center of the
+      supplied pixel.
+      @param pix the requested pixel number.
+      @return the pixel's center coordinates. */
+  public Vec3 pix2vec(long pix) throws Exception
+    { return pix2loc(pix).toVec3(); }
+
+  /** Returns nested pixel number for the supplied ring pixel number.
+      @param ipring the requested pixel number in RING scheme.
+      @return the corresponding pixel number in NESTED scheme. */
+  public long ring2nest(long ipring) throws Exception
+    {
+    Xyf xyf = ring2xyf(ipring);
+    return xyf2nest (xyf.ix,xyf.iy, xyf.face);
+    }
+
+  /** Returns ring pixel number for the supplied nested pixel number.
+      @param ipnest the requested pixel number in NESTED scheme.
+      @return the corresponding pixel number in RING scheme. */
+  public long nest2ring(long ipnest) throws Exception
+    {
+    Xyf xyf = nest2xyf(ipnest);
+    return xyf2ring (xyf.ix,xyf.iy, xyf.face);
+    }
+
+  protected long loc2pix (Hploc loc)
+    {
+    double z=loc.z, phi=loc.phi;
+
+    double za = Math.abs(z);
+    double tt = HealpixUtils.fmodulo((phi*Constants.inv_halfpi),4.0);// in [0,4)
+
+    if (scheme==Scheme.RING)
+      {
+      if (za<=Constants.twothird) // Equatorial region
+        {
+        double temp1 = nside*(0.5+tt);
+        double temp2 = nside*z*0.75;
+        long jp = (long)(temp1-temp2); // index of  ascending edge line
+        long jm = (long)(temp1+temp2); // index of descending edge line
+
+        // ring number counted from z=2/3
+        long ir = nside + 1 + jp - jm; // in {1,2n+1}
+        long kshift = 1-(ir&1); // kshift=1 if ir even, 0 otherwise
+
+        long t1 = jp+jm-nside+kshift+1+nl4+nl4;
+        long ip = (order>0) ?
+          (t1>>>1)&(nl4-1) : ((t1>>>1)%nl4); // in {0,4n-1}
+
+        return ncap + (ir-1)*nl4 + ip;
+        }
+      else  // North & South polar caps
+        {
+        double tp = tt-(long)(tt);
+        double tmp = ((za<0.99)||(!loc.have_sth)) ?
+                     nside*Math.sqrt(3*(1-za)) :
+                     nside*loc.sth/Math.sqrt((1.+za)/3.);
+
+        long jp = (long)(tp*tmp); // increasing edge line index
+        long jm = (long)((1.0-tp)*tmp); // decreasing edge line index
+
+        long ir = jp+jm+1; // ring number counted from the closest pole
+        long ip = (long)(tt*ir); // in {0,4*ir-1}
+        assert((ip>=0)&&(ip<4*ir));
+
+        return (z>0)  ?  2*ir*(ir-1) + ip  :  npix - 2*ir*(ir+1) + ip;
+        }
+      }
+    else // scheme_ == NEST
+      {
+      if (za<=Constants.twothird) // Equatorial region
+        {
+        double temp1 = nside*(0.5+tt);
+        double temp2 = nside*(z*0.75);
+        long jp = (long)(temp1-temp2); // index of  ascending edge line
+        long jm = (long)(temp1+temp2); // index of descending edge line
+        long ifp = jp >>> order;  // in {0,4}
+        long ifm = jm >>> order;
+        long face_num = (ifp==ifm) ? (ifp|4) : ((ifp<ifm) ? ifp : (ifm+8));
+
+        long ix = jm & (nside-1),
+             iy = nside - (jp & (nside-1)) - 1;
+        return xyf2nest((int)ix,(int)iy,(int)face_num);
+        }
+      else // polar region, za > 2/3
+        {
+        int ntt = Math.min(3,(int)tt);
+        double tp = tt-ntt;
+        double tmp = ((za<0.99)||(!loc.have_sth)) ?
+                     nside*Math.sqrt(3*(1-za)) :
+                     nside*loc.sth/Math.sqrt((1.+za)/3.);
+
+        long jp = (long)(tp*tmp); // increasing edge line index
+        long jm = (long)((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;
+        return (z>=0) ?
+          xyf2nest((int)(nside-jm -1),(int)(nside-jp-1),ntt) :
+          xyf2nest((int)jp,(int)jm,ntt+8);
+        }
+      }
+    }
+
+  /** Returns the pixel which contains the supplied Zphi.
+      @param zphi the requested location on the sphere.
+      @return the pixel number containing the location. */
+  public long zphi2pix (Zphi zphi)
+    { return loc2pix (new Hploc(zphi)); }
+
+  protected Hploc pix2loc (long pix)
+    {
+    Hploc loc = new Hploc();
+    if (scheme==Scheme.RING)
+      {
+      if (pix<ncap) // North Polar cap
+        {
+        long iring = (1+(HealpixUtils.isqrt(1+2*pix)))>>>1; //from North pole
+        long iphi  = (pix+1) - 2*iring*(iring-1);
+
+        double tmp = (iring*iring)*fact2;
+        loc.z = 1.0 - tmp;
+        if (loc.z>0.99) { loc.sth=Math.sqrt(tmp*(2.-tmp)); loc.have_sth=true; }
+        loc.phi = (iphi-0.5) * Constants.halfpi/iring;
+        }
+      else if (pix<(npix-ncap)) // Equatorial region
+        {
+        long ip  = pix - ncap;
+        long tmp = (order>=0) ? ip>>>(order+2) : ip/nl4;
+        long iring = tmp + nside,
+          iphi = ip-nl4*tmp+1;;
+        // 1 if iring+nside is odd, 1/2 otherwise
+        double fodd = ((iring+nside)&1)!=0 ? 1 : 0.5;
+
+        loc.z = (nl2-iring)*fact1;
+        loc.phi = (iphi-fodd) * Math.PI*0.75*fact1;
+        }
+      else // South Polar cap
+        {
+        long ip = npix - pix;
+        long iring = (1+HealpixUtils.isqrt(2*ip-1))>>>1; //from South pole
+        long iphi  = 4*iring + 1 - (ip - 2*iring*(iring-1));
+
+        double tmp = (iring*iring)*fact2;
+        loc.z = tmp-1.0;
+        if (loc.z<-0.99) { loc.sth=Math.sqrt(tmp*(2.-tmp)); loc.have_sth=true; }
+        loc.phi = (iphi-0.5) * Constants.halfpi/iring;
+        }
+      }
+    else
+      {
+      Xyf xyf= nest2xyf(pix);
+
+      long jr = ((long)(jrll[xyf.face])<<order) -xyf.ix - xyf.iy - 1;
+
+      long nr;
+      if (jr<nside)
+        {
+        nr = jr;
+        double tmp = (nr*nr)*fact2;
+        loc.z = 1 - tmp;
+        if (loc.z>0.99) { loc.sth=Math.sqrt(tmp*(2.-tmp)); loc.have_sth=true; }
+        }
+      else if (jr>nl3)
+        {
+        nr = nl4-jr;
+        double tmp = (nr*nr)*fact2;
+        loc.z = tmp - 1;
+        if (loc.z<-0.99) { loc.sth=Math.sqrt(tmp*(2.-tmp)); loc.have_sth=true; }
+        }
+      else
+        {
+        nr = nside;
+        loc.z = (nl2-jr)*fact1;
+        }
+
+      long tmp=(long)(jpll[xyf.face])*nr+xyf.ix-xyf.iy;
+      assert(tmp<8*nr); // must not happen
+      if (tmp<0) tmp+=8*nr;
+      loc.phi = (nr==nside) ? 0.75*Constants.halfpi*tmp*fact1 :
+                             (0.5*Constants.halfpi*tmp)/nr;
+      }
+    return loc;
+    }
+
+  /** Returns the Zphi corresponding to the center of the supplied pixel.
+      @param pix the requested pixel number.
+      @return the pixel's center coordinates. */
+  public Zphi pix2zphi (long pix)
+    { return pix2loc(pix).toZphi(); }
+
+  /** Returns the neighboring pixels of ipix.
+      This method works in both RING and NEST schemes, but is
+      considerably faster in the NEST scheme.
+      @param ipix the requested pixel number.
+      @return array with indices of the neighboring pixels.
+        The returned array contains (in this order)
+        the pixel numbers of the SW, W, NW, N, NE, E, SE and S neighbor
+        of ipix. If a neighbor does not exist (this can only happen
+        for the W, N, E and S neighbors), its entry is set to -1. */
+  public long[] neighbours(long ipix) throws Exception
+    {
+    long[] result = new long[8];
+    Xyf xyf = (scheme==Scheme.NESTED) ? nest2xyf(ipix) : ring2xyf(ipix);
+    int ix = xyf.ix, iy=xyf.iy, face_num=xyf.face;
+
+    long nsm1 = nside-1;
+    if ((ix>0)&&(ix<nsm1)&&(iy>0)&&(iy<nsm1))
+      {
+      if (scheme==Scheme.RING)
+        for (int m=0; m<8; ++m)
+          result[m]=(xyf2ring(ix+xoffset[m],iy+yoffset[m],face_num));
+      else
+        {
+        long fpix = (long)(face_num)<<(2*order),
+             px0=spread_bits(ix  ), py0=spread_bits(iy  )<<1,
+             pxp=spread_bits(ix+1), pyp=spread_bits(iy+1)<<1,
+             pxm=spread_bits(ix-1), pym=spread_bits(iy-1)<<1;
+
+        result[0]=fpix+pxm+py0; result[1]=fpix+pxm+pyp;
+        result[2]=fpix+px0+pyp; result[3]=fpix+pxp+pyp;
+        result[4]=fpix+pxp+py0; result[5]=fpix+pxp+pym;
+        result[6]=fpix+px0+pym; result[7]=fpix+pxm+pym;
+        }
+      }
+    else
+      {
+      for (int i=0; i<8; ++i)
+        {
+        int x=ix+xoffset[i];
+        int y=iy+yoffset[i];
+        int nbnum=4;
+        if (x<0)
+          { x+=nside; nbnum-=1; }
+        else if (x>=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)
+          {
+          int bits = swaparray[nbnum][face_num>>>2];
+          if ((bits&1)>0) x=(int)(nside-x-1);
+          if ((bits&2)>0) y=(int)(nside-y-1);
+          if ((bits&4)>0) { int tint=x; x=y; y=tint; }
+          result[i] = (scheme==Scheme.NESTED) ?
+            xyf2nest(x,y,f) : xyf2ring(x,y,f);
+          }
+        else
+          result[i]=-1;
+        }
+      }
+    return result;
+    }
+
+  /** Returns the maximum angular distance between a pixel center and its
+      corners.
+      @return maximum angular distance between a pixel center and its
+        corners. */
+  public double maxPixrad()
+    {
+    Vec3 va = new Vec3(new Zphi(2./3., Math.PI/nl4));
+    double t1 = 1.-1./nside;
+    t1*=t1;
+    Vec3 vb = new Vec3(new Zphi(1-t1/3, 0));
+    return va.angle(vb);
+    }
+
+  private RingInfoSmall get_ring_info_small (long ring)
+    {
+    RingInfoSmall ret = new RingInfoSmall();
+    if (ring<nside)
+      {
+      ret.shifted = true;
+      ret.ringpix = 4*ring;
+      ret.startpix = 2*ring*(ring-1);
+      }
+    else if (ring<nl3)
+      {
+      ret.shifted = ((ring-nside) & 1) == 0;
+      ret.ringpix = nl4;
+      ret.startpix = ncap + (ring-nside)*nl4;
+      }
+    else
+      {
+      ret.shifted = true;
+      long nr=nl4-ring;
+      ret.ringpix = 4*nr;
+      ret.startpix = npix-2*nr*(nr+1);
+      }
+    return ret;
+    }
+
+  private long ringAbove (double z)
+    {
+    double az=Math.abs(z);
+    if (az> Constants.twothird) // polar caps
+      {
+      long iring = (long)(nside*Math.sqrt(3*(1-az)));
+      return (z>0) ? iring : nl4-iring-1;
+      }
+    else // equatorial region
+      return (long)(nside*(2.0-1.5*z));
+    }
+
+  /** Returns the z-coordinate (equivalent to the cosine of the colatitude)
+      for the requested ring.
+      This method also accepts the not-really-existing ring indices 0 and
+      4*Nside, which correspond to North and South Poles, respectively.
+      @param ring ring index: the northernmost ring in the map has index 1;
+        ring indices are increasing towards the South pole.
+      @return z-coordinate of the ring. */
+  public double ring2z (long ring)
+    {
+    if (ring<nside)
+      return 1 - ring*ring*fact2;
+    if (ring <=nl3)
+      return (nl2-ring)*fact1;
+    ring=nl4 - ring;
+    return ring*ring*fact2 - 1;
+    }
+  /** Returns the colatitude for the requested ring.
+      This method also accepts the not-really-existing ring indices 0 and
+      4*Nside, which correspond to North and South Poles, respectively.
+      @param ring ring index: the northernmost ring in the map has index 1;
+        ring indices are increasing towards the South pole.
+      @return z-coordinate of the ring. */
+  public double ring2theta (long ring)
+    {
+    if (ring<nside)
+      {
+      double tmp=ring*ring*fact2;
+      return FastMath.atan2 (Math.sqrt(tmp*(2.-tmp)),1-tmp);
+      }
+    if (ring <=nl3)
+      {
+      double cth=(nl2-ring)*fact1;
+      return FastMath.atan2 (Math.sqrt(1.-cth*cth),cth);
+      }
+    ring=nl4 - ring;
+    double tmp=ring*ring*fact2;
+    return FastMath.atan2 (Math.sqrt(tmp*(2.-tmp)),tmp-1);
+    }
+
+  private final class pstack
+    {
+    private long[] p;
+    private int[] o;
+    private int s, m;
+
+    public pstack (int sz)
+      { p=new long[sz]; o=new int[sz]; s=m=0; }
+    public void push (long p_, int o_)
+      { p[s]=p_; o[s]=o_; ++s; }
+    public void pop ()
+      { --s; }
+    public void popToMark ()
+      { s=m; }
+    public int size ()
+      { return s; }
+    public void mark ()
+      { m=s; }
+    public int otop ()
+      { return o[s-1]; }
+    public long ptop ()
+      { return p[s-1]; }
+    }
+
+  private RangeSet queryStripInternal(double theta1, double theta2,
+    boolean inclusive) throws Exception
+    {
+    RangeSet pixset = new RangeSet(1);
+    if (scheme==Scheme.RING)
+      {
+      long ring1 = Math.max(1,1+ringAbove(FastMath.cos(theta1))),
+           ring2 = Math.min(4*nside-1,ringAbove(FastMath.cos(theta2)));
+      if (inclusive)
+        {
+        ring1 = Math.max(1,ring1-1);
+        ring2 = Math.min(4*nside-1,ring2+1);
+        }
+
+      RingInfoSmall ris1 = get_ring_info_small(ring1),
+                    ris2 = get_ring_info_small(ring2);
+      long pix1 = ris1.startpix,
+           pix2 = ris2.startpix+ris2.ringpix;
+      if (pix1<pix2) pixset.append(pix1,pix2);
+      }
+    else
+      HealpixUtils.check(false,"queryStrip not yet implemented for NESTED");
+
+    return pixset;
+    }
+
+  /** Returns a range set of pixels whose centers lie within a given latitude
+      range (if {@code inclusive==false}), or which overlap with this range
+      (if {@code inclusive==true}).<p>
+      The latitude range is defined as follows:
+      <ul>
+      <li>if {@code theta1<theta2}, it is the range between {@code theta1}
+          and {@code theta2}</li>
+      <li>otherwise it is the range between 0 and {@code theta2}, and between
+          {@code theta1} and pi.</li>
+      </ul>
+      This method currently only works in the RING scheme. */
+  public RangeSet queryStrip(double theta1, double theta2,
+    boolean inclusive) throws Exception
+    {
+    if (theta1<theta2)
+      return queryStripInternal(theta1,theta2,inclusive);
+    RangeSet res = queryStripInternal(0.,theta2,inclusive);
+    return res.union(queryStripInternal(theta1,Math.PI,inclusive));
+    }
+
+  private boolean checkPixelRing (HealpixBase b2, long pix, long nr,
+    long ipix1, int fct, Zphi czphi, double cosrp2, long cpix)
+    {
+    if (pix>=nr) pix-=nr;
+    if (pix<0) pix+=nr;
+    pix+=ipix1;
+    if (pix==cpix) return false; // disk center in pixel => overlap
+    Xyf xyf=pix2xyf(pix);
+    for (int i=0; i<fct-1; ++i) // go along the 4 edges
+      {
+      int ox=fct*xyf.ix, oy=fct*xyf.iy;
+      Xyf xyf2 = new Xyf (ox,oy,xyf.face);
+      double pz,pphi;
+      xyf2.ix=ox+i; xyf2.iy=oy;
+      if (HealpixUtils.cosdist_zphi(czphi,b2.pix2zphi(b2.xyf2pix(xyf2)))>cosrp2)
+        return false; // overlap
+      xyf2.ix=ox+fct-1; xyf2.iy=oy+i;
+      if (HealpixUtils.cosdist_zphi(czphi,b2.pix2zphi(b2.xyf2pix(xyf2)))>cosrp2)
+        return false; // overlap
+      xyf2.ix=ox+fct-1-i; xyf2.iy=oy+fct-1;
+      if (HealpixUtils.cosdist_zphi(czphi,b2.pix2zphi(b2.xyf2pix(xyf2)))>cosrp2)
+        return false; // overlap
+      xyf2.ix=ox; xyf2.iy=oy+fct-1-i;
+      if (HealpixUtils.cosdist_zphi(czphi,b2.pix2zphi(b2.xyf2pix(xyf2)))>cosrp2)
+        return false; // overlap
+      }
+    return true;
+    }
+
+  private RangeSet queryDiscInternal(Pointing ptg, double radius, int fact)
+    throws Exception
+    {
+    boolean inclusive=(fact!=0);
+    RangeSet pixset = new RangeSet();
+    if (scheme==Scheme.RING)
+      {
+      int fct=1;
+      if (inclusive)
+        {
+        HealpixUtils.check ((1L<<order_max)/nside>=fact,
+          "invalid oversampling factor");
+        fct = fact;
+        }
+      HealpixBase b2=null;
+      double rsmall,rbig;
+      if (fct>1)
+        {
+        b2=new HealpixBase(fct*nside,Scheme.RING);
+        rsmall = radius+b2.maxPixrad();
+        rbig = radius+maxPixrad();
+        }
+      else
+        rsmall = rbig = inclusive ? radius+maxPixrad() : radius;
+
+      if (rsmall>=Math.PI)
+        { pixset.append(0,npix); return pixset; }
+
+      rbig = Math.min (Math.PI,rbig);
+
+      double cosrsmall = FastMath.cos(rsmall);
+      double cosrbig = FastMath.cos(rbig);
+
+      double z0 = FastMath.cos(ptg.theta);
+      double xa = 1./Math.sqrt((1-z0)*(1+z0));
+
+      Zphi czphi = new Zphi(z0,ptg.phi);
+      long cpix = zphi2pix(czphi);
+
+      double rlat1  = ptg.theta - rsmall;
+      double zmax = FastMath.cos(rlat1);
+      long irmin = ringAbove (zmax)+1;
+
+      if ((rlat1<=0) && (irmin>1)) // north pole in the disk
+        {
+        RingInfoSmall info =get_ring_info_small(irmin-1);
+        pixset.append(0,info.startpix+info.ringpix);
+        }
+
+      if ((fct>1) && (rlat1>0)) irmin=Math.max(1L,irmin-1);
+
+      double rlat2  = ptg.theta + rsmall;
+      double zmin = FastMath.cos(rlat2);
+      long irmax = ringAbove (zmin);
+
+      if ((fct>1) && (rlat2<Math.PI)) irmax=Math.min(nl4-1,irmax+1);
+
+      for (long iz=irmin; iz<=irmax; ++iz) // rings partially in the disk
+        {
+        double z=ring2z(iz);
+
+        double x = (cosrbig-z*z0)*xa;
+        double ysq = 1-z*z-x*x;
+        double dphi=-1;
+        if (ysq<=0) // no intersection, ring completely inside or outside
+          dphi = (fct==1) ? 0: Math.PI-1e-15;
+        else
+          dphi = FastMath.atan2(Math.sqrt(ysq),x);
+        if (dphi>0)
+          {
+          RingInfoSmall info =get_ring_info_small(iz);
+          long ipix1 = info.startpix, nr=info.ringpix, ipix2=ipix1+nr-1;
+          double shift = info.shifted ? 0.5 : 0.;
+
+          long ip_lo = (long)Math.floor
+            (nr*Constants.inv_twopi*(ptg.phi-dphi) - shift)+1;
+          long ip_hi = (long)Math.floor
+            (nr*Constants.inv_twopi*(ptg.phi+dphi) - shift);
+
+          if (fct>1)
+            {
+            while ((ip_lo<=ip_hi) && checkPixelRing
+                  (b2,ip_lo,nr,ipix1,fct,czphi,cosrsmall,cpix))
+              ++ip_lo;
+            while ((ip_hi>ip_lo) && checkPixelRing
+                  (b2,ip_hi,nr,ipix1,fct,czphi,cosrsmall,cpix))
+              --ip_hi;
+            }
+
+          if (ip_lo<=ip_hi)
+            {
+            if (ip_hi>=nr)
+              { ip_lo-=nr; ip_hi-=nr; }
+            if (ip_lo<0)
+              {
+              pixset.append(ipix1,ipix1+ip_hi+1);
+              pixset.append(ipix1+ip_lo+nr,ipix2+1);
+              }
+            else
+              pixset.append(ipix1+ip_lo,ipix1+ip_hi+1);
+            }
+          }
+        }
+
+      if ((rlat2>=Math.PI) && (irmax+1<nl4)) // south pole in the disk
+        {
+        RingInfoSmall info =get_ring_info_small(irmax+1);
+        pixset.append(info.startpix,npix);
+        }
+      }
+    else // scheme_==NEST
+      {
+      if (radius>=Math.PI) // disk covers the whole sphere
+        { pixset.append(0,npix); return pixset; }
+
+      int oplus=0;
+      if (inclusive)
+        {
+        HealpixUtils.check ((1L<<order_max)>=fact,"invalid oversampling factor");
+        HealpixUtils.check ((fact&(fact-1))==0,
+          "oversampling factor must be a power of 2");
+        oplus=HealpixUtils.ilog2(fact);
+        }
+      int omax=Math.min(order_max,order+oplus); // the order up to which we test
+
+      Vec3 vptg = new Vec3(ptg);
+
+      double[] crpdr = new double[omax+1];
+      double[] crmdr = new double[omax+1];
+
+      double cosrad=FastMath.cos(radius),
+             sinrad=FastMath.sin(radius);
+      for (int o=0; o<=omax; o++) // prepare data at the required orders
+        {
+        double dr = HealpixProc.mpr[o]; // safety distance
+        double cdr = HealpixProc.cmpr[o];
+        double sdr = HealpixProc.smpr[o];
+        crpdr[o] = (radius+dr>Math.PI) ? -1. : cosrad*cdr-sinrad*sdr;
+        crmdr[o] = (radius-dr<0.)      ?  1. : cosrad*cdr+sinrad*sdr;
+        }
+
+      pstack stk=new pstack(12+3*omax);
+
+/* Still experimental, therefore disabled
+      Fxyf fxyf=new Fxyf(vptg);
+      for (int o=order; o>=0; --o)
+        {
+        long nsd=HealpixProc.bn[o].nside;
+        double fx=nsd*fxyf.fx-(int)(nsd*fxyf.fx),
+               fy=nsd*fxyf.fy-(int)(nsd*fxyf.fy);
+        double fmin = Math.min(Math.min(fx,fy),Math.min(1-fx,1-fy));
+        if (fmin*0.7>nsd*radius)
+          {
+          System.out.println("contained completely at order "+o);
+          stk.push(HealpixProc.bn[o].vec2pix(vptg),o);
+          break;
+          }
+        }
+      if (stk.size()==0)
+*/
+
+      for (int i=0; i<12; i++) // insert the 12 base pixels in reverse order
+        stk.push(11-i,0);
+
+      while (stk.size()>0) {// as long as there are pixels on the stack
+        // pop current pixel number and order from the stack
+        long pix=stk.ptop();
+        int o=stk.otop();
+        stk.pop();
+
+        Zphi pos=HealpixProc.bn[o].pix2zphi(pix);
+        // cosine of angular distance between pixel center and disk center
+        double cangdist=HealpixUtils.cosdist_zphi(vptg.z,ptg.phi,pos.z,pos.phi);
+
+        if (cangdist>crpdr[o])
+          {
+          int zone = (cangdist<cosrad) ? 1 : ((cangdist<=crmdr[o]) ? 2 : 3);
+
+          check_pixel (o, omax, zone, pixset, pix, stk, inclusive);
+          }
+        }
+      }
+    return pixset;
+    }
+
+  /** Returns a range set of pixels whose centers lie within a given disk. <p>
+      This method is more efficient in the RING scheme.
+      @param ptg the angular coordinates of the disk center
+      @param radius the radius (in radians) of the disk
+      @return the requested set of pixel number ranges  */
+  public RangeSet queryDisc(Pointing ptg, double radius)
+    throws Exception
+    { return queryDiscInternal (ptg, radius, 0); }
+  /** Returns a range set of pixels which overlap with a given disk. <p>
+      This method is more efficient in the RING scheme. <p>
+      This method may return some pixels which don't overlap with
+      the polygon at all. The higher {@code fact} is chosen, the fewer false
+      positives are returned, at the cost of increased run time.
+      @param ptg the angular coordinates of the disk center
+      @param radius the radius (in radians) of the disk
+      @param fact The overlapping test will be done at the resolution
+        {@code fact*nside}. For NESTED ordering, {@code fact} must be a power
+        of 2, else it can be any positive integer. A typical choice would be 4.
+      @return the requested set of pixel number ranges  */
+  public RangeSet queryDiscInclusive (Pointing ptg, double radius, int fact)
+    throws Exception
+    { return queryDiscInternal (ptg, radius, fact); }
+
+  private RangeSet queryMultiDisc (Vec3[] norm, double[] rad,
+    int fact) throws Exception
+    {
+    boolean inclusive = (fact!=0);
+    int nv=norm.length;
+    HealpixUtils.check(nv==rad.length,"inconsistent input arrays");
+    RangeSet res = new RangeSet();
+
+    if (scheme==Scheme.RING)
+      {
+      int fct=1;
+      if (inclusive)
+        {
+        HealpixUtils.check (((1L<<order_max)/nside)>=fact,
+          "invalid oversampling factor");
+        fct = fact;
+        }
+      HealpixBase b2=null;
+      double rpsmall,rpbig;
+      if (fct>1)
+        {
+        b2=new HealpixBase(fct*nside,Scheme.RING);
+        rpsmall = b2.maxPixrad();
+        rpbig = maxPixrad();
+        }
+      else
+        rpsmall = rpbig = inclusive ? maxPixrad() : 0;
+
+      long irmin=1, irmax=nl4-1;
+      int nd=0;
+      double[] z0=new double[nv];
+      double[] xa=new double[nv];
+      double[] cosrsmall=new double[nv];
+      double[] cosrbig=new double[nv];
+      Pointing[] ptg=new Pointing[nv];
+      long[] cpix=new long[nv];
+      Zphi[] czphi=new Zphi[nv];
+      for (int i=0; i<nv; ++i)
+        {
+        double rsmall=rad[i]+rpsmall;
+        if (rsmall<Math.PI)
+          {
+          double rbig = Math.min(Math.PI,rad[i]+rpbig);
+          Pointing pnt= new Pointing(norm[i]);
+          cosrsmall[nd]=FastMath.cos(rsmall);
+          cosrbig[nd]=FastMath.cos(rbig);
+          double cth=FastMath.cos(pnt.theta);
+          z0[nd]=cth;
+          if (fct>1) cpix[nd]=zphi2pix(new Zphi(cth,pnt.phi));
+          if (fct>1) czphi[nd]=new Zphi(cth,pnt.phi);
+          xa[nd]=1./Math.sqrt((1-cth)*(1+cth));
+          ptg[nd]=pnt;
+
+          double rlat1 = pnt.theta - rsmall;
+          double zmax = FastMath.cos(rlat1);
+          long irmin_t = (rlat1<=0) ? 1 : ringAbove (zmax)+1;
+
+          if ((fct>1) && (rlat1>0)) irmin_t=Math.max(1L,irmin_t-1);
+
+          double rlat2 = pnt.theta + rsmall;
+          double zmin = FastMath.cos(rlat2);
+          long irmax_t = (rlat2>=Math.PI) ? nl4-1 : ringAbove (zmin);
+
+          if ((fct>1) && (rlat2<Math.PI))
+            irmax_t=Math.min(nl4-1,irmax_t+1);
+          if (irmax_t < irmax) irmax=irmax_t;
+          if (irmin_t > irmin) irmin=irmin_t;
+
+          ++nd;
+          }
+        }
+
+      for (long iz=irmin; iz<=irmax; ++iz)
+        {
+        double z=ring2z(iz);
+        RingInfoSmall ris=get_ring_info_small(iz);
+        long ipix1=ris.startpix, nr=ris.ringpix;
+        long ipix2 = ipix1 + nr - 1; // highest pixel number in the ring
+        double shift = ris.shifted ? 0.5 : 0.;
+        RangeSet rstmp = new RangeSet();
+        rstmp.append(ipix1,ipix2+1);
+
+        for (int j=0; (j<nd)&&(rstmp.nranges()>0); ++j)
+          {
+          double x = (cosrbig[j]-z*z0[j])*xa[j];
+          double ysq = 1.-z*z-x*x;
+          double dphi = (ysq<=0) ? Math.PI-1e-15 :
+                                   FastMath.atan2(Math.sqrt(ysq),x);
+
+          long ip_lo = (long)Math.floor
+            (nr*Constants.inv_twopi*(ptg[j].phi-dphi)-shift)+1;
+          long ip_hi = (long)Math.floor
+            (nr*Constants.inv_twopi*(ptg[j].phi+dphi)-shift);
+
+          if (fct>1)
+            {
+            while ((ip_lo<=ip_hi) && checkPixelRing
+                  (b2,ip_lo,nr,ipix1,fct,czphi[j],cosrsmall[j],cpix[j]))
+              ++ip_lo;
+            while ((ip_hi>ip_lo) && checkPixelRing
+                  (b2,ip_hi,nr,ipix1,fct,czphi[j],cosrsmall[j],cpix[j]))
+              --ip_hi;
+            }
+
+          if (ip_hi>=nr)
+            { ip_lo-=nr; ip_hi-=nr;}
+
+          if (ip_lo<0)
+            {
+            if (ip_hi+1<=ip_lo+nr-1)
+              rstmp.remove(ipix1+ip_hi+1,ipix1+ip_lo+nr);
+            }
+          else
+            rstmp.intersect(ipix1+ip_lo,ipix1+ip_hi+1);
+          }
+        res.append(rstmp);
+        }
+      }
+    else // scheme == NEST
+      {
+      int oplus = 0;
+      if (inclusive)
+        {
+        HealpixUtils.check ((1L<<(order_max-order))>=fact,
+          "invalid oversampling factor");
+        HealpixUtils.check ((fact&(fact-1))==0,
+          "oversampling factor must be a power of 2");
+        oplus=HealpixUtils.ilog2(fact);
+        }
+      int omax=order+oplus; // the order up to which we test
+
+      // TODO: ignore all disks with radius>=pi
+
+      double[][][] crlimit=new double[omax+1][nv][3];
+      for (int o=0; o<=omax; ++o) // prepare data at the required orders
+        {
+        double dr=HealpixProc.bn[o].maxPixrad(); // safety distance
+        for (int i=0; i<nv; ++i)
+          {
+          crlimit[o][i][0] = (rad[i]+dr>Math.PI) ? -1: FastMath.cos(rad[i]+dr);
+          crlimit[o][i][1] = (o==0) ? FastMath.cos(rad[i]) : crlimit[0][i][1];
+          crlimit[o][i][2] = (rad[i]-dr<0.) ?  1. : FastMath.cos(rad[i]-dr);
+          }
+        }
+
+      pstack stk=new pstack(12+3*omax);
+      for (int i=0; i<12; i++) // insert the 12 base pixels in reverse order
+        stk.push(11-i,0);
+
+      while (stk.size()>0) { // as long as there are pixels on the stack
+        // pop current pixel number and order from the stack
+        long pix=stk.ptop();
+        int o=stk.otop();
+        stk.pop();
+
+        Vec3 pv = HealpixProc.bn[o].pix2vec(pix);
+
+        int zone=3;
+        for (int i=0; (i<nv)&&(zone>0); ++i)
+          {
+          double crad=pv.dot(norm[i]);
+          for (int iz=0; iz<zone; ++iz)
+            if (crad<crlimit[o][i][iz])
+              zone=iz;
+          }
+
+        if (zone>0) check_pixel (o, omax, zone, res, pix, stk, inclusive);
+        }
+      }
+    return res;
+    }
+
+  private RangeSet queryPolygonInternal (Pointing[] vertex, int fact)
+    throws Exception
+    {
+    boolean inclusive = (fact!=0);
+    int nv=vertex.length;
+    int ncirc = inclusive ? nv+1 : nv;
+    HealpixUtils.check(nv>=3,"not enough vertices in polygon");
+    Vec3[] vv = new Vec3[nv];
+    for (int i=0; i<nv; ++i)
+      vv[i] = new Vec3(vertex[i]);
+    Vec3[] normal = new Vec3[ncirc];
+    int flip=0;
+    for (int i=0; i<nv; ++i)
+      {
+      normal[i]=vv[i].cross(vv[(i+1)%nv]).norm();
+      double hnd=normal[i].dot(vv[(i+2)%nv]);
+      HealpixUtils.check(Math.abs(hnd)>1e-10,"degenerate corner");
+      if (i==0)
+        flip = (hnd<0.) ? -1 : 1;
+      else
+        HealpixUtils.check(flip*hnd>0,"polygon is not convex");
+      normal[i].scale(flip);
+      }
+    double[] rad = new double[ncirc];
+    Arrays.fill(rad,Constants.halfpi);
+    if (inclusive)
+      {
+      CircleFinder cf = new CircleFinder(vv);
+      normal[nv]=cf.getCenter();
+      rad[nv]=FastMath.acos(cf.getCosrad());
+      }
+    return queryMultiDisc(normal,rad,fact);
+    }
+  /** Returns a range set of pixels whose centers lie within the convex
+      polygon defined by the {@code vertex} array. <p>
+      This method is more efficient in the RING scheme.
+      @param vertex an array containing the vertices of the requested convex
+        polygon.
+      @return the requested set of pixel number ranges  */
+  public RangeSet queryPolygon (Pointing[] vertex) throws Exception
+    { return queryPolygonInternal (vertex, 0); }
+  /** Returns a range set of pixels that overlap with the convex
+      polygon defined by the {@code vertex} array. <p>
+      This method is more efficient in the RING scheme.<p>
+      This method may return some pixels which don't overlap with
+      the polygon at all. The higher {@code fact} is chosen, the fewer false
+      positives are returned, at the cost of increased run time.
+      @param vertex an array containing the vertices of the requested convex
+        polygon.
+      @param fact The overlapping test will be done at the resolution
+        {@code fact*nside}. For NESTED ordering, {@code fact} must be a power
+        of 2, else it can be any positive integer. A typical choice would be 4.
+      @return the requested set of pixel number ranges  */
+  public RangeSet queryPolygonInclusive (Pointing[] vertex, int fact)
+    throws Exception
+    { return queryPolygonInternal (vertex, fact); }
+
+  private void check_pixel (int o, int omax, int zone,
+    RangeSet pixset, long pix, pstack stk, boolean inclusive)
+    {
+    if (zone==0) return;
+
+    if (o<order)
+      {
+      if (zone>=3) // output all subpixels
+        {
+        int sdist=2*(order-o); // the "bit-shift distance" between map orders
+        pixset.append(pix<<sdist,((pix+1)<<sdist));
+        }
+      else // (zone>=1)
+        for (int i=0; i<4; ++i)
+          stk.push(4*pix+3-i,o+1); // add children
+      }
+    else if (o>order) // this implies that inclusive==true
+      {
+      if (zone>=2) // pixel center in shape
+        {
+        pixset.append(pix>>>(2*(o-order))); // output the parent pixel at order
+        stk.popToMark(); // unwind the stack
+        }
+      else // (zone>=1): pixel center in safety range
+        {
+        if (o<omax) // check sublevels
+          for (int i=0; i<4; ++i) // add children in reverse order
+            stk.push(4*pix+3-i,o+1); // add children
+        else // at resolution limit
+          {
+          pixset.append(pix>>>(2*(o-order)));// output the parent pixel at order
+          stk.popToMark(); // unwind the stack
+          }
+        }
+      }
+    else // o==order
+      {
+      if (zone>=2)
+        pixset.append(pix);
+      else if (inclusive) // and (zone>=1)
+        {
+        if (order<omax) // check sublevels
+          {
+          stk.mark(); // remember current stack position
+          for (int i=0; i<4; ++i) // add children in reverse order
+            stk.push(4*pix+3-i,o+1); // add children
+          }
+        else // at resolution limit
+          pixset.append(pix); // output the pixel
+        }
+      }
+    }
+
+  /** Compute ring index from pixel number.
+      Works in both RING and NESTED schemes
+      @param pix pixel number
+      @return ring index (1 to 4Nside-1) */
+  public long pix2ring (long pix)
+    {
+    if (scheme==Scheme.RING)
+      {
+      if (pix<ncap) // North Polar cap
+        return (1+HealpixUtils.isqrt(1+2*pix))>>>1; // counted from North pole
+      else if (pix<(npix-ncap)) // Equatorial region
+        return (pix-ncap)/nl4 + nside; // counted from North pole
+      else // South Polar cap
+        return nl4-((1+HealpixUtils.isqrt(2*(npix-pix)-1))>>>1);
+      }
+    else
+      {
+      Xyf xyf = nest2xyf(pix);
+      return ((long)(jrll[xyf.face])<<order) - xyf.ix - xyf.iy - 1;
+      }
+    }
+
+  /** Returns a set of points along the boundary of the given pixel.
+    * Step 1 gives 4 points on the corners. The first point corresponds
+    * to the northernmost corner, the subsequent points follow the pixel
+    * boundary through west, south and east corners.
+    *
+    * @param pix pixel index number
+    * @param step the number of returned points is 4*step
+    * @return {@link Vec3} for each point
+    * @throws Exception
+    */
+  public Vec3[] boundaries(long pix, int step) throws Exception
+    {
+    HealpixUtils.check(step>0,"step must be positive");
+    Vec3[] points = new Vec3[4*step];
+    Xyf xyf = pix2xyf(pix);
+    double dc=0.5/nside;
+    double xc=(xyf.ix+0.5)/nside, yc=(xyf.iy+0.5)/nside;
+    double d = 1./(step*nside);
+    for (int i=0; i<step; ++i)
+      {
+      points[i       ]=new Fxyf(xc+dc-i*d, yc+dc, xyf.face).toVec3();
+      points[i+  step]=new Fxyf(xc-dc, yc+dc-i*d, xyf.face).toVec3();
+      points[i+2*step]=new Fxyf(xc-dc+i*d, yc-dc, xyf.face).toVec3();
+      points[i+3*step]=new Fxyf(xc+dc, yc-dc+i*d, xyf.face).toVec3();
+      }
+    return points;
+    }
+  }
diff -Nru healpix-java-3.40/src/java/src/healpix/essentials/HealpixMapDouble.java healpix-java-3.50/src/java/src/healpix/essentials/HealpixMapDouble.java
--- healpix-java-3.40/src/java/src/healpix/essentials/HealpixMapDouble.java	1969-12-31 19:00:00.000000000 -0500
+++ healpix-java-3.50/src/java/src/healpix/essentials/HealpixMapDouble.java	2014-10-24 05:23:50.000000000 -0400
@@ -0,0 +1,227 @@
+/*
+ *  This file is part of Healpix Java.
+ *
+ *  This code 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 code 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 code; 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.sourceforge.net
+ */
+
+package healpix.essentials;
+
+import java.util.Arrays;
+
+/** Class representing a full HEALPix map containing double values.
+    This class is conceptually very similar the the Healpix_Map<double>
+    class of Healpix_cxx.
+
+    @copyright 2011,2012 Max-Planck-Society
+    @author Martin Reinecke */
+public class HealpixMapDouble extends HealpixBase
+  {
+  private double[] data;
+
+  public static final double undef=-1.6375e30;
+
+  public HealpixMapDouble() throws Exception
+    { this(1,Scheme.NESTED); }
+  public HealpixMapDouble(long nside_in, Scheme scheme_in) throws Exception
+    {
+    super(nside_in,scheme_in);
+    HealpixUtils.check(nside<=(1<<13),"resolution too high");
+    data=new double[(int)getNpix()];
+    }
+  public HealpixMapDouble(double[] data_in, Scheme scheme_in) throws Exception
+    {
+    super(npix2Nside(data_in.length),scheme_in);
+    HealpixUtils.check(nside<=(1<<13),"resolution too high");
+    data=data_in;
+    }
+
+  /** Adjusts the object to nside_in.
+      @param nside_in the new Nside parameter */
+  public void setNside (long nside_in) throws Exception
+    {
+    if (nside_in!=nside)
+      {
+      super.setNside(nside_in);
+      HealpixUtils.check(nside<=(1<<13),"resolution too high");
+      data=new double[(int)getNpix()];
+      }
+    }
+
+  /** Adjusts the object to nside_in and scheme_in.
+      @param nside_in the new Nside parameter
+      @param scheme_in the new ordering scheme */
+  public void setNsideAndScheme (long nside_in, Scheme scheme_in)
+    throws Exception
+    {
+    super.setNsideAndScheme(nside_in,scheme_in);
+    HealpixUtils.check(nside<=(1<<13),"resolution too high");
+    data=new double[(int)getNpix()];
+    }
+
+  /** Adjusts the object to scheme_in, and sets pixel data to data_in.
+      @param data_in pixel data; must have a valid length (12*nside^2)
+      @param scheme_in the new ordering scheme */
+  public void setDataAndScheme(double[] data_in, Scheme scheme_in)
+    throws Exception
+    {
+    super.setNsideAndScheme(npix2Nside(data_in.length),scheme_in);
+    data=data_in;
+    }
+
+  /** Sets all map pixel to a specific value.
+      @param val pixel value to use */
+  public void fill(double val)
+    { Arrays.fill(data,val); }
+
+  /** Converts the map from NESTED to RING scheme or vice versa.
+      This operation is done in-place, i.e. it does not require additional
+      memory. */
+  public void swapScheme() throws Exception
+    {
+    HealpixUtils.check((order>=0) && (order<=13),
+      "swapping not supported for this Nside");
+    for (int m=0; m<swap_cycle[order].length; ++m)
+      {
+      int istart = swap_cycle[order][m];
+
+      double pixbuf = data[istart];
+      long iold = istart,
+           inew = (scheme==Scheme.RING) ? nest2ring(istart) : ring2nest(istart);
+      while (inew != istart)
+        {
+        data[(int)iold] = data[(int)inew];
+        iold = inew;
+        inew = (scheme==Scheme.RING) ? nest2ring(inew) : ring2nest(inew);
+        }
+      data[(int)iold] = pixbuf;
+      }
+    scheme = (scheme==Scheme.RING) ? Scheme.NESTED : Scheme.RING;
+    }
+
+  /** Returns the value of the pixel with a given index.
+      @param ipix index of the requested pixel
+      @return pixel value */
+  public double getPixel(int ipix)
+    { return data[ipix]; }
+  /** Returns the value of the pixel with a given index.
+      @param ipix index of the requested pixel
+      @return pixel value */
+  public double getPixel(long ipix)
+    { return data[(int)ipix]; }
+  /** Sets the value of a specific pixel.
+      @param ipix index of the pixel
+      @param val new value for the pixel */
+  public void setPixel(int ipix, double val)
+    { data[ipix] = val; }
+  /** Sets the value of a specific pixel.
+      @param ipix index of the pixel
+      @param val new value for the pixel */
+  public void setPixel(long ipix, double val)
+    { data[(int)ipix] = val; }
+
+  /** Returns the array containing all map pixels.
+      @return the map array */
+  public double[] getData()
+    { return data; }
+
+  /** Imports the map "orig" to this object, adjusting pixel ordering.
+      @param orig map to import */
+  public void importNograde (HealpixMapDouble orig) throws Exception
+    {
+    HealpixUtils.check (nside==orig.nside,
+      "importNograde: maps have different nside");
+    if (orig.scheme == scheme)
+      System.arraycopy(orig.data,0,data,0,(int)npix);
+    else
+      for (int m=0; m<npix; ++m)
+        data[scheme==Scheme.NESTED ? (int)ring2nest(m) : (int)nest2ring(m)]
+          = orig.data[m];
+    }
+  /** Imports the map "orig" to this object, adjusting pixel ordering
+      and increasing resolution.
+      @param orig map to import */
+  public void importUpgrade (HealpixMapDouble orig) throws Exception
+    {
+    HealpixUtils.check(nside>orig.nside,"importUpgrade: this is no upgrade");
+    int fact = (int)(nside/orig.nside);
+    HealpixUtils.check(nside==orig.nside*fact,
+      "the larger Nside must be a multiple of the smaller one");
+
+    for (int m=0; m<orig.npix; ++m)
+      {
+      Xyf xyf = orig.pix2xyf(m);
+      int x=xyf.ix, y=xyf.iy, f=xyf.face;
+      for (int j=fact*y; j<fact*(y+1); ++j)
+        for (int i=fact*x; i<fact*(x+1); ++i)
+          {
+          long mypix = xyf2pix(i,j,f);
+          data[(int)mypix] = orig.data[m];
+          }
+      }
+    }
+  /** Imports the map "orig" to this object, adjusting pixel ordering
+      and reducing resolution.
+      @param orig map to import
+      @param pessimistic if true, set a pixel to undefined if at least one the
+        original subpixels was undefined; otherwise only set it to undefined if
+        all original subpixels were undefined. */
+  public void importDegrade (HealpixMapDouble orig, boolean pessimistic)
+    throws Exception
+    {
+    HealpixUtils.check(nside<orig.nside,"importDegrade: this is no degrade");
+    int fact = (int)(orig.nside/nside);
+    HealpixUtils.check(orig.nside==nside*fact,
+      "the larger Nside must be a multiple of the smaller one");
+
+    int minhits = pessimistic ? fact*fact : 1;
+    for (int m=0; m<npix; ++m)
+      {
+      Xyf xyf = pix2xyf(m);
+      int x=xyf.ix, y=xyf.iy, f=xyf.face;
+      int hits = 0;
+      double sum = 0;
+      for (int j=fact*y; j<fact*(y+1); ++j)
+        for (int i=fact*x; i<fact*(x+1); ++i)
+          {
+          int opix = (int)orig.xyf2pix(i,j,f);
+          if (!HealpixUtils.approx(orig.data[opix],undef,1e-5))
+            {
+            ++hits;
+            sum += orig.data[opix];
+            }
+          }
+      data[m] = (hits<minhits) ? undef : (sum/hits);
+      }
+    }
+  /** Imports the map "orig" to this object, adjusting pixel ordering
+      and resolution if necessary.
+      @param orig map to import
+      @param pessimistic only used when resolution must be reduced: if true,
+        set a pixel to undefined if at least one the original subpixels
+        was undefined; otherwise only set it to undefined if all original
+        subpixels were undefined. */
+  public void importGeneral (HealpixMapDouble orig, boolean pessimistic)
+    throws Exception
+    {
+    if (orig.nside==nside)
+      importNograde(orig);
+    else if (orig.nside<nside) // upgrading
+      importUpgrade(orig);
+    else
+      importDegrade(orig,pessimistic);
+    }
+  }
diff -Nru healpix-java-3.40/src/java/src/healpix/essentials/HealpixMapFloat.java healpix-java-3.50/src/java/src/healpix/essentials/HealpixMapFloat.java
--- healpix-java-3.40/src/java/src/healpix/essentials/HealpixMapFloat.java	1969-12-31 19:00:00.000000000 -0500
+++ healpix-java-3.50/src/java/src/healpix/essentials/HealpixMapFloat.java	2014-10-24 05:23:50.000000000 -0400
@@ -0,0 +1,227 @@
+/*
+ *  This file is part of Healpix Java.
+ *
+ *  This code 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 code 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 code; 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.sourceforge.net
+ */
+
+package healpix.essentials;
+
+import java.util.Arrays;
+
+/** Class representing a full HEALPix map containing float values.
+    This class is conceptually very similar the the Healpix_Map<float>
+    class of Healpix_cxx.
+
+    @copyright 2011,2012 Max-Planck-Society
+    @author Martin Reinecke */
+public class HealpixMapFloat extends HealpixBase
+  {
+  private float[] data;
+
+  public static final float undef=(float)(-1.6375e30);
+
+  public HealpixMapFloat() throws Exception
+    { this(1,Scheme.NESTED); }
+  public HealpixMapFloat(long nside_in, Scheme scheme_in) throws Exception
+    {
+    super(nside_in,scheme_in);
+    HealpixUtils.check(nside<=(1<<13),"resolution too high");
+    data=new float[(int)getNpix()];
+    }
+  public HealpixMapFloat(float[] data_in, Scheme scheme_in) throws Exception
+    {
+    super(npix2Nside(data_in.length),scheme_in);
+    HealpixUtils.check(nside<=(1<<13),"resolution too high");
+    data=data_in;
+    }
+
+  /** Adjusts the object to nside_in.
+      @param nside_in the new Nside parameter */
+  public void setNside (long nside_in) throws Exception
+    {
+    if (nside_in!=nside)
+      {
+      super.setNside(nside_in);
+      HealpixUtils.check(nside<=(1<<13),"resolution too high");
+      data=new float[(int)getNpix()];
+      }
+    }
+
+  /** Adjusts the object to nside_in and scheme_in.
+      @param nside_in the new Nside parameter
+      @param scheme_in the new ordering scheme */
+  public void setNsideAndScheme (long nside_in, Scheme scheme_in)
+    throws Exception
+    {
+    super.setNsideAndScheme(nside_in,scheme_in);
+    HealpixUtils.check(nside<=(1<<13),"resolution too high");
+    data=new float[(int)getNpix()];
+    }
+
+  /** Adjusts the object to scheme_in, and sets pixel data to data_in.
+      @param data_in pixel data; must have a valid length (12*nside^2)
+      @param scheme_in the new ordering scheme */
+  public void setDataAndScheme(float[] data_in, Scheme scheme_in)
+    throws Exception
+    {
+    super.setNsideAndScheme(npix2Nside(data_in.length),scheme_in);
+    data=data_in;
+    }
+
+  /** Sets all map pixel to a specific value.
+      @param val pixel value to use */
+  public void fill(float val)
+    { Arrays.fill(data,val); }
+
+  /** Converts the map from NESTED to RING scheme or vice versa.
+      This operation is done in-place, i.e. it does not require additional
+      memory. */
+  public void swapScheme() throws Exception
+    {
+    HealpixUtils.check((order>=0) && (order<=13),
+      "swapping not supported for this Nside");
+    for (int m=0; m<swap_cycle[order].length; ++m)
+      {
+      int istart = swap_cycle[order][m];
+
+      float pixbuf = data[istart];
+      long iold = istart,
+           inew = (scheme==Scheme.RING) ? nest2ring(istart) : ring2nest(istart);
+      while (inew != istart)
+        {
+        data[(int)iold] = data[(int)inew];
+        iold = inew;
+        inew = (scheme==Scheme.RING) ? nest2ring(inew) : ring2nest(inew);
+        }
+      data[(int)iold] = pixbuf;
+      }
+    scheme = (scheme==Scheme.RING) ? Scheme.NESTED : Scheme.RING;
+    }
+
+  /** Returns the value of the pixel with a given index.
+      @param ipix index of the requested pixel
+      @return pixel value */
+  public float getPixel(int ipix)
+    { return data[ipix]; }
+  /** Returns the value of the pixel with a given index.
+      @param ipix index of the requested pixel
+      @return pixel value */
+  public float getPixel(long ipix)
+    { return data[(int)ipix]; }
+  /** Sets the value of a specific pixel.
+      @param ipix index of the pixel
+      @param val new value for the pixel */
+  public void setPixel(int ipix, float val)
+    { data[ipix] = val; }
+  /** Sets the value of a specific pixel.
+      @param ipix index of the pixel
+      @param val new value for the pixel */
+  public void setPixel(long ipix, float val)
+    { data[(int)ipix] = val; }
+
+  /** Returns the array containing all map pixels.
+      @return the map array */
+  public float[] getData()
+    { return data; }
+
+  /** Imports the map "orig" to this object, adjusting pixel ordering.
+      @param orig map to import */
+  public void importNograde (HealpixMapFloat orig) throws Exception
+    {
+    HealpixUtils.check (nside==orig.nside,
+      "importNograde: maps have different nside");
+    if (orig.scheme == scheme)
+      System.arraycopy(orig.data,0,data,0,(int)npix);
+    else
+      for (int m=0; m<npix; ++m)
+        data[scheme==Scheme.NESTED ? (int)ring2nest(m) : (int)nest2ring(m)]
+          = orig.data[m];
+    }
+  /** Imports the map "orig" to this object, adjusting pixel ordering
+      and increasing resolution.
+      @param orig map to import */
+  public void importUpgrade (HealpixMapFloat orig) throws Exception
+    {
+    HealpixUtils.check(nside>orig.nside,"importUpgrade: this is no upgrade");
+    int fact = (int)(nside/orig.nside);
+    HealpixUtils.check(nside==orig.nside*fact,
+      "the larger Nside must be a multiple of the smaller one");
+
+    for (int m=0; m<orig.npix; ++m)
+      {
+      Xyf xyf = orig.pix2xyf(m);
+      int x=xyf.ix, y=xyf.iy, f=xyf.face;
+      for (int j=fact*y; j<fact*(y+1); ++j)
+        for (int i=fact*x; i<fact*(x+1); ++i)
+          {
+          long mypix = xyf2pix(i,j,f);
+          data[(int)mypix] = orig.data[m];
+          }
+      }
+    }
+  /** Imports the map "orig" to this object, adjusting pixel ordering
+      and reducing resolution.
+      @param orig map to import
+      @param pessimistic if true, set a pixel to undefined if at least one the
+        original subpixels was undefined; otherwise only set it to undefined if
+        all original subpixels were undefined. */
+  public void importDegrade (HealpixMapFloat orig, boolean pessimistic)
+    throws Exception
+    {
+    HealpixUtils.check(nside<orig.nside,"importDegrade: this is no degrade");
+    int fact = (int)(orig.nside/nside);
+    HealpixUtils.check(orig.nside==nside*fact,
+      "the larger Nside must be a multiple of the smaller one");
+
+    int minhits = pessimistic ? fact*fact : 1;
+    for (int m=0; m<npix; ++m)
+      {
+      Xyf xyf = pix2xyf(m);
+      int x=xyf.ix, y=xyf.iy, f=xyf.face;
+      int hits = 0;
+      double sum = 0;
+      for (int j=fact*y; j<fact*(y+1); ++j)
+        for (int i=fact*x; i<fact*(x+1); ++i)
+          {
+          int opix = (int)orig.xyf2pix(i,j,f);
+          if (!HealpixUtils.approx(orig.data[opix],undef,1e-5))
+            {
+            ++hits;
+            sum += orig.data[opix];
+            }
+          }
+      data[m] = (hits<minhits) ? undef : (float) (sum/hits);
+      }
+    }
+  /** Imports the map "orig" to this object, adjusting pixel ordering
+      and resolution if necessary.
+      @param orig map to import
+      @param pessimistic only used when resolution must be reduced: if true,
+        set a pixel to undefined if at least one the original subpixels
+        was undefined; otherwise only set it to undefined if all original
+        subpixels were undefined. */
+  public void importGeneral (HealpixMapFloat orig, boolean pessimistic)
+    throws Exception
+    {
+    if (orig.nside==nside)
+      importNograde(orig);
+    else if (orig.nside<nside) // upgrading
+      importUpgrade(orig);
+    else
+      importDegrade(orig,pessimistic);
+    }
+  }
diff -Nru healpix-java-3.40/src/java/src/healpix/essentials/HealpixMap.tmpl healpix-java-3.50/src/java/src/healpix/essentials/HealpixMap.tmpl
--- healpix-java-3.40/src/java/src/healpix/essentials/HealpixMap.tmpl	1969-12-31 19:00:00.000000000 -0500
+++ healpix-java-3.50/src/java/src/healpix/essentials/HealpixMap.tmpl	2014-10-24 05:23:50.000000000 -0400
@@ -0,0 +1,227 @@
+/*
+ *  This file is part of Healpix Java.
+ *
+ *  This code 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 code 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 code; 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.sourceforge.net
+ */
+
+package healpix.essentials;
+
+import java.util.Arrays;
+
+/** Class representing a full HEALPix map containing <type> values.
+    This class is conceptually very similar the the Healpix_Map<<type>>
+    class of Healpix_cxx.
+
+    @copyright 2011,2012 Max-Planck-Society
+    @author Martin Reinecke */
+public class HealpixMap<Type> extends HealpixBase
+  {
+  private <type>[] data;
+
+  public static final <type> undef=(<type>)(-1.6375e30);
+
+  public HealpixMap<Type>() throws Exception
+    { this(1,Scheme.NESTED); }
+  public HealpixMap<Type>(long nside_in, Scheme scheme_in) throws Exception
+    {
+    super(nside_in,scheme_in);
+    HealpixUtils.check(nside<=(1<<13),"resolution too high");
+    data=new <type>[(int)getNpix()];
+    }
+  public HealpixMap<Type>(<type>[] data_in, Scheme scheme_in) throws Exception
+    {
+    super(npix2Nside(data_in.length),scheme_in);
+    HealpixUtils.check(nside<=(1<<13),"resolution too high");
+    data=data_in;
+    }
+
+  /** Adjusts the object to nside_in.
+      @param nside_in the new Nside parameter */
+  public void setNside (long nside_in) throws Exception
+    {
+    if (nside_in!=nside)
+      {
+      super.setNside(nside_in);
+      HealpixUtils.check(nside<=(1<<13),"resolution too high");
+      data=new <type>[(int)getNpix()];
+      }
+    }
+
+  /** Adjusts the object to nside_in and scheme_in.
+      @param nside_in the new Nside parameter
+      @param scheme_in the new ordering scheme */
+  public void setNsideAndScheme (long nside_in, Scheme scheme_in)
+    throws Exception
+    {
+    super.setNsideAndScheme(nside_in,scheme_in);
+    HealpixUtils.check(nside<=(1<<13),"resolution too high");
+    data=new <type>[(int)getNpix()];
+    }
+
+  /** Adjusts the object to scheme_in, and sets pixel data to data_in.
+      @param data_in pixel data; must have a valid length (12*nside^2)
+      @param scheme_in the new ordering scheme */
+  public void setDataAndScheme(<type>[] data_in, Scheme scheme_in)
+    throws Exception
+    {
+    super.setNsideAndScheme(npix2Nside(data_in.length),scheme_in);
+    data=data_in;
+    }
+
+  /** Sets all map pixel to a specific value.
+      @param val pixel value to use */
+  public void fill(<type> val)
+    { Arrays.fill(data,val); }
+
+  /** Converts the map from NESTED to RING scheme or vice versa.
+      This operation is done in-place, i.e. it does not require additional
+      memory. */
+  public void swapScheme() throws Exception
+    {
+    HealpixUtils.check((order>=0) && (order<=13),
+      "swapping not supported for this Nside");
+    for (int m=0; m<swap_cycle[order].length; ++m)
+      {
+      int istart = swap_cycle[order][m];
+
+      <type> pixbuf = data[istart];
+      long iold = istart,
+           inew = (scheme==Scheme.RING) ? nest2ring(istart) : ring2nest(istart);
+      while (inew != istart)
+        {
+        data[(int)iold] = data[(int)inew];
+        iold = inew;
+        inew = (scheme==Scheme.RING) ? nest2ring(inew) : ring2nest(inew);
+        }
+      data[(int)iold] = pixbuf;
+      }
+    scheme = (scheme==Scheme.RING) ? Scheme.NESTED : Scheme.RING;
+    }
+
+  /** Returns the value of the pixel with a given index.
+      @param ipix index of the requested pixel
+      @return pixel value */
+  public <type> getPixel(int ipix)
+    { return data[ipix]; }
+  /** Returns the value of the pixel with a given index.
+      @param ipix index of the requested pixel
+      @return pixel value */
+  public <type> getPixel(long ipix)
+    { return data[(int)ipix]; }
+  /** Sets the value of a specific pixel.
+      @param ipix index of the pixel
+      @param val new value for the pixel */
+  public void setPixel(int ipix, <type> val)
+    { data[ipix] = val; }
+  /** Sets the value of a specific pixel.
+      @param ipix index of the pixel
+      @param val new value for the pixel */
+  public void setPixel(long ipix, <type> val)
+    { data[(int)ipix] = val; }
+
+  /** Returns the array containing all map pixels.
+      @return the map array */
+  public <type>[] getData()
+    { return data; }
+
+  /** Imports the map "orig" to this object, adjusting pixel ordering.
+      @param orig map to import */
+  public void importNograde (HealpixMap<Type> orig) throws Exception
+    {
+    HealpixUtils.check (nside==orig.nside,
+      "importNograde: maps have different nside");
+    if (orig.scheme == scheme)
+      System.arraycopy(orig.data,0,data,0,(int)npix);
+    else
+      for (int m=0; m<npix; ++m)
+        data[scheme==Scheme.NESTED ? (int)ring2nest(m) : (int)nest2ring(m)]
+          = orig.data[m];
+    }
+  /** Imports the map "orig" to this object, adjusting pixel ordering
+      and increasing resolution.
+      @param orig map to import */
+  public void importUpgrade (HealpixMap<Type> orig) throws Exception
+    {
+    HealpixUtils.check(nside>orig.nside,"importUpgrade: this is no upgrade");
+    int fact = (int)(nside/orig.nside);
+    HealpixUtils.check(nside==orig.nside*fact,
+      "the larger Nside must be a multiple of the smaller one");
+
+    for (int m=0; m<orig.npix; ++m)
+      {
+      Xyf xyf = orig.pix2xyf(m);
+      int x=xyf.ix, y=xyf.iy, f=xyf.face;
+      for (int j=fact*y; j<fact*(y+1); ++j)
+        for (int i=fact*x; i<fact*(x+1); ++i)
+          {
+          long mypix = xyf2pix(i,j,f);
+          data[(int)mypix] = orig.data[m];
+          }
+      }
+    }
+  /** Imports the map "orig" to this object, adjusting pixel ordering
+      and reducing resolution.
+      @param orig map to import
+      @param pessimistic if true, set a pixel to undefined if at least one the
+        original subpixels was undefined; otherwise only set it to undefined if
+        all original subpixels were undefined. */
+  public void importDegrade (HealpixMap<Type> orig, boolean pessimistic)
+    throws Exception
+    {
+    HealpixUtils.check(nside<orig.nside,"importDegrade: this is no degrade");
+    int fact = (int)(orig.nside/nside);
+    HealpixUtils.check(orig.nside==nside*fact,
+      "the larger Nside must be a multiple of the smaller one");
+
+    int minhits = pessimistic ? fact*fact : 1;
+    for (int m=0; m<npix; ++m)
+      {
+      Xyf xyf = pix2xyf(m);
+      int x=xyf.ix, y=xyf.iy, f=xyf.face;
+      int hits = 0;
+      double sum = 0;
+      for (int j=fact*y; j<fact*(y+1); ++j)
+        for (int i=fact*x; i<fact*(x+1); ++i)
+          {
+          int opix = (int)orig.xyf2pix(i,j,f);
+          if (!HealpixUtils.approx(orig.data[opix],undef,1e-5))
+            {
+            ++hits;
+            sum += orig.data[opix];
+            }
+          }
+      data[m] = (hits<minhits) ? undef : (<type>) (sum/hits);
+      }
+    }
+  /** Imports the map "orig" to this object, adjusting pixel ordering
+      and resolution if necessary.
+      @param orig map to import
+      @param pessimistic only used when resolution must be reduced: if true,
+        set a pixel to undefined if at least one the original subpixels
+        was undefined; otherwise only set it to undefined if all original
+        subpixels were undefined. */
+  public void importGeneral (HealpixMap<Type> orig, boolean pessimistic)
+    throws Exception
+    {
+    if (orig.nside==nside)
+      importNograde(orig);
+    else if (orig.nside<nside) // upgrading
+      importUpgrade(orig);
+    else
+      importDegrade(orig,pessimistic);
+    }
+  }
diff -Nru healpix-java-3.40/src/java/src/healpix/essentials/HealpixProc.java healpix-java-3.50/src/java/src/healpix/essentials/HealpixProc.java
--- healpix-java-3.40/src/java/src/healpix/essentials/HealpixProc.java	1969-12-31 19:00:00.000000000 -0500
+++ healpix-java-3.50/src/java/src/healpix/essentials/HealpixProc.java	2013-04-03 09:15:40.000000000 -0400
@@ -0,0 +1,127 @@
+/*
+ *  This file is part of Healpix Java.
+ *
+ *  This code 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 code 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 code; 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.sourceforge.net
+ */
+
+package healpix.essentials;
+
+/** Procedural interface to the {@link HealpixBase} functionality.
+    This class is intended for users who prefer a procedural (instead of
+    object-oriented) interface to the HEALPix functionality. It should make
+    transition from packages like PixTools easier.
+
+    @copyright 2012 Max-Planck-Society
+    @author Martin Reinecke */
+public abstract class HealpixProc extends HealpixBase
+  {
+  static final HealpixBase[] bn=new HealpixBase[HealpixBase.order_max+1],
+                             br=new HealpixBase[HealpixBase.order_max+1];
+  static final double[] mpr =new double[HealpixBase.order_max+1],
+                        cmpr=new double[HealpixBase.order_max+1],
+                        smpr=new double[HealpixBase.order_max+1];
+
+  static
+    {
+    try {
+      for (int i=0; i<=HealpixBase.order_max; ++i)
+        {
+        bn[i]=new HealpixBase(1L<<i, Scheme.NESTED);
+        br[i]=new HealpixBase(1L<<i, Scheme.RING);
+        mpr[i]=bn[i].maxPixrad();
+        cmpr[i]=FastMath.cos(mpr[i]);
+        smpr[i]=FastMath.sin(mpr[i]);
+        }
+      }
+    catch (Exception Ex) {/*doesn't happen*/}
+    }
+
+  private HealpixProc() {} // this class should not be instantiated
+
+  public static double maxPixrad (int order)
+    { return bn[order].maxPixrad(); }
+
+  public static long ang2pixNest (int order, Pointing ptg) throws Exception
+    { return bn[order].ang2pix(ptg); }
+  public static long ang2pixRing (int order, Pointing ptg) throws Exception
+    { return br[order].ang2pix(ptg); }
+
+  public static Pointing pix2angNest (int order, long pix) throws Exception
+    { return bn[order].pix2ang(pix); }
+  public static Pointing pix2angRing (int order, long pix) throws Exception
+    { return br[order].pix2ang(pix); }
+
+  public static long vec2pixNest (int order, Vec3 vec) throws Exception
+    { return bn[order].vec2pix(vec); }
+  public static long vec2pixRing (int order, Vec3 vec) throws Exception
+    { return br[order].vec2pix(vec); }
+
+  public static Vec3 pix2vecNest (int order, long pix) throws Exception
+    { return bn[order].pix2vec(pix); }
+  public static Vec3 pix2vecRing (int order, long pix) throws Exception
+    { return br[order].pix2vec(pix); }
+
+  public static long ring2nest (int order, long pix) throws Exception
+    { return bn[order].ring2nest(pix); }
+  public static long nest2ring (int order, long pix) throws Exception
+    { return bn[order].nest2ring(pix); }
+
+  public static long[] neighboursNest (int order, long pix) throws Exception
+    { return bn[order].neighbours(pix); }
+  public static long[] neighboursRing (int order, long pix) throws Exception
+    { return br[order].neighbours(pix); }
+
+  public static Vec3[] boundariesNest(int order, long pix, int step)
+    throws Exception
+    { return bn[order].boundaries(pix,step); }
+  public static Vec3[] boundariesRing(int order, long pix, int step)
+    throws Exception
+    { return br[order].boundaries(pix,step); }
+
+  public static RangeSet queryDiscNest(int order, Pointing ptg, double radius)
+    throws Exception
+    { return bn[order].queryDisc(ptg,radius); }
+  public static RangeSet queryDiscRing(int order, Pointing ptg, double radius)
+    throws Exception
+    { return br[order].queryDisc(ptg,radius); }
+  public static RangeSet queryDiscInclusiveNest(int order, Pointing ptg,
+    double radius, int fact) throws Exception
+    { return bn[order].queryDiscInclusive(ptg,radius,fact); }
+  public static RangeSet queryDiscInclusiveRing(int order, Pointing ptg,
+    double radius, int fact) throws Exception
+    { return br[order].queryDiscInclusive(ptg,radius,fact); }
+
+  public static RangeSet queryPolygonNest(int order, Pointing[] vertex)
+    throws Exception
+    { return bn[order].queryPolygon(vertex); }
+  public static RangeSet queryPolygonRing(int order, Pointing[] vertex)
+    throws Exception
+    { return br[order].queryPolygon(vertex); }
+  public static RangeSet queryPolygonInclusiveNest(int order, Pointing[] vertex,
+    int fact) throws Exception
+    { return bn[order].queryPolygonInclusive(vertex,fact); }
+  public static RangeSet queryPolygonInclusiveRing(int order, Pointing[] vertex,
+    int fact) throws Exception
+    { return br[order].queryPolygonInclusive(vertex,fact); }
+
+  public static RangeSet queryStripNest(int order, double theta1, double theta2,
+    boolean inclusive) throws Exception
+    { return bn[order].queryStrip(theta1,theta2,inclusive); }
+  public static RangeSet queryStripRing(int order, double theta1, double theta2,
+    boolean inclusive) throws Exception
+    { return br[order].queryStrip(theta1,theta2,inclusive); }
+  };
diff -Nru healpix-java-3.40/src/java/src/healpix/essentials/HealpixTables.java healpix-java-3.50/src/java/src/healpix/essentials/HealpixTables.java
--- healpix-java-3.40/src/java/src/healpix/essentials/HealpixTables.java	1969-12-31 19:00:00.000000000 -0500
+++ healpix-java-3.50/src/java/src/healpix/essentials/HealpixTables.java	2016-03-10 10:13:56.000000000 -0500
@@ -0,0 +1,116 @@
+/*
+ *  This file is part of Healpix Java.
+ *
+ *  This code 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 code 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 code; 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.sourceforge.net
+ */
+
+package healpix.essentials;
+
+import java.io.Serializable;
+
+/** Various data tables needed by the {@link HealpixBase} class.
+
+    @copyright 2011, 2012 Max-Planck-Society
+    @author Martin Reinecke */
+public class HealpixTables implements Serializable
+  {
+  static final protected short[] ctab={
+  0,1,256,257,2,3,258,259,512,513,768,769,514,515,770,771,4,5,260,261,6,7,262,
+  263,516,517,772,773,518,519,774,775,1024,1025,1280,1281,1026,1027,1282,1283,
+  1536,1537,1792,1793,1538,1539,1794,1795,1028,1029,1284,1285,1030,1031,1286,
+  1287,1540,1541,1796,1797,1542,1543,1798,1799,8,9,264,265,10,11,266,267,520,
+  521,776,777,522,523,778,779,12,13,268,269,14,15,270,271,524,525,780,781,526,
+  527,782,783,1032,1033,1288,1289,1034,1035,1290,1291,1544,1545,1800,1801,1546,
+  1547,1802,1803,1036,1037,1292,1293,1038,1039,1294,1295,1548,1549,1804,1805,
+  1550,1551,1806,1807,2048,2049,2304,2305,2050,2051,2306,2307,2560,2561,2816,
+  2817,2562,2563,2818,2819,2052,2053,2308,2309,2054,2055,2310,2311,2564,2565,
+  2820,2821,2566,2567,2822,2823,3072,3073,3328,3329,3074,3075,3330,3331,3584,
+  3585,3840,3841,3586,3587,3842,3843,3076,3077,3332,3333,3078,3079,3334,3335,
+  3588,3589,3844,3845,3590,3591,3846,3847,2056,2057,2312,2313,2058,2059,2314,
+  2315,2568,2569,2824,2825,2570,2571,2826,2827,2060,2061,2316,2317,2062,2063,
+  2318,2319,2572,2573,2828,2829,2574,2575,2830,2831,3080,3081,3336,3337,3082,
+  3083,3338,3339,3592,3593,3848,3849,3594,3595,3850,3851,3084,3085,3340,3341,
+  3086,3087,3342,3343,3596,3597,3852,3853,3598,3599,3854,3855 };
+  static final protected short[] utab={
+  0,1,4,5,16,17,20,21,64,65,68,69,80,81,84,85,256,257,260,261,272,273,276,277,
+  320,321,324,325,336,337,340,341,1024,1025,1028,1029,1040,1041,1044,1045,1088,
+  1089,1092,1093,1104,1105,1108,1109,1280,1281,1284,1285,1296,1297,1300,1301,
+  1344,1345,1348,1349,1360,1361,1364,1365,4096,4097,4100,4101,4112,4113,4116,
+  4117,4160,4161,4164,4165,4176,4177,4180,4181,4352,4353,4356,4357,4368,4369,
+  4372,4373,4416,4417,4420,4421,4432,4433,4436,4437,5120,5121,5124,5125,5136,
+  5137,5140,5141,5184,5185,5188,5189,5200,5201,5204,5205,5376,5377,5380,5381,
+  5392,5393,5396,5397,5440,5441,5444,5445,5456,5457,5460,5461,16384,16385,16388,
+  16389,16400,16401,16404,16405,16448,16449,16452,16453,16464,16465,16468,16469,
+  16640,16641,16644,16645,16656,16657,16660,16661,16704,16705,16708,16709,16720,
+  16721,16724,16725,17408,17409,17412,17413,17424,17425,17428,17429,17472,17473,
+  17476,17477,17488,17489,17492,17493,17664,17665,17668,17669,17680,17681,17684,
+  17685,17728,17729,17732,17733,17744,17745,17748,17749,20480,20481,20484,20485,
+  20496,20497,20500,20501,20544,20545,20548,20549,20560,20561,20564,20565,20736,
+  20737,20740,20741,20752,20753,20756,20757,20800,20801,20804,20805,20816,20817,
+  20820,20821,21504,21505,21508,21509,21520,21521,21524,21525,21568,21569,21572,
+  21573,21584,21585,21588,21589,21760,21761,21764,21765,21776,21777,21780,21781,
+  21824,21825,21828,21829,21840,21841,21844,21845 };
+
+  // coordinate of the lowest corner of each face
+  static final protected byte[] jrll = { 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4 };
+  static final protected byte[] jpll = { 1, 3, 5, 7, 0, 2, 4, 6, 1, 3, 5, 7 };
+
+  static final protected short[] xoffset = { -1,-1, 0, 1, 1, 1, 0,-1 };
+  static final protected short[] yoffset = {  0, 1, 1, 1, 0,-1,-1,-1 };
+  static final protected short[][] facearray =
+        { {  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 final protected byte[][] swaparray =
+        { { 0,0,3 },   // S
+          { 0,0,6 },   // SE
+          { 0,0,0 },   // E
+          { 0,0,5 },   // SW
+          { 0,0,0 },   // center
+          { 5,0,0 },   // NE
+          { 0,0,0 },   // W
+          { 6,0,0 },   // NW
+          { 3,0,0 } }; // N
+
+  static final protected int swap_cycle[][] = {
+    {},
+    {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} };
+  }
diff -Nru healpix-java-3.40/src/java/src/healpix/essentials/HealpixUtils.java healpix-java-3.50/src/java/src/healpix/essentials/HealpixUtils.java
--- healpix-java-3.40/src/java/src/healpix/essentials/HealpixUtils.java	1969-12-31 19:00:00.000000000 -0500
+++ healpix-java-3.50/src/java/src/healpix/essentials/HealpixUtils.java	2014-10-22 05:32:25.000000000 -0400
@@ -0,0 +1,140 @@
+/*
+ *  This file is part of Healpix Java.
+ *
+ *  This code 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 code 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 code; 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.sourceforge.net
+ */
+
+package healpix.essentials;
+
+/** Collection of utility functions.
+
+    @copyright 2011-2014 Max-Planck-Society
+    @author Martin Reinecke */
+public class HealpixUtils
+  {
+  /** Evaluates cond; if it is false, throws an Exception containing errtxt. */
+  static public void check(boolean cond, String errtxt) throws Exception
+    { if (!cond) throw new Exception(errtxt); }
+
+  /** Integer base 2 logarithm.
+      @param arg
+      @return the largest integer {@code n} that fulfills {@code 2^n<=arg}.
+      For negative arguments and zero, 0 is returned. */
+  static public int ilog2(long arg)
+    {
+    return 63-Long.numberOfLeadingZeros(Math.max(arg,1L));
+    }
+
+  /** Integer square root.
+      @param arg
+      @return the integer {@code n} which fulfills {@code n^2<=arg<(n+1)^2} */
+  static public int isqrt(long arg)
+    {
+    long res = (long)Math.sqrt(((double)arg)+0.5);
+    if (arg<(1L<<50)) return (int)res;
+    if (res*res>arg)
+      --res;
+    else if ((res+1)*(res+1)<=arg)
+      ++res;
+    return (int)res;
+    }
+
+  /** Computes the cosine of the angular distance between two z, phi positions
+      on the unit sphere. */
+  static public double cosdist_zphi (double z1, double phi1,
+    double z2, double phi2)
+    {
+    return z1*z2+ FastMath.cos(phi1-phi2)* Math.sqrt((1.0-z1*z1)*(1.0-z2*z2));
+    }
+  /** Computes the cosine of the angular distance between two z, phi positions
+      on the unit sphere. */
+  static public double cosdist_zphi (Zphi zp1, Zphi zp2)
+    { return cosdist_zphi(zp1.z,zp1.phi,zp2.z,zp2.phi); }
+
+  /** Returns the remainder of the division {@code v1/v2}.
+      The result is non-negative.
+      @param v1 dividend; can be positive or negative
+      @param v2 divisor; must be positive
+      @return remainder of the division; positive and smaller than {@code v2} */
+  static public double fmodulo (double v1, double v2)
+    {
+    if (v1>=0)
+      return (v1<v2) ? v1 : v1%v2;
+    double tmp=v1%v2+v2;
+    return (tmp==v2) ? 0. : tmp;
+    }
+
+  static public boolean approx (float a, float b, float epsilon)
+    { return Math.abs(a-b) < (epsilon*Math.abs(b)); }
+  static public boolean approx (double a, double b, double epsilon)
+    { return Math.abs(a-b) < (epsilon*Math.abs(b)); }
+
+  static public int uniq2order (long uniq)
+    { return ilog2(uniq>>>2)>>>1; }
+
+  static private long nest_peano_helper (long pix, int order, int dir)
+    {
+    final short arr2[] =
+      {   0, 35, 65, 66, 68,  5,103,  6,110,109, 15, 44, 72,  9,107, 10,
+         31,126, 60,125, 81, 16, 82, 51,123, 88, 26, 25,119, 84, 22, 21,
+         42, 75, 41,104, 12, 47, 77, 78, 38, 71, 37,100, 98, 97,  3, 32,
+         53, 54,116, 87, 57, 58,120, 91, 19,114, 48,113, 93, 28, 94, 63,
+         64,  1, 99,  2, 46, 79, 45,108,  4, 39, 69, 70,  8, 43, 73, 74,
+         85, 20, 86, 55,115, 80, 18, 17, 89, 24, 90, 59, 61, 62,124, 95,
+        106,105, 11, 40,102,101,  7, 36, 76, 13,111, 14, 34, 67, 33, 96,
+        127, 92, 30, 29, 27,122, 56,121, 49, 50,112, 83, 23,118, 52,117,
+        128,194,195,161,196,133,135,230,204,141,143,238,171,233,232,138,
+        149,212,214,183,221,159,158,252,217,155,154,248,178,243,241,144,
+        175,237,236,142,235,170,168,201,227,162,160,193,132,198,199,165,
+        186,251,249,152,242,176,177,211,246,180,181,215,157,220,222,191,
+        192,129,131,226,136,202,203,169,140,206,207,173,231,166,164,197,
+        213,151,150,244,145,208,210,179,153,216,218,187,254,188,189,223,
+        239,174,172,205,167,229,228,134,163,225,224,130,200,137,139,234,
+        250,184,185,219,190,255,253,156,182,247,245,148,209,147,146,240 };
+    final byte arr[] = { 16, 1,27, 2,31,20, 6, 5,10,19, 9,24,13,14,28,23,
+                          0,11,17,18,21, 4,22,15,26,25, 3, 8, 7,30,12,29,
+                         48,33,35,58,53,39,38,60,59,42,40,49,62,44,45,55,
+                         32,50,51,41,37,52,54,47,43,57,56,34,46,63,61,36 };
+    final byte peano_face2path[][] =
+      { { 2,5,2,5,3,6,3,6,2,3,2,3 }, { 2,6,2,3,3,5,2,6,2,3,3,5 } };
+    final byte peano_face2face[][] =
+      { { 0,5,6,11,10,1,4,7,2,3,8,9 }, { 0,5,8,9,6,1,2,7,10,11,4,3 } };
+
+    int face = (int)(pix>>>(2*order));
+    long result = 0L;
+    int state = ((peano_face2path[dir][face]<<4))|(dir<<7);
+    int shift=2*order-4;
+    for (; shift>=0; shift-=4)
+      {
+      state=arr2[(state&0xF0) | (((int)(pix>>>shift))&0xF)];
+      result = (result<<4) | (state&0xF);
+      }
+    if (shift==-2)
+      {
+      state=arr[((state>>>2)&0xFC) | ((int)(pix)&0x3)];
+      result = (result<<2) | (state&0x3);
+      }
+
+    return result + (((long)peano_face2face[dir][face])<<(2*order));
+    }
+
+  static public long nest2peano(long pix, int order)
+    { return nest_peano_helper(pix,order,0); }
+  static public long peano2nest(long pix, int order)
+    { return nest_peano_helper(pix,order,1); }
+
+  }
diff -Nru healpix-java-3.40/src/java/src/healpix/essentials/Hploc.java healpix-java-3.50/src/java/src/healpix/essentials/Hploc.java
--- healpix-java-3.40/src/java/src/healpix/essentials/Hploc.java	1969-12-31 19:00:00.000000000 -0500
+++ healpix-java-3.50/src/java/src/healpix/essentials/Hploc.java	2013-04-03 09:15:40.000000000 -0400
@@ -0,0 +1,76 @@
+/*
+ *  This file is part of Healpix Java.
+ *
+ *  This code 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 code 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 code; 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.sourceforge.net
+ */
+
+package healpix.essentials;
+
+/** Healpix-internal class for specifying locations on the sphere.
+
+    @copyright 2011 Max-Planck-Society
+    @author Martin Reinecke */
+final class Hploc
+  {
+  public double z, phi, sth;
+  public boolean have_sth;
+
+  /** Default constructor. */
+  public Hploc() {}
+  public Hploc (Vec3 v)
+    {
+    double xl = 1./v.length();
+    z = v.z*xl;
+    phi = FastMath.atan2(v.y,v.x);
+    if (Math.abs(z)>0.99)
+      {
+      sth = Math.sqrt(v.x*v.x+v.y*v.y)*xl;
+      have_sth=true;
+      }
+    }
+  public Hploc (Zphi zphi)
+    {
+    z = zphi.z;
+    phi = zphi.phi;
+    have_sth=false;
+    }
+  public Hploc (Pointing ptg) throws Exception
+    {
+    HealpixUtils.check((ptg.theta>=0.)&&(ptg.theta<=Math.PI),
+      "invalid theta value");
+    z = FastMath.cos(ptg.theta);
+    phi = ptg.phi;
+    if (Math.abs(z)>0.99)
+      {
+      sth = FastMath.sin(ptg.theta);
+      have_sth=true;
+      }
+    }
+
+  public Zphi toZphi()
+    { return new Zphi(z,phi); }
+  public Pointing toPointing()
+    {
+    double st = have_sth ? sth : Math.sqrt((1.0-z)*(1.0+z));
+    return new Pointing(FastMath.atan2(st,z),phi);
+    }
+  public Vec3 toVec3()
+    {
+    double st = have_sth ? sth : Math.sqrt((1.0-z)*(1.0+z));
+    return new Vec3(st*FastMath.cos(phi),st*FastMath.sin(phi),z);
+    }
+  }
diff -Nru healpix-java-3.40/src/java/src/healpix/essentials/MocFitsIO.java healpix-java-3.50/src/java/src/healpix/essentials/MocFitsIO.java
--- healpix-java-3.40/src/java/src/healpix/essentials/MocFitsIO.java	1969-12-31 19:00:00.000000000 -0500
+++ healpix-java-3.50/src/java/src/healpix/essentials/MocFitsIO.java	2016-03-21 18:45:42.000000000 -0400
@@ -0,0 +1,120 @@
+/*
+ *  This file is part of Healpix Java.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+package healpix.essentials;
+
+import java.io.*;
+import nom.tam.fits.*;
+
+/** Moc FITS I/O routines.
+    @copyright 2014-2015 Max-Planck-Society
+    @author Martin Reinecke */
+public class MocFitsIO
+  {
+  /** Converts the contents of a FITS input stream to a MOC. */
+  public static Moc mocFromFits(InputStream inp) throws Exception
+    {
+    FitsFactory.setUseHierarch(true);
+    FitsFactory.setUseAsciiTables(false);
+    FitsFactory.setLongStringsEnabled(true);
+    BasicHDU<?> bhdu = (new Fits(inp)).getHDU(1);
+    Header head = bhdu.getHeader();
+
+    Object tmp = ((BinaryTable)bhdu.getData()).getFlattenedColumn(0);
+    long[] data=null;
+    if (tmp instanceof long[])
+      data = (long[])tmp;
+    else if (tmp instanceof int[])
+      {
+      int[] tmp2 = (int[])tmp;
+      data = new long[tmp2.length];
+      for (int i=0; i<tmp2.length; ++i)
+        data[i] = (long)tmp2[i];
+      }
+    else if (tmp instanceof short[])
+      {
+      short[] tmp2 = (short[])tmp;
+      data = new long[tmp2.length];
+      for (int i=0; i<tmp2.length; ++i)
+        data[i] = (long)tmp2[i];
+      }
+    else
+      HealpixUtils.check(false,"unsupported data format");
+
+    RangeSet ru = new RangeSet();
+    for (int i=0; i<data.length; ++i)
+      ru.append(data[i]);
+    return Moc.fromUniqRS(ru);
+    }
+  /** Converts the contents of a FITS file to a MOC. */
+  public static Moc mocFromFits(String filename) throws Exception
+    {
+    FileInputStream inp = new FileInputStream(filename);
+    Moc moc = mocFromFits(inp);
+    inp.close();
+    return moc;
+    }
+
+  /** Writes the provided Moc to the stream in FITS format. */
+  public static void mocToFits(Moc moc, OutputStream out) throws Exception
+    {
+    FitsFactory.setUseHierarch(true);
+    FitsFactory.setUseAsciiTables(false);
+    FitsFactory.setLongStringsEnabled(true);
+    Fits f = new Fits();
+    Object[] table = new Object[1];
+    long[] data=moc.toUniq();
+    long maxval=0;
+    if (data.length>0) maxval=data[data.length-1];
+    if (maxval<=0x7fff)
+      {
+      short[] dtmp = new short[data.length];
+      for (int i=0; i<data.length; ++i)
+        dtmp[i]=(short)data[i];
+      table[0]=dtmp;
+      }
+    else if (maxval<=0x7FFFFFFF)
+      {
+      int[] dtmp = new int[data.length];
+      for (int i=0; i<data.length; ++i)
+        dtmp[i]=(int)data[i];
+      table[0]=dtmp;
+      }
+    else
+      table[0] = data;
+
+    f.addHDU(Fits.makeHDU(table));
+    BinaryTableHDU bhdu = (BinaryTableHDU) f.getHDU(1);
+
+    bhdu.setColumnName(0, "PIXEL", "");
+    bhdu.addValue("PIXTYPE", "HEALPIX", "HEALPix magic value");
+    bhdu.addValue("ORDERING", "NUNIQ", "NUNIQ coding method");
+    bhdu.addValue("COORDSYS", "C", "mandated by MOC standard");
+    bhdu.addValue("MOCORDER", moc.maxOrder(), "MOC resolution (best order)");
+
+    f.write(new DataOutputStream(out));
+    out.flush();
+    }
+  /** Writes the provided Moc to the specified file in FITS format. */
+  public static void mocToFits(Moc moc, String filename) throws Exception
+    {
+    FileOutputStream out = new FileOutputStream(filename);
+    mocToFits(moc,out);
+    out.close();
+    }
+  }
diff -Nru healpix-java-3.40/src/java/src/healpix/essentials/Moc.java healpix-java-3.50/src/java/src/healpix/essentials/Moc.java
--- healpix-java-3.40/src/java/src/healpix/essentials/Moc.java	1969-12-31 19:00:00.000000000 -0500
+++ healpix-java-3.50/src/java/src/healpix/essentials/Moc.java	2015-04-14 09:49:56.000000000 -0400
@@ -0,0 +1,207 @@
+/*
+ *  This file is part of Healpix Java.
+ *
+ *  This code 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 code 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 code; 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.sourceforge.net
+ */
+
+package healpix.essentials;
+
+/** Support for MOC algorithms.
+    @copyright 2014-2015 Max-Planck-Society
+    @author Martin Reinecke */
+public class Moc
+  {
+  private final static int maxorder=29;
+  private RangeSet rs;
+
+  /** Creates a new, empty Moc. */
+  public Moc()
+    { rs=new RangeSet(); }
+  /** Creates a new Moc, which is identical to "other". */
+  public Moc(Moc other)
+    { rs=new RangeSet(other.rs); }
+  /** Creates a new Moc from the range set of NESTED pixels at the given order.
+      */
+  public Moc(RangeSet rs2, int order)
+    {
+    rs=new RangeSet(rs2.nranges());
+    int shift=2*(maxorder-order);
+    for (int i=0; i<rs2.nranges(); ++i)
+      rs.append(rs2.ivbegin(i)<<shift,rs2.ivend(i)<<shift);
+    }
+
+  static private Moc fromNewRangeSet(RangeSet rngset)
+    {
+    Moc res = new Moc();
+    res.rs = rngset;
+    return res;
+    }
+
+  /** Returns the internal range set. */
+  public RangeSet getRangeSet()
+    { return new RangeSet(rs); }
+
+  /** Returns the maximum HEALPix order necessary to describe the Moc exactly.
+      */
+  public int maxOrder()
+    {
+    long combo=0;
+    for (int i=0; i<rs.nranges(); ++i)
+      combo|=rs.ivbegin(i)|rs.ivend(i);
+    return maxorder-(Long.numberOfTrailingZeros(combo)>>>1);
+    }
+
+  /** Returns a Moc with degraded resolution.
+      @param order the maximum HEALPix order used for the result
+      @param keepPartialCells if true, partially filled cells will be included
+        in the output Moc; if false, they will be ignored. */
+  public Moc degradedToOrder (int order, boolean keepPartialCells)
+    {
+    int shift=2*(maxorder-order);
+    long ofs=(1L<<shift)-1;
+    long mask = ~ofs;
+    long adda = keepPartialCells ? 0L : ofs,
+         addb = keepPartialCells ? ofs : 0L;
+    RangeSet rs2=new RangeSet();
+    for (int i=0; i<rs.nranges(); ++i)
+      {
+      long a=(rs.ivbegin(i)+adda)&mask;
+      long b=(rs.ivend  (i)+addb)&mask;
+      if (b>a) rs2.append(a,b);
+      }
+    return fromNewRangeSet(rs2);
+    }
+
+  /** Adds a range of pixels at a given HEALPix order to the Moc.
+      @param order the HEALPix order of the added pixels
+      @param p1 the first pixel of the range
+      @param p2 the one-after-last pixel of the range */
+  public void addPixelRange (int order, long p1, long p2)
+    {
+    int shift=2*(maxorder-order);
+    rs.add(p1<<shift,p2<<shift);
+    }
+  public void addPixel (int order, long p)
+    { addPixelRange(order, p, p+1); }
+  /** Returns a new Moc that contains the union of this Moc and "other". */
+  public Moc union (Moc other)
+    { return fromNewRangeSet(rs.union(other.rs)); }
+  /** Returns a new Moc that contains the intersection of this Moc and "other".
+      */
+  public Moc intersection (Moc other)
+    { return fromNewRangeSet(rs.intersection(other.rs)); }
+  /** Returns a new Moc that contains all parts of this Moc that are not
+      contained in "other". */
+  public Moc subtraction (Moc other)
+    { return fromNewRangeSet(rs.difference(other.rs)); }
+  /** Returns the complement of this Moc. */
+  public Moc complement()
+    {
+    RangeSet full = new RangeSet(new long[]{0L,12L*(1L<<(2*maxorder))});
+    return fromNewRangeSet(full.difference(rs));
+    }
+  /** @return true, if "other" is a subset of this Moc, else false. */
+  public boolean contains(Moc other) // FIXME: needs optimization!
+    { return rs.contains(other.rs); }
+  /** @return true, if the intersection of this Moc and "other" is not empty. */
+  public boolean overlaps(Moc other) // FIXME: needs optimization!
+    { return rs.overlaps(other.rs); }
+  /** @return A RangeSet containing all HEALPix pixels (in NUNIQ order) covered
+      by this Moc. The result is well-formed in the sense that every pixel is
+      given at its lowest possible HEALPix order. */
+  public RangeSet toUniqRS() // should be tuned!
+    {
+    RangeSet r2 = new RangeSet(rs);
+    RangeSet r3 = new RangeSet();
+    RangeSet res= new RangeSet();
+    for (int o=0; o<=maxorder; ++o)
+      {
+      if (r2.isEmpty()) return res;
+
+      int shift = 2*(maxorder-o);
+      long ofs=(1L<<shift)-1;
+      long ofs2 = 1L<<(2*o+2);
+      r3.clear();
+      for (int iv=0; iv<r2.nranges(); ++iv)
+        {
+        long a=(r2.ivbegin(iv)+ofs)>>>shift,
+             b=r2.ivend(iv)>>>shift;
+        r3.append(a<<shift, b<<shift);
+        res.append(a+ofs2,b+ofs2);
+        }
+      if (!r3.isEmpty())
+        r2 = r2.difference(r3);
+      }
+    return res;
+    }
+  public long[] toUniq() // should be tuned!
+    { return toUniqRS().toArray(); }
+
+  /** @return A Moc built from the RangeSet of NUNIQ HEALPix pixels given in
+      "ru". "ru" need not be well-formed. */
+  public static Moc fromUniqRS (RangeSet ru) // should be tuned!
+    {
+    RangeSet r= new RangeSet();
+    RangeSet rtmp = new RangeSet();
+    int lastorder=0;
+    int shift=2*maxorder;
+    for (int i=0; i<ru.nranges(); ++i)
+      for (long j=ru.ivbegin(i); j<ru.ivend(i); ++j)
+        {
+        int order = HealpixUtils.uniq2order(j);
+        if (order!=lastorder)
+          {
+          r=r.union(rtmp);
+          rtmp.clear();
+          lastorder=order;
+          shift=2*(maxorder-order);
+          }
+        long pix = j-(1L<<(2*order+2));
+        rtmp.append (pix<<shift,(pix+1)<<shift);
+        }
+    r=r.union(rtmp);
+    return fromNewRangeSet(r);
+    }
+
+  public static Moc fromUniq (long []u) // should be tuned!
+    {
+    return fromUniqRS(RangeSet.fromArray(u));
+    }
+
+  /** @return A compressed representation of the Moc obtained by interpolative
+      coding. */
+  public byte[] toCompressed() throws Exception
+    { return rs.toCompressed(); }
+  /** @return A Moc built from the compressed representation given in "data". */
+  public static Moc fromCompressed(byte[] data) throws Exception
+    { return fromNewRangeSet(RangeSet.fromCompressed(data)); }
+
+  public boolean equals(Object obj)
+    {
+    if (this == obj)
+      return true;
+    if ((obj==null) || (!(obj instanceof Moc)))
+      return false;
+    Moc other = (Moc) obj;
+    return rs.equals(other.rs);
+    }
+  public int hashCode()
+    { return rs.hashCode(); }
+
+  public int nranges()
+    { return rs.nranges(); }
+  }
diff -Nru healpix-java-3.40/src/java/src/healpix/essentials/MocQuery.java healpix-java-3.50/src/java/src/healpix/essentials/MocQuery.java
--- healpix-java-3.40/src/java/src/healpix/essentials/MocQuery.java	1969-12-31 19:00:00.000000000 -0500
+++ healpix-java-3.50/src/java/src/healpix/essentials/MocQuery.java	2015-08-05 05:49:32.000000000 -0400
@@ -0,0 +1,470 @@
+/*
+ *  This file is part of Healpix Java.
+ *
+ *  This code 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 code 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 code; 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.sourceforge.net
+ */
+
+package healpix.essentials;
+import java.util.ArrayList;
+
+/** Support for MOC queries.
+    @copyright 2015 Max-Planck-Society
+    @author Martin Reinecke */
+public class MocQuery
+  {
+  static public enum MocQueryOp { AND,OR,XOR,NOT,NONE }
+
+  static public class MocQueryComponent
+    {
+    public MocQueryOp op;
+    public Vec3 center;
+    public double radius;
+    public int nops;
+    public MocQueryComponent(MocQueryOp op_) throws Exception
+      {
+      op= op_;
+      HealpixUtils.check(op_!=MocQueryOp.NONE,"bad operator");
+      switch (op)
+        {
+        case AND:
+        case OR:
+        case XOR:
+          nops=2;
+          break;
+        case NOT:
+          nops=1;
+          break;
+        case NONE:
+          nops=0;
+          break;
+        }
+      }
+    public MocQueryComponent(MocQueryOp op_, int nops_) throws Exception
+      {
+      op= op_;
+      nops=nops_;
+      switch (op)
+        {
+        case AND:
+        case OR:
+          HealpixUtils.check(nops>=2,"bad nops");
+          break;
+        case XOR:
+          HealpixUtils.check(nops==2,"bad nops");
+          break;
+        case NOT:
+          HealpixUtils.check(nops==1,"bad nops");
+          break;
+        case NONE:
+          HealpixUtils.check(false,"bad operator");
+          break;
+        }
+      }
+    public MocQueryComponent(Vec3 cnt, double rad)
+      {
+      op = MocQueryOp.NONE;
+      center = new Vec3(cnt);
+      center.normalize();
+      radius = rad;
+      nops=0;
+      }
+    }
+
+  static private class queryHelper
+    {
+    private final class pstack
+      {
+      private long[] p;
+      private int[] o;
+      private int s, m;
+
+      public pstack (int sz)
+        { p=new long[sz]; o=new int[sz]; s=m=0; }
+      public void push (long p_, int o_)
+        { p[s]=p_; o[s]=o_; ++s; }
+      public void pop ()
+        { --s; }
+      public void popToMark ()
+        { s=m; }
+      public int size ()
+        { return s; }
+      public void mark ()
+        { m=s; }
+      public int otop ()
+        { return o[s-1]; }
+      public long ptop ()
+        { return p[s-1]; }
+      public void clear ()
+        { s=m=0; }
+      public boolean empty ()
+        { return s==0; }
+      }
+
+    private int order, omax, ncomp;
+    private boolean inclusive;
+    private HealpixBase base[];
+    private double cr[], crmin[][], crmax[][];
+    private int shortcut[];
+    private MocQueryOp op[];
+    private int nops[];
+    private Vec3 center[];
+
+    private pstack stk; // stack for pixel numbers and their orders
+    private long pix;
+    private int o;
+    private Vec3 pv;
+    private int loc;
+
+    private void check_pixel (int zone, Moc pixset)
+      {
+      if (zone==0) return;
+      if (o<order)
+        {
+        if (zone>=3)
+          pixset.addPixel(o,pix); // output all subpixels
+        else // (zone>=1)
+          for (int i=0; i<4; ++i)
+            stk.push(4*pix+3-i,o+1); // add children
+        }
+      else if (o>order) // this implies that inclusive==true
+        {
+        if (zone>=2) // pixel center in shape
+          {
+          pixset.addPixel(order,pix>>>(2*(o-order))); // output parent pixel
+          stk.popToMark(); // unwind the stack
+          }
+        else // (zone>=1): pixel center in safety range
+          {
+          if (o<omax) // check sublevels
+            for (int i=0; i<4; ++i) // add children in reverse order
+              stk.push(4*pix+3-i,o+1);
+          else // at resolution limit
+            {
+            pixset.addPixel(order,pix>>>(2*(o-order))); // output parent pixel
+            stk.popToMark(); // unwind the stack
+            }
+          }
+        }
+      else // o==order
+        {
+        if (zone>=2)
+          pixset.addPixel(order,pix);
+        else if (inclusive) // and (zone>=1)
+          {
+          if (order<omax) // check sublevels
+            {
+            stk.mark(); // remember current stack position
+            for (int i=0; i<4; ++i) // add children in reverse order
+              stk.push(4*pix+3-i,o+1);
+            }
+          else // at resolution limit
+            pixset.addPixel(order,pix); // output the pixel
+          }
+        }
+      }
+
+    void correctLoc() throws Exception
+      {
+      int myloc=loc--;
+      HealpixUtils.check((myloc>=0)&&(myloc<ncomp),"inconsistency");
+      for (int i=0; i<nops[myloc]; ++i)
+        correctLoc();
+      }
+    int getZone (int zmin, int zmax)
+      {
+      if (zmin==zmax) { loc=shortcut[loc]; return zmin; } // short-circuit
+      int myloc=loc--;
+      switch (op[myloc])
+        {
+        case AND:
+          {
+          int z1=zmax;
+          for (int i=0; i<nops[myloc]; ++i)
+            z1 = getZone(zmin,z1);
+          return z1;
+          }
+        case OR:
+          {
+          int z1=zmin;
+          for (int i=0; i<nops[myloc]; ++i)
+            z1 = getZone(z1,zmax);
+          return z1;
+          }
+        case XOR:
+          {
+          int z1=getZone(0,3);
+          int z2=getZone(0,3);
+          return Math.max(zmin,Math.min(zmax,
+            Math.max(Math.min(z1,3-z2),Math.min(3-z1,z2))));
+          }
+        case NOT:
+          return 3-getZone(3-zmax,3-zmin);
+        case NONE:
+          {
+          int res=zmax;
+          double crad=pv.dot(center[myloc]);
+          if (crad<=crmax[o][myloc]) res=0;
+          else if (crad<=cr[myloc]) res=1;
+          else if (crad<=crmin[o][myloc]) res=2;
+          return Math.max(zmin,Math.min(zmax,res));
+          }
+        }
+      return -1; // unreachable
+      }
+
+    public queryHelper (int order_, int omax_, boolean inclusive_,
+      ArrayList<MocQueryComponent> comp) throws Exception
+      {
+      order=order_;
+      omax=omax_;
+      ncomp=comp.size();
+      inclusive=inclusive_;
+      base=new HealpixBase[omax+1];
+      cr=new double[ncomp];
+      crmin=new double [omax+1][ncomp];
+      crmax=new double [omax+1][ncomp];
+      HealpixUtils.check(ncomp>=1,"bad query component ArrayList");
+      HealpixUtils.check(order<=omax,"order>omax");
+      if (!inclusive) HealpixUtils.check(order==omax,"inconsistency");
+      HealpixUtils.check(omax<=HealpixBase.order_max,"omax too high");
+
+      op=new MocQueryOp[ncomp];
+      nops=new int[ncomp];
+      center=new Vec3[ncomp];
+      for (int i=0; i<ncomp; ++i)
+        {
+        op[i]=comp.get(i).op;
+        nops[i]=comp.get(i).nops;
+        center[i]=comp.get(i).center;
+        if (op[i]==MocQueryOp.NONE) // it's a cap
+          cr[i]=Math.cos(comp.get(i).radius);
+        }
+      for (o=0; o<=omax; ++o) // prepare data at the required orders
+        {
+        base[o] = new HealpixBase(1<<o,Scheme.NESTED);
+        double dr=base[o].maxPixrad(); // safety distance
+        for (int i=0; i<ncomp; ++i)
+          if (op[i]==MocQueryOp.NONE) // it's a cap
+            {
+            double r=comp.get(i).radius;
+            crmax[o][i] = (r+dr>=Math.PI) ?
+              -1.01 : Math.cos(r+dr);
+            crmin[o][i] = (r-dr<=0.) ?
+               1.01 : Math.cos(r-dr);
+            }
+        }
+      stk=new pstack(12+3*omax); // reserve maximum size to avoid reallocation
+
+      shortcut=new int[ncomp];
+      for (int i=0; i<ncomp; ++i)
+        {
+        loc=i;
+        correctLoc();
+        shortcut[i]=loc;
+        }
+      }
+    Moc result() throws Exception
+      {
+      Moc pixset = new Moc();
+      stk.clear();
+      stk.mark();
+      for (int i=0; i<12; ++i) // insert the 12 base pixels in reverse order
+        stk.push(11-i,0);
+
+      while (!stk.empty()) // as long as there are pixels on the stack
+        {
+        // pop current pixel number and order from the stack
+        pix=stk.ptop();
+        o=stk.otop();
+        stk.pop();
+        pv = base[o].pix2vec(pix);
+
+        loc=ncomp-1;
+        int zone=getZone(0,3);
+        check_pixel (zone, pixset);
+        HealpixUtils.check(loc==-1,"stack not used up");
+        }
+      return pixset;
+      }
+    }
+
+  static public Moc doMocQuery (int order, ArrayList<MocQueryComponent> comp)
+    throws Exception
+    { return (new queryHelper(order,order,false,comp)).result(); }
+
+  static public Moc doMocQueryInclusive (int order, int omax,
+    ArrayList<MocQueryComponent> comp)
+    throws Exception
+    { return (new queryHelper(order,omax,true,comp)).result(); }
+
+  static private double isLeft (Vec3 a, Vec3 b, Vec3 c)
+    {
+    return (a.cross(b)).dot(c);
+    }
+
+  // adapted from code available at http://geomalgorithms.com/a12-_hull-3.html
+  // Original copyright notice follows:
+  // Copyright 2001 softSurfer, 2012 Dan Sunday
+  // This code may be freely used and modified for any purpose
+  // providing that this copyright notice is included with it.
+  // SoftSurfer makes no warranty for this code, and cannot be held
+  // liable for any real or imagined damage resulting from its use.
+  // Users of this code must verify correctness for their application.
+  static private int[] getHull (Vec3 vert[], int P[])
+    throws Exception
+    {
+    // initialize a deque D[] from bottom to top so that the
+    // 1st three vertices of P[] are a ccw triangle
+    int n = P.length;
+    int D[] = new int[2*n+1];
+    int bot = n-2, top = bot+3;    // initial bottom and top deque indices
+    D[bot] = D[top] = P[2];      // 3rd vertex is at both bot and top
+    if (isLeft(vert[P[0]], vert[P[1]], vert[P[2]]) > 0)
+      {
+      D[bot+1] = P[0];
+      D[bot+2] = P[1];           // ccw vertices are: 2,0,1,2
+      }
+    else
+      {
+      D[bot+1] = P[1];
+      D[bot+2] = P[0];           // ccw vertices are: 2,1,0,2
+      }
+
+    // compute the hull on the deque D[]
+    for (int i=3; i<n; i++)
+      {   // process the rest of vertices
+      // test if next vertex is inside the deque hull
+      if ((isLeft(vert[D[bot]], vert[D[bot+1]], vert[P[i]]) > 0) &&
+          (isLeft(vert[D[top-1]], vert[D[top]], vert[P[i]]) > 0) )
+        continue;         // skip an interior vertex
+
+      // incrementally add an exterior vertex to the deque hull
+      // get the rightmost tangent at the deque bot
+      while (isLeft(vert[D[bot]], vert[D[bot+1]], vert[P[i]]) <= 0)
+        ++bot;                 // remove bot of deque
+      D[--bot] = P[i];         // insert P[i] at bot of deque
+
+      // get the leftmost tangent at the deque top
+      while (isLeft(vert[D[top-1]], vert[D[top]], vert[P[i]]) <= 0)
+        --top;                 // pop top of deque
+      D[++top] = P[i];         // push P[i] onto top of deque
+      }
+
+    // transcribe deque D[] to the output hull array H[]
+    int nout = top-bot;
+    int res[] = new int[nout];
+    for (int h=0; h<nout; h++)
+      res[h] = D[bot + h +1];
+
+    return res;
+    }
+
+  static public ArrayList<MocQueryComponent> prepPolyHelper (Vec3 vv[],
+    int P[], ArrayList<MocQueryComponent> comp, boolean doLast)
+    throws Exception
+    {
+    int hull[]=getHull(vv,P);
+    boolean addHull[]=new boolean[hull.length];
+
+    // sync both sequences at the first point of the convex hull
+    int ihull=0, ipoly=0, nhull=hull.length, npoly=P.length;
+    while (hull[ihull]!=P[ipoly]) ++ipoly;
+
+    // iterate over the pockets between the polygon and its convex hull
+    int npockets=0;
+    if (P.length==3)
+      for (int i=0; i<3; i++) addHull[i]=true;
+    else
+      {
+      do
+        {
+        int ihull_next = (ihull+1)%nhull,
+            ipoly_next = (ipoly+1)%npoly;
+        if (hull[ihull_next]==P[ipoly_next]) // no pocket found
+          { addHull[ihull]=true; ihull=ihull_next; ipoly=ipoly_next; }
+        else // query pocket
+          {
+          int nvpocket=2; // number of vertices for this pocket
+          while (P[ipoly_next]!=hull[ihull_next])
+            {
+            ipoly_next = (ipoly_next+1)%npoly;
+            ++nvpocket;
+            }
+          int ppocket[] = new int[nvpocket];
+          int idx=0;
+          int ipoly_bw=ipoly_next;
+          while (P[ipoly_bw]!=hull[ihull])
+            {
+            ppocket[idx++]=P[ipoly_bw];
+            ipoly_bw=(ipoly_bw+npoly-1)%npoly;
+            }
+          ppocket[idx]=hull[ihull];
+          // process pocket recursively
+          ++npockets;
+          comp=prepPolyHelper (vv, ppocket, comp, false);
+          ihull=ihull_next;
+          ipoly=ipoly_next;
+          }
+        } while (ihull!=0);
+      }
+    if (npockets>1) 
+      comp.add(new MocQueryComponent(MocQueryOp.OR,npockets));
+    if (npockets>0) 
+      comp.add(new MocQueryComponent(MocQueryOp.NOT));
+
+    if (!doLast)
+      addHull[hull.length-1]=false;
+
+    // add convex hull
+    for (int i=0; i<hull.length; ++i)
+      if (addHull[i])
+        comp.add(new MocQueryComponent
+          (vv[hull[i]].cross(vv[hull[(i+1)%hull.length]]).norm(),0.5*Math.PI));
+
+    int num_and = 0;
+    for (int i=0; i<hull.length; ++i)
+      if (addHull[i]) ++num_and;
+    if (npockets>0) ++num_and;
+    if (num_and>1) 
+      comp.add(new MocQueryComponent(MocQueryOp.AND,num_and));
+
+    return comp;
+    }
+
+  static public ArrayList<MocQueryComponent> prepPolygon(ArrayList<Vec3> vertex)
+    throws Exception
+    {
+    HealpixUtils.check(vertex.size()>=3,"not enough vertices in polygon");
+    Vec3 vv[] = new Vec3[vertex.size()];
+    for (int i=0; i<vertex.size(); ++i)
+      vv[i]=vertex.get(i).norm();
+
+    int[] P=new int[vv.length];
+    for (int i=0; i<P.length; ++i)
+      P[i]=i;
+    ArrayList<MocQueryComponent> comp = new ArrayList<MocQueryComponent>();
+    return prepPolyHelper(vv,P,comp,true);
+    }
+
+  static public Moc queryGeneralPolygon (ArrayList<Vec3> vertex, int order)
+    throws Exception
+    { return doMocQuery (order, MocQuery.prepPolygon(vertex)); }
+  static public Moc queryGeneralPolygonInclusive (ArrayList<Vec3> vertex,
+    int order, int omax)
+    throws Exception
+    { return doMocQueryInclusive (order, omax, MocQuery.prepPolygon(vertex)); }
+  }
diff -Nru healpix-java-3.40/src/java/src/healpix/essentials/MocStringIO.java healpix-java-3.50/src/java/src/healpix/essentials/MocStringIO.java
--- healpix-java-3.40/src/java/src/healpix/essentials/MocStringIO.java	1969-12-31 19:00:00.000000000 -0500
+++ healpix-java-3.50/src/java/src/healpix/essentials/MocStringIO.java	2015-07-05 02:56:22.000000000 -0400
@@ -0,0 +1,121 @@
+/*
+ *  This file is part of Healpix Java.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+package healpix.essentials;
+
+import java.io.*;
+
+/** Moc string I/O routines.
+    @copyright 2014-2015 Max-Planck-Society
+    @author Martin Reinecke */
+public class MocStringIO
+  {
+  /** Parses a string following either the basic ASCII or JSON syntax given in
+      the MOC standard document, and converts it into a MOC.
+      The string need not obey the rules for a well-formed MOC given in the
+      document. */
+  public static Moc mocFromString(String in)
+    {
+    in=in.replaceAll(",+"," "); // replace commas with spaces
+    in=in.replaceAll("[\\[\\]{}\"]+",""); // get rid of useless characters
+    in=in.replaceAll("\\s*[:/]\\s*","/ "); // stick order indicator to order
+    in=in.replaceAll("\\s*-\\s*","-"); // fuse ranges into one token
+    String[] tok = in.split("[\\s]+"); // split at whitespace
+    RangeSet ru = new RangeSet();
+    int order=0;
+    long ofs=0;
+    for (int i=0; i<tok.length; ++i)
+      {
+      if (tok[i].isEmpty()) continue;
+      if (tok[i].contains("/")) // new order
+        {
+        tok[i]=tok[i].split("/")[0];
+        order=Integer.parseInt(tok[i]);
+        ofs = 4*(1L<<(2*order));
+        }
+      else if (tok[i].contains("-")) // range of values
+        {
+        String [] lim=tok[i].split("-");
+        ru.add(Long.parseLong(lim[0])+ofs,
+               Long.parseLong(lim[1])+ofs+1);
+        }
+      else // single value
+        ru.add(Long.parseLong(tok[i])+ofs);
+      }
+    return Moc.fromUniqRS(ru);
+    }
+  private static String mocToStringGeneral(Moc moc, boolean json)
+    {
+    RangeSet ru = moc.toUniqRS();
+    StringBuilder s = new StringBuilder();
+    if (json) s.append("{");
+    boolean firstOrder=true;
+    int omax = moc.maxOrder();
+    for (int o=0; o<=omax; ++o)
+      {
+      RangeSet rt = new RangeSet();
+      long offset=4*(1L<<(2*o));
+      rt.append(offset, 4*offset);
+      rt=rt.intersection(ru);
+      boolean prefix=false;
+      if (!rt.isEmpty())
+        {
+        for (int iv=0; iv<rt.nranges(); ++iv)
+          {
+          long a=rt.ivbegin(iv)-offset,
+               b=rt.ivend(iv)-offset;
+          if (!prefix)
+            {
+            if (!firstOrder) s.append(json ? ", " : " ");
+            firstOrder=false;
+            if (json)
+              s.append("\"").append(o).append("\":[");
+            else
+              s.append(o).append("/");
+            prefix=true;
+            }
+          else
+            s.append(",");
+          if (json)
+            {
+            for (long i=a;i<b-1;++i)
+              s.append(i).append(",");
+            s.append(b-1);
+            }
+          else
+            {
+            s.append(a);
+            if (b>a+1) s.append("-").append(b-1);
+            }
+          }
+        }
+      if (json&&prefix)
+        s.append("]");
+      }
+    if (json) s.append("}");
+    return s.toString();
+    }
+  /** Converts the Moc to its basic ASCII representation as described in the MOC
+      standard document. The result is well-formed. */
+  public static String mocToStringASCII (Moc moc)
+    { return mocToStringGeneral(moc,false); }
+  /** Converts the Moc to its JSON representation as described in the MOC
+      standard document. The result is well-formed. */
+  public static String mocToStringJSON(Moc moc)
+    { return mocToStringGeneral(moc,true); }
+  }
diff -Nru healpix-java-3.40/src/java/src/healpix/essentials/package-info.java healpix-java-3.50/src/java/src/healpix/essentials/package-info.java
--- healpix-java-3.40/src/java/src/healpix/essentials/package-info.java	1969-12-31 19:00:00.000000000 -0500
+++ healpix-java-3.50/src/java/src/healpix/essentials/package-info.java	2012-05-29 07:57:22.000000000 -0400
@@ -0,0 +1,48 @@
+/**
+Package implementing essential HEALPix functionality.<br>
+healpix.essentials is a Java package aiming to combine the advantages
+of other Java HEALPix libraries like
+the gov.fnal.eag.healpix package by N. Kuropatkin
+(<a href="http://home.fnal.gov/~kuropat/HEALPIX/PixTools.html">http://home.fnal.gov/~kuropat/HEALPIX/PixTools.html</a>),
+Jan Kotek's org.asterope.healpix package
+(<a href="https://github.com/jankotek/HEALPix">https://github.com/jankotek/HEALPix</a>),
+and the healpix.core package developed at ESO.
+<br>
+Current features include:
+<ul>
+<li>close similarities with Healpix_Base_T class from Healpix C++, which allows
+  simultaneous development and bug fixes for both.
+<li>support for arbitrary positive Nside values in RING scheme; no longer
+  limited to powers of 2
+<li>maximum supported Nside value: 2^29
+<li>significant performance improvements: most methods have been accelerated
+  by integral factors, some by more than an order of magnitude.
+<li>re-implementation of queryDisc and queryPolygon:
+<ul>
+  <li> query methods return RangeSet objects which allow much more compact
+    storage of the result
+  <li> new native query methods for NESTED ordering; these are slower than those
+    for RING ordering, but much quicker than converting all pixels from a RING
+    result to NESTED.
+  <li> inclusive queries have been improved: several bugs were fixed, and the
+    number of false positives in the result has been reduced. Users can now
+    choose between quick inclusive queries returning more false positives,
+    and slower ones returning fewer false positives.
+</ul>
+<li> the HealpixProc class offers a procedural (instead of object-oriented)
+  interface to the HealpixBase functionality, which simplifies transition
+  for users of the "Healpix" and "PixTools" classes.
+  NOTE: this only works for Nside parameters which are powers of 2
+<li> many bug fixes
+<li> no external library dependencies, except for "nom.tam.fits" if FITS I/O is
+  required
+<li> the code base is thread-safe in the following sense:
+<ul>
+  <li> HealpixProc methods can be called concurrently
+  <li> HealpixBase methods can be called concurrently on different objects
+</ul>
+</ul>
+ at copyright 2011, 2012 Max-Planck-Society
+ at author Martin Reinecke
+*/
+package healpix.essentials;
diff -Nru healpix-java-3.40/src/java/src/healpix/essentials/Pointing.java healpix-java-3.50/src/java/src/healpix/essentials/Pointing.java
--- healpix-java-3.40/src/java/src/healpix/essentials/Pointing.java	1969-12-31 19:00:00.000000000 -0500
+++ healpix-java-3.50/src/java/src/healpix/essentials/Pointing.java	2015-04-01 08:52:19.000000000 -0400
@@ -0,0 +1,108 @@
+/*
+ *  This file is part of Healpix Java.
+ *
+ *  This code 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 code 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 code; 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.sourceforge.net
+ */
+
+package healpix.essentials;
+
+/** An angular position on the unit sphere.
+
+    @copyright 2011 Max-Planck-Society
+    @author Martin Reinecke */
+public class Pointing
+  {
+  /** Colatitude in radians (0 is North Pole; Pi is South Pole) */
+  public double theta;
+
+  /** Longitude in radians */
+  public double phi;
+
+  /** Default constructor */
+  public Pointing() {}
+
+  public Pointing(Pointing ptg)
+    { this.theta = ptg.theta; this.phi = ptg.phi; }
+
+  /** Simple constructor initializing both values.
+      @param theta in radians [0,Pi]
+      @param phi in radians [0,2*Pi] */
+  public Pointing(double theta, double phi)
+    { this.theta = theta; this.phi = phi; }
+
+  /** Conversion from {@link Vec3} */
+  public Pointing(Vec3 vec)
+    {
+    theta = FastMath.atan2(Math.sqrt(vec.x*vec.x+vec.y*vec.y),vec.z);
+    phi = FastMath.atan2 (vec.y,vec.x);
+    if (phi<0.) phi += 2*Math.PI;
+    if (phi>=2*Math.PI) phi -= 2*Math.PI;
+    }
+
+  /** Conversion from {@link Zphi} */
+  public Pointing (Zphi zphi)
+    {
+    double xy=Math.sqrt((1.-zphi.z)*(1.+zphi.z));
+    theta = FastMath.atan2(xy,zphi.z); phi=zphi.phi;
+    }
+  // for some reason, the alternative below is much slower...
+  //{ theta=FastMath.acos(zphi.z); phi=zphi.phi; }
+
+  /** Normalize theta range */
+  public void normalizeTheta()
+    {
+    theta=HealpixUtils.fmodulo(theta,2*Math.PI);
+    if (theta>Math.PI)
+      {
+      phi+=Math.PI;
+      theta=2*Math.PI-theta;
+      }
+    }
+
+  /** Normalize theta and phi ranges */
+  public void normalize()
+    {
+    normalizeTheta();
+    phi=HealpixUtils.fmodulo(phi,2*Math.PI);
+    }
+
+  public String toString()
+    {
+    StringBuilder s = new StringBuilder();
+    s.append("ptg(");s.append(theta);
+    s.append(",");s.append(phi);
+    s.append(")");
+    return s.toString();
+    }
+
+  public boolean equals(Object o)
+    {
+    if (this==o) return true;
+    if ((o==null) || (getClass()!=o.getClass())) return false;
+    Pointing pointing = (Pointing) o;
+    if (Double.compare(pointing.phi, phi) != 0) return false;
+    if (Double.compare(pointing.theta, theta) != 0) return false;
+    return true;
+    }
+
+  public int hashCode()
+    {
+    int result = Double.valueOf(theta).hashCode();
+    result = 31 * result + Double.valueOf(phi).hashCode();
+    return result;
+    }
+  }
diff -Nru healpix-java-3.40/src/java/src/healpix/essentials/RangeSet.java healpix-java-3.50/src/java/src/healpix/essentials/RangeSet.java
--- healpix-java-3.40/src/java/src/healpix/essentials/RangeSet.java	1969-12-31 19:00:00.000000000 -0500
+++ healpix-java-3.50/src/java/src/healpix/essentials/RangeSet.java	2015-04-01 08:52:19.000000000 -0400
@@ -0,0 +1,523 @@
+/*
+ *  This file is part of Healpix Java.
+ *
+ *  This code 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 code 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 code; 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.sourceforge.net
+ */
+
+package healpix.essentials;
+import java.util.NoSuchElementException;
+
+/** Class for dealing with sets of integer ranges.
+    Ranges are described by the first element and the one-past-last element.
+    This code was inspired by Jan Kotek's "LongRangeSet" class, but has been
+    completely reimplemented.
+
+    @copyright 2011-2015 Max-Planck-Society
+    @author Martin Reinecke */
+public class RangeSet
+  {
+  /** Interface describing an iterator for going through all values in
+      a RangeSet object. */
+  public interface ValueIterator {
+    public boolean hasNext();
+    public long next();
+    }
+
+  private static final ValueIterator EMPTY_ITER = new ValueIterator()
+    {
+    public boolean hasNext() { return false; }
+    public long next() { throw new NoSuchElementException(); }
+    };
+
+  /** Sorted list of interval boundaries. */
+  protected long[] r;
+  /** Current number of active entries. */
+  protected int sz;
+
+  /** Construct new object with initial space for 4 ranges. */
+  public RangeSet() { this(4); }
+  /** Construct new object with initial capacity for a given number of ranges.
+      @param cap number of initially reserved ranges. */
+  public RangeSet(int cap)
+    {
+    if (cap<0) throw new IllegalArgumentException("capacity must be positive");
+    r = new long[cap<<1];
+    sz=0;
+    }
+  /** Construct new object from an array of longs.
+      @param data */
+   public RangeSet(long[] data)
+     {
+     sz=data.length;
+     r = new long[sz];
+     System.arraycopy(data,0,r,0,sz);
+     checkConsistency();
+     }
+  /** Construct new object from another RangeSet
+      @param other */
+  public RangeSet(RangeSet other)
+    {
+    sz=other.sz;
+    r = new long[sz];
+    System.arraycopy(other.r,0,r,0,sz);
+    }
+
+  /** Checks the object for internal consistency. If a problem is detected,
+      an IllegalArgumentException is thrown. */
+  public void checkConsistency()
+    {
+    if ((sz&1)!=0)
+      throw new IllegalArgumentException("invalid number of entries");
+    for (int i=1; i<sz; ++i)
+      if (r[i]<=r[i-1])
+        throw new IllegalArgumentException("inconsistent entries");
+    }
+
+  private void resize(int newsize)
+    {
+    if (newsize<sz)
+      throw new IllegalArgumentException("requested array size too small");
+    if (newsize==r.length) return;
+    long[] rnew = new long[newsize];
+    System.arraycopy(r,0,rnew,0,sz);
+    r = rnew;
+    }
+
+  /** Make sure the object can hold at least the given number of entries. */
+  public void ensureCapacity(int cap)
+    { if (r.length<cap) resize (Math.max(2*r.length,cap)); }
+  /** Shrinks the array for the entries to minimum size. */
+  public void trimSize()
+    { resize(sz); }
+  /** Shrinks the array for the entries to minimum size, if it is more than
+      twice the minimum size */
+  public void trimIfTooLarge()
+    { if (r.length-sz>=sz) resize(sz); }
+
+  /** Returns an internal representation of the interval a number belongs to.
+      @param val number whose interval is requested
+      @return interval number, starting with -1 (smaller than all numbers in the
+      RangeSet), 0 (first "on" interval), 1 (first "off" interval etc.), up to
+      (and including) sz-1 (larger than all numbers in the RangeSet). */
+  private int iiv (long val)
+    {
+    int count=sz, first=0;
+    while (count>0)
+      {
+      int step=count>>>1, it = first+step;
+      if (r[it]<=val)
+        { first=++it; count-=step+1; }
+      else
+        count=step;
+      }
+    return first-1;
+    }
+
+  /** Append a single-value range to the object.
+      @param val value to append */
+  public void append(long val)
+    { append(val,val+1); }
+
+  /** Append a range to the object.
+      @param a first long in range
+      @param b one-after-last long in range */
+  public void append (long a, long b)
+    {
+    if (a>=b) return;
+    if ((sz>0) && (a<=r[sz-1]))
+      {
+      if (a<r[sz-2]) throw new IllegalArgumentException("bad append operation");
+      if (b>r[sz-1]) r[sz-1]=b;
+      return;
+      }
+    ensureCapacity(sz+2);
+
+    r[sz] = a;
+    r[sz+1] = b;
+    sz+=2;
+    }
+
+  /** Append an entire range set to the object. */
+  public void append (RangeSet other)
+    {
+    for (int i=0; i<other.sz; i+=2)
+      append(other.r[i],other.r[i+1]);
+    }
+
+  /** @return number of ranges in the set. */
+  public int nranges()
+    { return sz>>>1; }
+
+  /** @return true if no entries are stored, else false. */
+  public boolean isEmpty()
+    { return sz==0; }
+
+  /** @return first number in range iv. */
+  public long ivbegin(int iv)
+    { return r[2*iv]; }
+  /** @return one-past-last number in range iv. */
+  public long ivend(int iv)
+    { return r[2*iv+1]; }
+
+  /** Remove all entries in the set. */
+  public void clear()
+    { sz=0; }
+
+  /** Push a single entry at the end of the entry vector. */
+  private void pushv(long v)
+    { ensureCapacity(sz+1); r[sz++]=v; }
+
+  /** Estimate a good strategy for set operations involving two RangeSets. */
+  private static int strategy (int sza, int szb)
+    {
+    final double fct1 = 1.;
+    final double fct2 = 1.;
+    int slo = sza<szb ? sza : szb,
+        shi = sza<szb ? szb : sza;
+    double cost1 = fct1 * (sza+szb);
+    double cost2 = fct2 * slo * Math.max(1.,HealpixUtils.ilog2(shi));
+    return (cost1<=cost2) ? 1 : (slo==sza) ? 2 : 3;
+    }
+
+  private static boolean generalAllOrNothing1 (RangeSet a, RangeSet b,
+    boolean flip_a, boolean flip_b)
+    {
+    boolean state_a=flip_a, state_b=flip_b, state_res=state_a||state_b;
+    int ia=0, ea=a.sz, ib=0, eb=b.sz;
+    boolean runa = ia!=ea, runb = ib!=eb;
+    while(runa||runb)
+      {
+      long va = runa ? a.r[ia] : 0L,
+           vb = runb ? b.r[ib] : 0L;
+      boolean adv_a = runa && (!runb || (va<=vb)),
+              adv_b = runb && (!runa || (vb<=va));
+      if (adv_a) { state_a=!state_a; ++ia; runa = ia!=ea; }
+      if (adv_b) { state_b=!state_b; ++ib; runb = ib!=eb; }
+      if ((state_a||state_b)!=state_res)
+        return false;
+      }
+    return true;
+    }
+
+  private static boolean generalAllOrNothing2 (RangeSet a, RangeSet b,
+    boolean flip_a, boolean flip_b)
+    {
+    int iva = flip_a ? 0 : -1;
+    while (iva<a.sz)
+      {
+      if (iva==-1) // implies that flip_a==false
+        { if ((!flip_b)||(b.r[0]<a.r[0])) return false; }
+      else if (iva==a.sz-1) // implies that flip_a==false
+        { if ((!flip_b)||(b.r[b.sz-1]>a.r[a.sz-1])) return false; }
+      else
+        {
+        int ivb=b.iiv(a.r[iva]);
+        if ((ivb!=b.sz-1)&&(b.r[ivb+1]<a.r[iva+1])) return false;
+        if (flip_b==((ivb&1)==0)) return false;
+        }
+      iva+=2;
+      }
+    return true;
+    }
+
+  private static boolean generalAllOrNothing (RangeSet a, RangeSet b,
+    boolean flip_a, boolean flip_b)
+    {
+    if (a.isEmpty())
+      return flip_a ? true : b.isEmpty();
+    if (b.isEmpty())
+      return flip_b ? true : a.isEmpty();
+    int strat = strategy (a.nranges(), b.nranges());
+    return (strat==1) ? generalAllOrNothing1(a,b,flip_a,flip_b) :
+             ((strat==2) ? generalAllOrNothing2(a,b,flip_a,flip_b)
+                         : generalAllOrNothing2(b,a,flip_b,flip_a));
+    }
+
+  /** Internal helper function for constructing unions, intersections
+      and differences of two RangeSets. */
+  private static RangeSet generalUnion1 (RangeSet a, RangeSet b,
+    boolean flip_a, boolean flip_b)
+    {
+    RangeSet res = new RangeSet();
+
+    boolean state_a=flip_a, state_b=flip_b, state_res=state_a||state_b;
+    int ia=0, ea=a.sz, ib=0, eb=b.sz;
+    boolean runa = ia!=ea, runb = ib!=eb;
+    while(runa||runb)
+      {
+      long va = runa ? a.r[ia] : 0L,
+           vb = runb ? b.r[ib] : 0L;
+      boolean adv_a = runa && (!runb || (va<=vb)),
+              adv_b = runb && (!runa || (vb<=va));
+      if (adv_a) { state_a=!state_a; ++ia; runa = ia!=ea; }
+      if (adv_b) { state_b=!state_b; ++ib; runb = ib!=eb; }
+      if ((state_a||state_b)!=state_res)
+        { res.pushv(adv_a ? va : vb); state_res = !state_res; }
+      }
+    return res;
+    }
+  /** Internal helper function for constructing unions, intersections
+      and differences of two RangeSets. */
+  private static RangeSet generalUnion2 (RangeSet a, RangeSet b,
+    boolean flip_a, boolean flip_b)
+    {
+    RangeSet res = new RangeSet();
+    int iva = flip_a ? 0 : -1;
+    while (iva<a.sz)
+      {
+      int ivb = (iva==-1) ? -1 : b.iiv(a.r[iva]);
+      boolean state_b = flip_b^((ivb&1)==0);
+      if ((iva>-1) && (!state_b)) res.pushv(a.r[iva]);
+      while((ivb<b.sz-1)&&((iva==a.sz-1)||(b.r[ivb+1]<a.r[iva+1])))
+        { ++ivb; state_b=!state_b; res.pushv(b.r[ivb]); }
+      if ((iva<a.sz-1)&&(!state_b)) res.pushv(a.r[iva+1]);
+      iva+=2;
+      }
+    return res;
+    }
+  private static RangeSet generalUnion (RangeSet a, RangeSet b,
+    boolean flip_a, boolean flip_b)
+    {
+    if (a.isEmpty())
+      return flip_a ? new RangeSet() : new RangeSet(b);
+    if (b.isEmpty())
+      return flip_b ? new RangeSet() : new RangeSet(a);
+    int strat = strategy (a.nranges(), b.nranges());
+    return (strat==1) ? generalUnion1(a,b,flip_a,flip_b) :
+             ((strat==2) ? generalUnion2(a,b,flip_a,flip_b)
+                         : generalUnion2(b,a,flip_b,flip_a));
+    }
+
+  /** Return the union of this RangeSet and other. */
+  public RangeSet union (RangeSet other)
+    { return generalUnion (this,other,false,false); }
+  /** Return the intersection of this RangeSet and other. */
+  public RangeSet intersection (RangeSet other)
+    { return generalUnion (this,other,true,true); }
+  /** Return the difference of this RangeSet and other. */
+  public RangeSet difference (RangeSet other)
+    { return generalUnion (this,other,true,false); }
+
+  /** Returns true if a is contained in the set, else false. */
+  public boolean contains (long a)
+    { return ((iiv(a)&1)==0); }
+  /** Returns true if all numbers [a;b[ are contained in the set, else false. */
+  public boolean contains (long a,long b)
+    {
+    int res=iiv(a);
+    if ((res&1)!=0) return false;
+    return (b<=r[res+1]);
+    }
+  @Deprecated
+  public boolean containsAll (long a,long b)
+    { return contains(a,b); }
+  /** Returns true if any of the numbers [a;b[ are contained in the set,
+      else false. */
+  public boolean overlaps (long a,long b)
+    {
+    int res=iiv(a);
+    if ((res&1)==0) return true;
+    if (res==sz-1) return false; // beyond the end of the set
+    return (r[res+1]<b);
+    }
+  @Deprecated
+  public boolean containsAny (long a,long b)
+    { return overlaps(a,b); }
+  /** Returns true if the set completely contains "other", else false. */
+  public boolean contains (RangeSet other)
+    { return generalAllOrNothing(this,other,false,true); }
+  @Deprecated
+  public boolean containsAll (RangeSet other)
+    { return contains(other); }
+  /** Returns true if there is overlap between the set and "other",
+      else false. */
+  public boolean overlaps (RangeSet other)
+    { return !generalAllOrNothing(this,other,true,true); }
+  @Deprecated
+  public boolean containsAny (RangeSet other)
+    { return overlaps(other); }
+  /** Returns true the object represents an identical set of ranges as obj. */
+  public boolean equals(Object obj) {
+    if (this == obj)
+      return true;
+    if ((obj==null) || (!(obj instanceof RangeSet)))
+      return false;
+    RangeSet other = (RangeSet) obj;
+    if (other.sz!=sz) return false;
+    for (int i=0; i<sz; ++i)
+      if (other.r[i]!=r[i]) return false;
+    return true;
+    }
+  public int hashCode()
+    {
+    int result = Integer.valueOf(sz).hashCode();
+    for (int i=0; i<sz; ++i)
+      result = 31 * result + Long.valueOf(r[sz]).hashCode();
+    return result;
+    }
+
+  /** @return total number of values (not ranges) in the set. */
+  public long nval()
+    {
+    long res = 0;
+    for (int i=0; i<sz; i+=2)
+      res+=r[i+1]-r[i];
+    return res;
+    }
+
+  /** Internal helper function for building unions and differences of the
+      RangeSet with a single range. */
+  private void addRemove (long a, long b, int v)
+    {
+    int pos1=iiv(a), pos2=iiv(b);
+    if ((pos1>=0) && (r[pos1]==a)) --pos1;
+    // first to delete is at pos1+1; last is at pos2
+    boolean insert_a = (pos1&1)==v;
+    boolean insert_b = (pos2&1)==v;
+    int rmstart=pos1+1+(insert_a ? 1 : 0);
+    int rmend  =pos2-(insert_b?1:0);
+
+    if (((rmend-rmstart)&1)==0)
+      throw new IllegalArgumentException("cannot happen: "+rmstart+" "+rmend);
+
+    if (insert_a && insert_b && (pos1+1>pos2)) // insert
+      {
+      ensureCapacity(sz+2);
+      System.arraycopy(r,pos1+1,r,pos1+3,sz-pos1-1); // move to right
+      r[pos1+1]=a;
+      r[pos1+2]=b;
+      sz+=2;
+      }
+    else
+      {
+      if (insert_a) r[pos1+1]=a;
+      if (insert_b) r[pos2]=b;
+      if (rmstart!=rmend+1)
+        System.arraycopy(r,rmend+1,r,rmstart,sz-rmend-1); // move to left
+      sz-=rmend-rmstart+1;
+      }
+    }
+
+  /** After this operation, the RangeSet contains the intersection of itself and
+      [a;b[. */
+  public void intersect (long a, long b)
+    {
+    int pos1=iiv(a), pos2=iiv(b);
+    if ((pos2>=0) && (r[pos2]==b)) --pos2;
+    // delete all up to pos1 (inclusive); and starting from pos2+1
+    boolean insert_a = (pos1&1)==0;
+    boolean insert_b = (pos2&1)==0;
+
+    // cut off end
+    sz=pos2+1;
+    if (insert_b) r[sz++]=b;
+
+    // erase start
+    if (insert_a) r[pos1--]=a;
+    if (pos1>=0)
+      System.arraycopy(r,pos1+1,r,0,sz-pos1-1); // move to left
+
+    sz-=pos1+1;
+    if ((sz&1)!=0)
+      throw new IllegalArgumentException("cannot happen");
+    }
+
+  /** After this operation, the RangeSet contains the union of itself and
+      [a;b[. */
+  public void add (long a, long b)
+    { if ((sz==0)||(a>=r[sz-1])) append(a,b); else addRemove(a,b,1); }
+  /** After this operation, the RangeSet contains the union of itself and
+      [a;a+1[. */
+  public void add (long a)
+    { if ((sz==0)||(a>=r[sz-1])) append(a,a+1); else addRemove(a,a+1,1); }
+  /** After this operation, the RangeSet contains the difference of itself and
+      [a;b[. */
+  public void remove (long a, long b)
+    { addRemove(a,b,0); }
+  /** After this operation, the RangeSet contains the difference of itself and
+      [a;a+1[. */
+  public void remove (long a)
+    { addRemove(a,a+1,0); }
+
+  /** Creates an array containing all the numbers in the RangeSet.
+      Not recommended, because the arrays can become prohibitively large.
+      It is preferrable to use a ValueIterator or explicit loops. */
+  public long[] toArray(){
+    long[] res = new long[(int)nval()];
+    int ofs=0;
+    for (int i=0; i<sz; i+=2)
+      for (long j=r[i]; j<r[i+1]; ++j)
+        res[ofs++]=j;
+    return res;
+    }
+  public static RangeSet fromArray(long[]v){
+    RangeSet res = new RangeSet();
+    for (int i=0; i<v.length; i++)
+      res.append(v[i]);
+    return res;
+    }
+
+  public String toString()
+    {
+    StringBuilder s = new StringBuilder();
+    s.append("{ ");
+    for (int i=0; i<sz; i+=2)
+      {
+      s.append("[").append(r[i]).append(";").append(r[i + 1]).append("[");
+      if (i<sz-2) s.append(",");
+      }
+    s.append(" }");
+    return s.toString();
+    }
+
+  /** Returns a ValueIterator, which iterates over all individual numbers
+      in the RangeSet. */
+  public ValueIterator valueIterator()
+    {
+    if(sz == 0) return EMPTY_ITER;
+    return new ValueIterator()
+      {
+      int pos = 0;
+      long value = (sz>0) ? r[0] : 0;
+
+      public boolean hasNext()
+        { return (pos<sz); }
+
+      public long next() {
+        if (pos>sz)
+          throw new NoSuchElementException();
+        long ret = value;
+        if (++value==r[pos+1])
+          {
+          pos+=2;
+          if (pos<sz)
+            value = r[pos];
+          }
+        return ret;
+        }
+      };
+    }
+
+  /** Returns a compressed representation of the RangeSet, using interpolative
+      coding. */
+  public byte[] toCompressed() throws Exception
+    { return Compressor.interpol_encode (r, 0, sz); }
+  /** Returns a RangeSet obtained by decompressing a byte array which was
+      originally generated by toCompressed(). */
+  public static RangeSet fromCompressed (byte[] data) throws Exception
+    { return new RangeSet(Compressor.interpol_decode(data)); }
+  }
diff -Nru healpix-java-3.40/src/java/src/healpix/essentials/Scheme.java healpix-java-3.50/src/java/src/healpix/essentials/Scheme.java
--- healpix-java-3.40/src/java/src/healpix/essentials/Scheme.java	1969-12-31 19:00:00.000000000 -0500
+++ healpix-java-3.50/src/java/src/healpix/essentials/Scheme.java	2012-05-21 09:06:23.000000000 -0400
@@ -0,0 +1,9 @@
+package healpix.essentials;
+
+/** The Healpix pixel ordering scheme. */
+public enum Scheme {
+  /** RING ordering. */
+  RING,
+  /** NESTED ordering. */
+  NESTED
+}
diff -Nru healpix-java-3.40/src/java/src/healpix/essentials/test/CompressorTest.java healpix-java-3.50/src/java/src/healpix/essentials/test/CompressorTest.java
--- healpix-java-3.40/src/java/src/healpix/essentials/test/CompressorTest.java	1969-12-31 19:00:00.000000000 -0500
+++ healpix-java-3.50/src/java/src/healpix/essentials/test/CompressorTest.java	2015-07-05 02:10:50.000000000 -0400
@@ -0,0 +1,46 @@
+/*
+ *  This file is part of Healpix Java.
+ *
+ *  This code 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 code 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 code; 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.sourceforge.net
+ */
+package healpix.essentials.test;
+
+import healpix.essentials.Compressor;
+import junit.framework.TestCase;
+import java.io.*;
+import java.util.Random;
+
+/** Tests for the linear interpolative coding compression
+
+    @copyright 2015 Max-Planck-Society
+    @author Martin Reinecke */
+public class CompressorTest extends TestCase {
+
+  public void testCompressDecompress() throws Exception
+    {
+    int num=100000;
+    Random randomGenerator = new Random();
+    long[] input=new long[num];
+    input[0]=0;
+    for (int i=1; i<num; ++i) input[i]=input[i-1]+1+randomGenerator.nextInt(100);
+    byte[] compressed=Compressor.interpol_encode(input,0,input.length);
+    long[] output=Compressor.interpol_decode(compressed);
+    assertEquals("inconsistency",input.length,output.length);
+    for (int i=0; i<output.length; ++i)
+      assertEquals("inconsistency",input[i],output[i]);
+    }
+}
diff -Nru healpix-java-3.40/src/java/src/healpix/essentials/test/FastMathPerfTest.java healpix-java-3.50/src/java/src/healpix/essentials/test/FastMathPerfTest.java
--- healpix-java-3.40/src/java/src/healpix/essentials/test/FastMathPerfTest.java	1969-12-31 19:00:00.000000000 -0500
+++ healpix-java-3.50/src/java/src/healpix/essentials/test/FastMathPerfTest.java	2015-07-05 02:10:50.000000000 -0400
@@ -0,0 +1,104 @@
+package healpix.essentials.test;
+
+import junit.framework.TestCase;
+import java.text.DecimalFormat;
+import static healpix.essentials.FastMath.*;
+
+/** FastMath benchmarking code
+
+    @copyright 2014 Max-Planck-Society
+    @author Martin Reinecke */
+public class FastMathPerfTest extends TestCase
+  {
+  static private final DecimalFormat form = new DecimalFormat("##0.00");
+  final int ncomp=10000000;
+
+  public void test_perf_math()
+    {
+    System.out.println("Rough performance test of math functions");
+    long cnt, tstart;
+    double dummy=0, di, time;
+    di=1./ncomp;
+    tstart = System.nanoTime();
+    cnt=0;
+    for (double i=0; i<1; i+=di)
+       { dummy+=Math.sqrt(i); ++cnt; }
+    time = 1e-9*(System.nanoTime()-tstart);
+    System.out.println("sqrt: " + form.format(cnt/time*1e-6) + "MOps/s");
+    di=4*Math.PI/ncomp;
+    tstart = System.nanoTime();
+    cnt=0;
+    for (double i=-2*Math.PI; i<2*Math.PI; i+=di)
+      { dummy+=Math.sin(i); ++cnt; }
+    time = 1e-9*(System.nanoTime()-tstart);
+    System.out.println("sin : " + form.format(cnt/time*1e-6) + "MOps/s");
+    tstart = System.nanoTime();
+    cnt=0;
+    for (double i=-2*Math.PI; i<2*Math.PI; i+=di)
+      { dummy+=Math.cos(i); ++cnt; }
+    time = 1e-9*(System.nanoTime()-tstart);
+    System.out.println("cos : " + form.format(cnt/time*1e-6) + "MOps/s");
+    di=2./ncomp;
+    tstart = System.nanoTime();
+    cnt=0;
+    for (double i=-1; i<1; i+=di)
+      { dummy+=Math.acos(i); ++cnt; }
+    time = 1e-9*(System.nanoTime()-tstart);
+    System.out.println("acos: " + form.format(cnt/time*1e-6) + "MOps/s");
+    di=1000./ncomp;
+    tstart = System.nanoTime();
+    cnt=0;
+    for (double i=-500; i<500; i+=di)
+      { dummy+=Math.atan(i); ++cnt; }
+    time = 1e-9*(System.nanoTime()-tstart);
+    System.out.println("atan: " + form.format(cnt/time*1e-6) + "MOps/s");
+    di=1000./ncomp;
+    tstart = System.nanoTime();
+    cnt=0;
+    for (double i=-500; i<500; i+=di)
+      { dummy+=Math.atan2(i,2.9); ++cnt; }
+    time = 1e-9*(System.nanoTime()-tstart);
+    System.out.println("atan2: " + form.format(cnt/time*1e-6) + "MOps/s");
+    di=1000./ncomp;
+    }
+  public void test_perf_fastmath()
+    {
+    System.out.println("Rough performance test of fast math functions");
+    long cnt,tstart;
+    double dummy=0, di, time;
+    di=4*Math.PI/ncomp;
+    tstart = System.nanoTime();
+    cnt=0;
+    for (double i=-2*Math.PI; i<2*Math.PI; i+=di)
+      { dummy+=sin(i); ++cnt; }
+    time = 1e-9*(System.nanoTime()-tstart);
+    System.out.println("sin : " + form.format(cnt/time*1e-6) + "MOps/s");
+    tstart = System.nanoTime();
+    cnt=0;
+    for (double i=-2*Math.PI; i<2*Math.PI; i+=di)
+      { dummy+=cos(i); ++cnt; }
+    time = 1e-9*(System.nanoTime()-tstart);
+    System.out.println("cos : " + form.format(cnt/time*1e-6) + "MOps/s");
+    di=2./ncomp;
+    tstart = System.nanoTime();
+    cnt=0;
+    for (double i=-1; i<1; i+=di)
+      { dummy+=acos(i); ++cnt; }
+    time = 1e-9*(System.nanoTime()-tstart);
+    System.out.println("acos: " + form.format(cnt/time*1e-6) + "MOps/s");
+    di=1000./ncomp;
+    tstart = System.nanoTime();
+    cnt=0;
+    for (double i=-500; i<500; i+=di)
+      { dummy+=atan(i); ++cnt; }
+    time = 1e-9*(System.nanoTime()-tstart);
+    System.out.println("atan: " + form.format(cnt/time*1e-6) + "MOps/s");
+    di=1000./ncomp;
+    tstart = System.nanoTime();
+    cnt=0;
+    for (double i=-500; i<500; i+=di)
+      { dummy+=atan2(i,2.9); ++cnt; }
+    time = 1e-9*(System.nanoTime()-tstart);
+    System.out.println("atan2: " + form.format(cnt/time*1e-6) + "MOps/s");
+    }
+  }
diff -Nru healpix-java-3.40/src/java/src/healpix/essentials/test/FastMathTest.java healpix-java-3.50/src/java/src/healpix/essentials/test/FastMathTest.java
--- healpix-java-3.40/src/java/src/healpix/essentials/test/FastMathTest.java	1969-12-31 19:00:00.000000000 -0500
+++ healpix-java-3.50/src/java/src/healpix/essentials/test/FastMathTest.java	2012-05-21 09:06:23.000000000 -0400
@@ -0,0 +1,111 @@
+package healpix.essentials.test;
+
+import junit.framework.TestCase;
+import java.text.DecimalFormat;
+import static healpix.essentials.FastMath.*;
+
+/** A class to perform correctness and speed tests for FastMath class
+ *
+ * @author Naoki Shibata
+ */
+public class FastMathTest extends TestCase
+  {
+  private static final double p0=+0.0, m0=-0.0, pinf=Double.POSITIVE_INFINITY,
+    minf=Double.NEGATIVE_INFINITY, nan=Double.NaN;
+
+  private static boolean isPlusZero(double x)
+    { return x == 0 && Math.copySign(1, x) == 1; }
+  private static boolean isMinusZero(double x)
+    { return x == 0 && Math.copySign(1, x) == -1; }
+
+  private static boolean cmpDenorm(double x, double y) {
+    if (Double.isNaN(x) && Double.isNaN(y)) return true;
+    if (x == pinf && y == pinf) return true;
+    if (x == minf && y == minf) return true;
+    if (!Double.isNaN(x) && !Double.isNaN(y) &&
+        !Double.isInfinite(x) && !Double.isInfinite(y))
+      return true;
+    return false;
+    }
+
+  private static void ulptest (double v1, double v2, double ulp)
+    { assertTrue ("inconsistency",Math.abs((v1-v2)/Math.ulp(v2))<=ulp); }
+
+  private static void check1 (double d)
+    {
+    ulptest (sin(d),Math.sin(d),2.);
+    ulptest (cos(d),Math.cos(d),2.);
+    ulptest (atan(d),Math.atan(d),2.);
+    }
+  private static void check2 (double d)
+    {
+    ulptest (asin(d),Math.asin(d),3.);
+    ulptest (acos(d),Math.acos(d),2.);
+    }
+
+  public void testmain() throws Exception
+    {
+    assertEquals("inconsistency", Math.PI,(atan2(p0, m0)));
+    assertEquals("inconsistency",-Math.PI,(atan2(m0, m0)));
+    assertTrue("inconsistency",isPlusZero(atan2(p0, p0)));
+    assertTrue("inconsistency",isMinusZero(atan2(m0, p0)));
+    assertEquals("inconsistency",3*Math.PI/4,atan2(pinf, minf));
+    assertEquals("inconsistency",-3*Math.PI/4,atan2(minf, minf));
+    assertEquals("inconsistency",Math.PI/4,atan2(pinf, pinf));
+    assertEquals("inconsistency",-Math.PI/4,atan2(minf, pinf));
+    assertTrue("inconsistency",Double.isNaN(atan2(nan,nan)));
+
+    double[] a = { 100000.5, 100000, 3, 2.5, 2, 1.5, 1.0, 0.5 };
+    double[] b = { nan, pinf, minf };
+    double[] c = { nan, pinf, minf, 2, -2 };
+
+    for(int i=0;i<a.length;i++)
+      {
+      assertEquals("inconsistency",Math.PI,atan2(p0, -a[i]));
+      assertEquals("inconsistency",-Math.PI,atan2(m0, -a[i]));
+      assertEquals("inconsistency",-Math.PI/2,atan2(-a[i], p0));
+      assertEquals("inconsistency",-Math.PI/2,atan2(-a[i], m0));
+      assertEquals("inconsistency",Math.PI/2,atan2(a[i], p0));
+      assertEquals("inconsistency",Math.PI/2,atan2(a[i], m0));
+      assertEquals("inconsistency",Math.PI/2,atan2(pinf,a[i]));
+      assertEquals("inconsistency",Math.PI/2,atan2(pinf,-a[i]));
+      assertEquals("inconsistency",-Math.PI/2,atan2(minf,a[i]));
+      assertEquals("inconsistency",-Math.PI/2,atan2(minf,-a[i]));
+      assertEquals("inconsistency",Math.PI,atan2(a[i],minf));
+      assertEquals("inconsistency",-Math.PI,atan2(-a[i],minf));
+      assertEquals("inconsistency",p0,atan2(a[i],pinf));
+      assertEquals("inconsistency",m0,atan2(-a[i],pinf));
+      assertTrue("inconsistency",Double.isNaN(atan2(a[i],nan)));
+      assertTrue("inconsistency",Double.isNaN(atan2(-a[i],nan)));
+      assertTrue("inconsistency",Double.isNaN(atan2(nan,a[i])));
+      assertTrue("inconsistency",Double.isNaN(atan2(nan,-a[i])));
+      }
+
+    for(int i=0;i<b.length;i++)
+      {
+      assertTrue("inconsistency",cmpDenorm(sin(b[i]), Math.sin(b[i])));
+      assertTrue("inconsistency",cmpDenorm(cos(b[i]), Math.cos(b[i])));
+      assertTrue("inconsistency",cmpDenorm(atan(b[i]), Math.atan(b[i])));
+      }
+    for(int i=0;i<c.length;i++)
+      {
+      assertTrue("inconsistency",cmpDenorm(asin(c[i]), Math.asin(c[i])));
+      assertTrue("inconsistency",cmpDenorm(acos(c[i]), Math.acos(c[i])));
+      }
+
+    for(double d = -10;d < 10;d += 0.000001)
+      check1(d);
+    for(double d = -10000;d < 10000;d += 0.001)
+      check1(d);
+
+    for(double d = -1;d < 1;d += 0.0000001)
+      check2(d);
+
+    for(double y = -10;y < 10;y += 0.01)
+        for(double x = -10;x < 10;x += 0.01)
+          ulptest (atan2(y,x),Math.atan2(y,x),2.);
+    for(double y = -1000;y < 1000;y += 1.01)
+        for(double x = -1000;x < 1000;x += 1.01)
+          ulptest (atan2(y,x),Math.atan2(y,x),2.);
+    }
+  }
diff -Nru healpix-java-3.40/src/java/src/healpix/essentials/test/FitsUtilTest.java healpix-java-3.50/src/java/src/healpix/essentials/test/FitsUtilTest.java
--- healpix-java-3.40/src/java/src/healpix/essentials/test/FitsUtilTest.java	1969-12-31 19:00:00.000000000 -0500
+++ healpix-java-3.50/src/java/src/healpix/essentials/test/FitsUtilTest.java	2015-07-05 02:10:50.000000000 -0400
@@ -0,0 +1,64 @@
+/*
+ *  This file is part of Healpix Java.
+ *
+ *  This code 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 code 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 code; 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.sourceforge.net
+ */
+package healpix.essentials.test;
+
+import healpix.essentials.*;
+
+import junit.framework.TestCase;
+import java.util.UUID;
+import java.io.File;
+
+/** Tests for the FitsUtil class
+
+    @copyright 2014 Max-Planck-Society
+    @author Martin Reinecke */
+public class FitsUtilTest extends TestCase
+  {
+  public void testHPmapf() throws Exception
+    {
+    String name = UUID.randomUUID().toString()+".fits";
+    HealpixMapFloat hpmf = new HealpixMapFloat(128,Scheme.NESTED);
+    for (long i=0; i<hpmf.getNpix(); ++i)
+      hpmf.setPixel(i,(float)i);
+    FitsUtil.writeFloatMap(hpmf,name);
+    hpmf.setNsideAndScheme (64, Scheme.RING);
+    hpmf=FitsUtil.getFloatMap(name,2,1);
+    new File(name).delete();
+    assertEquals("Scheme problem",Scheme.NESTED,hpmf.getScheme());
+    assertEquals("Nside problem",128,hpmf.getNside());
+    for (long i=0; i<hpmf.getNpix(); ++i)
+      assertEquals("Value problem",(float)i,hpmf.getPixel(i));
+    }
+  public void testHPmapd() throws Exception
+    {
+    String name = UUID.randomUUID().toString()+".fits";
+    HealpixMapDouble hpmd = new HealpixMapDouble(128,Scheme.NESTED);
+    for (long i=0; i<hpmd.getNpix(); ++i)
+      hpmd.setPixel(i,(double)i);
+    FitsUtil.writeDoubleMap(hpmd,name);
+    hpmd.setNsideAndScheme (64, Scheme.RING);
+    hpmd=FitsUtil.getDoubleMap(name,2,1);
+    new File(name).delete();
+    assertEquals("Scheme problem",Scheme.NESTED,hpmd.getScheme());
+    assertEquals("Nside problem",128,hpmd.getNside());
+    for (long i=0; i<hpmd.getNpix(); ++i)
+      assertEquals("Value problem",(double)i,hpmd.getPixel(i));
+    }
+  }
diff -Nru healpix-java-3.40/src/java/src/healpix/essentials/test/FxyfTest.java healpix-java-3.50/src/java/src/healpix/essentials/test/FxyfTest.java
--- healpix-java-3.40/src/java/src/healpix/essentials/test/FxyfTest.java	1969-12-31 19:00:00.000000000 -0500
+++ healpix-java-3.50/src/java/src/healpix/essentials/test/FxyfTest.java	2015-07-05 02:10:50.000000000 -0400
@@ -0,0 +1,49 @@
+/*
+ *  This file is part of Healpix Java.
+ *
+ *  This code 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 code 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 code; 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.sourceforge.net
+ */
+package healpix.essentials.test;
+
+import junit.framework.TestCase;
+import java.util.Random;
+
+import healpix.essentials.*;
+
+/** Tests for the Fxyf class
+
+    @copyright 2015 Max-Planck-Society
+    @author Martin Reinecke */
+public class FxyfTest extends TestCase {
+
+  public void testFxyf() throws Exception
+    {
+    System.out.println("Testing Fxyf");
+    for (int i=0; i<12; ++i)
+      for (int j=0; j<=100; ++j)
+        for (int k=0; k<=100; ++k)
+          {
+          double fx=(0.01*j)*(1-1e-14)+.5e-14,
+                 fy=(0.01*k)*(1-1e-14)+.5e-14;
+          Fxyf res=new Fxyf(new Fxyf(fx,fy,i).toVec3());
+          assertEquals (res.face,i);
+          assertEquals (res.fx,fx,5e-15);
+          assertEquals (res.fy,fy,5e-15);
+          }
+    }
+
+  }
diff -Nru healpix-java-3.40/src/java/src/healpix/essentials/test/HealpixBasePerfTest.java healpix-java-3.50/src/java/src/healpix/essentials/test/HealpixBasePerfTest.java
--- healpix-java-3.40/src/java/src/healpix/essentials/test/HealpixBasePerfTest.java	1969-12-31 19:00:00.000000000 -0500
+++ healpix-java-3.50/src/java/src/healpix/essentials/test/HealpixBasePerfTest.java	2015-07-05 02:10:50.000000000 -0400
@@ -0,0 +1,282 @@
+/*
+ *  This file is part of Healpix Java.
+ *
+ *  This code 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 code 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 code; 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.sourceforge.net
+ */
+package healpix.essentials.test;
+
+import junit.framework.TestCase;
+import java.text.DecimalFormat;
+
+import healpix.essentials.*;
+
+/** Benchmarks for the HealpixBase class
+
+    @copyright 2014 Max-Planck-Society
+    @author Martin Reinecke */
+public class HealpixBasePerfTest extends TestCase
+  {
+  static private final DecimalFormat form = new DecimalFormat("##0.00");
+  static private final int nsteps=100000; // influences number of performance tests
+
+  private double subtest_perf_neighbours(String name, Scheme scheme)
+    throws Exception
+    {
+    long cnt=0;
+    double dummy=0;
+    long tstart = System.nanoTime();
+    int omax=HealpixBase.order_max;
+    for (int order=0; order<=omax; ++order)
+      {
+      HealpixBase base = new HealpixBase (1L<<order,scheme);
+      long dpix=Math.max(base.getNpix()/nsteps,1L);
+      for (long pix=0; pix<base.getNpix(); pix+=dpix)
+        {
+        long nres[] = base.neighbours(pix);
+        dummy+=nres[0];
+        ++cnt;
+        }
+      }
+    double time = 1e-9*(System.nanoTime()-tstart);
+    System.out.println(name + ": " + form.format(cnt/time*1e-6) + "MOps/s");
+    return dummy;
+    }
+
+  private double subtest_perf_pix2ang(String name, Scheme scheme)
+    throws Exception
+    {
+    long cnt=0;
+    double dummy=0;
+    long tstart = System.nanoTime();
+    int omax=HealpixBase.order_max;
+    for (int order=0; order<=omax; ++order)
+      {
+      HealpixBase base = new HealpixBase (1L<<order,scheme);
+      long dpix=Math.max(base.getNpix()/nsteps,1L);
+      for (long pix=0; pix<base.getNpix(); pix+=dpix)
+        {
+        Pointing p=base.pix2ang(pix);
+        dummy+=p.theta+p.phi;
+        ++cnt;
+        }
+      }
+    double time = 1e-9*(System.nanoTime()-tstart);
+    System.out.println(name + ": " + form.format(cnt/time*1e-6) + "MOps/s");
+    return dummy;
+    }
+
+  private double subtest_perf_pix2vec(String name, Scheme scheme)
+    throws Exception
+    {
+    long cnt=0;
+    double dummy=0;
+    long tstart = System.nanoTime();
+    int omax=HealpixBase.order_max;
+    for (int order=0; order<=omax; ++order)
+      {
+      HealpixBase base = new HealpixBase (1L<<order,scheme);
+      long dpix=Math.max(base.getNpix()/nsteps,1L);
+      for (long pix=0; pix<base.getNpix(); pix+=dpix)
+        {
+        Vec3 v=base.pix2vec(pix);
+        dummy+=v.x+v.y+v.z;
+        ++cnt;
+        }
+      }
+    double time = 1e-9*(System.nanoTime()-tstart);
+    System.out.println(name + ": " + form.format(cnt/time*1e-6) + "MOps/s");
+    return dummy;
+    }
+
+  private double subtest_perf_pix2zphi(String name, Scheme scheme)
+    throws Exception
+    {
+    long cnt=0;
+    double dummy=0;
+    long tstart = System.nanoTime();
+    int omax=HealpixBase.order_max;
+    for (int order=0; order<=omax; ++order)
+      {
+      HealpixBase base = new HealpixBase (1L<<order,scheme);
+      long dpix=Math.max(base.getNpix()/nsteps,1L);
+      for (long pix=0; pix<base.getNpix(); pix+=dpix)
+        {
+        Zphi blah=base.pix2zphi(pix);
+        dummy+=blah.z;
+        ++cnt;
+        }
+      }
+    double time = 1e-9*(System.nanoTime()-tstart);
+    System.out.println(name + ": " + form.format(cnt/time*1e-6) + "MOps/s");
+    return dummy;
+    }
+
+  private double subtest_perf_ring2nest() throws Exception
+    {
+    long cnt=0;
+    double dummy=0;
+    long tstart = System.nanoTime();
+    int omax=HealpixBase.order_max;
+    for (int order=0; order<=omax; ++order)
+      {
+      HealpixBase base = new HealpixBase (1L<<order,Scheme.RING);
+      long dpix=Math.max(base.getNpix()/nsteps,1L);
+      for (long pix=0; pix<base.getNpix(); pix+=dpix)
+        {
+        dummy+=base.ring2nest(pix);
+        ++cnt;
+        }
+      }
+    double time = 1e-9*(System.nanoTime()-tstart);
+    System.out.println("ring2nest       : " + form.format(cnt/time*1e-6) + "MOps/s");
+    return dummy;
+    }
+
+  private double subtest_perf_nest2ring() throws Exception
+    {
+    long cnt=0;
+    double dummy=0;
+    long tstart = System.nanoTime();
+    int omax=HealpixBase.order_max;
+    for (int order=0; order<=omax; ++order)
+      {
+      HealpixBase base = new HealpixBase (1L<<order,Scheme.RING);
+      long dpix=Math.max(base.getNpix()/nsteps,1L);
+      for (long pix=0; pix<base.getNpix(); pix+=dpix)
+        {
+        dummy+=base.nest2ring(pix);
+        ++cnt;
+        }
+      }
+    double time = 1e-9*(System.nanoTime()-tstart);
+    System.out.println("nest2ring       : " + form.format(cnt/time*1e-6) + "MOps/s");
+    return dummy;
+    }
+
+  private double subtest_perf_ang2pix(String name, Scheme scheme)
+    throws Exception
+    {
+    long cnt=0;
+    double dummy=0;
+    long tstart = System.nanoTime();
+    int omax=HealpixBase.order_max;
+    double dth=Math.PI/Math.sqrt(nsteps);
+    double dph=Constants.twopi/Math.sqrt(nsteps);
+    for (int order=0; order<=omax; ++order)
+      {
+      HealpixBase base = new HealpixBase (1L<<order,scheme);
+      for (double theta=0; theta<Math.PI; theta+=dth)
+        for (double phi=0; phi<2*Math.PI; phi+=dph)
+          {
+          dummy+=base.ang2pix(new Pointing(theta+1e-15*phi,phi));
+          ++cnt;
+          }
+      }
+    double time = 1e-9*(System.nanoTime()-tstart);
+    System.out.println(name+": " + form.format(cnt/time*1e-6) + "MOps/s");
+    return dummy;
+    }
+
+  private double subtest_perf_zphi2pix(String name, Scheme scheme)
+    throws Exception
+    {
+    long cnt=0;
+    double dummy=0;
+    long tstart = System.nanoTime();
+    int omax=HealpixBase.order_max;
+    double dz=2./Math.sqrt(nsteps);
+    double dph=Constants.twopi/Math.sqrt(nsteps);
+    for (int order=0; order<=omax; ++order)
+      {
+      HealpixBase base = new HealpixBase (1L<<order,scheme);
+      for (double z=-1; z<1; z+=dz)
+        for (double phi=0; phi<Constants.twopi; phi+=dph)
+          {
+          dummy+=base.zphi2pix(new Zphi(z,phi));
+          ++cnt;
+          }
+      }
+    double time = 1e-9*(System.nanoTime()-tstart);
+    System.out.println(name+": " + form.format(cnt/time*1e-6) + "MOps/s");
+    return dummy;
+    }
+
+  private double subtest_perf_query_disc(String name,
+    Scheme scheme) throws Exception
+    {
+    long cnt=0;
+    double dummy=0;
+    HealpixBase base = new HealpixBase (1024,scheme);
+    long tstart = System.nanoTime();
+    for (int m=0; m<1000; ++m)
+      {
+      RangeSet lrs=base.queryDisc(new Pointing(new Vec3(1,0,0)),Constants.halfpi/9.);
+      dummy+=lrs.nranges();
+      ++cnt;
+      }
+    double time = 1e-9*(System.nanoTime()-tstart);
+    System.out.println(name+": " + form.format(cnt/time*1e-3) + "kOps/s");
+    return dummy;
+    }
+
+  private double subtest_perf_query_polygon(String name,
+    Scheme scheme) throws Exception
+    {
+    long cnt=0;
+    double dummy=0;
+    HealpixBase base = new HealpixBase (1024,scheme);
+    Pointing[] corner = new Pointing[4];
+    corner[0]=new Pointing(new Vec3(1,0.01,0.01));
+    corner[1]=new Pointing(new Vec3(1,1,-0.3));
+    corner[2]=new Pointing(new Vec3(0.01,1,0.01));
+    corner[3]=new Pointing(new Vec3(0.01,0.01,1));
+    long tstart = System.nanoTime();
+    for (int m=0; m<1000; ++m)
+      {
+      RangeSet lrs=base.queryPolygon(corner);
+      dummy+=lrs.nranges();
+      ++cnt;
+      }
+    double time = 1e-9*(System.nanoTime()-tstart);
+    System.out.println(name+": " + form.format(cnt/time*1e-3) + "kOps/s");
+    return dummy;
+    }
+
+  public void test_perf() throws Exception
+    {
+    System.out.println("Performance tests of HealpixBase methods");
+    double d=0;
+    d+=subtest_perf_neighbours("neighbours(NEST)",Scheme.NESTED);
+    d+=subtest_perf_neighbours("neighbours(RING)",Scheme.RING);
+    d+=subtest_perf_pix2ang   ("pix2ang   (NEST)",Scheme.NESTED);
+    d+=subtest_perf_pix2ang   ("pix2ang   (RING)",Scheme.RING);
+    d+=subtest_perf_ang2pix   ("ang2pix   (NEST)",Scheme.NESTED);
+    d+=subtest_perf_ang2pix   ("ang2pix   (RING)",Scheme.RING);
+    d+=subtest_perf_pix2vec   ("pix2vec   (NEST)",Scheme.NESTED);
+    d+=subtest_perf_pix2vec   ("pix2vec   (RING)",Scheme.RING);
+    d+=subtest_perf_pix2zphi  ("pix2zphi  (NEST)",Scheme.NESTED);
+    d+=subtest_perf_pix2zphi  ("pix2zphi  (RING)",Scheme.RING);
+    d+=subtest_perf_zphi2pix  ("zphi2pix  (NEST)",Scheme.NESTED);
+    d+=subtest_perf_zphi2pix  ("zphi2pix  (RING)",Scheme.RING);
+    d+=subtest_perf_ring2nest();
+    d+=subtest_perf_nest2ring();
+    d+=subtest_perf_query_disc("disc      (NEST)",Scheme.NESTED);
+    d+=subtest_perf_query_disc("disc      (RING)",Scheme.RING);
+    d+=subtest_perf_query_polygon("polygon   (NEST)",Scheme.NESTED);
+    d+=subtest_perf_query_polygon("polygon   (RING)",Scheme.RING);
+    }
+  }
diff -Nru healpix-java-3.40/src/java/src/healpix/essentials/test/HealpixBaseTest.java healpix-java-3.50/src/java/src/healpix/essentials/test/HealpixBaseTest.java
--- healpix-java-3.40/src/java/src/healpix/essentials/test/HealpixBaseTest.java	1969-12-31 19:00:00.000000000 -0500
+++ healpix-java-3.50/src/java/src/healpix/essentials/test/HealpixBaseTest.java	2015-09-12 05:25:53.000000000 -0400
@@ -0,0 +1,353 @@
+/*
+ *  This file is part of Healpix Java.
+ *
+ *  This code 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 code 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 code; 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.sourceforge.net
+ */
+package healpix.essentials.test;
+
+import junit.framework.TestCase;
+import java.util.Random;
+import java.text.DecimalFormat;
+
+import healpix.essentials.*;
+
+/** @author Martin Reinecke */
+public class HealpixBaseTest extends TestCase {
+
+  static private final int nsamples=10000; // influences number of correctness tests
+  static private final DecimalFormat form = new DecimalFormat("##0.00");
+
+  private Zphi random_zphi(Random rng)
+    { return new Zphi(2*rng.nextDouble()-1,2*Math.PI*rng.nextDouble()); }
+
+  private Pointing random_dir(Random rng)
+    { return new Pointing(Math.acos(2*rng.nextDouble()-1),2*Math.PI*rng.nextDouble()); }
+
+  public void test_boundaries()throws Exception
+    {
+    System.out.println("Testing whether the boundary shapes look sane");
+
+    for (int nside=1; nside<=5; ++nside)
+      {
+      HealpixBase base=new HealpixBase(nside,Scheme.RING);
+      for (int pix=0; pix<base.getNpix(); ++pix)
+        {
+        for (int res=1; res<=50; res+=7)
+          {
+          Vec3[] points = base.boundaries(pix,res);
+          double dmin=1e30, dmax=-1e30;
+          for (int i=0; i<points.length; ++i)
+            {
+            double dv=(points[i].sub(points[(i+1)%points.length])).length();
+            assertTrue("error in boundaries",dv!=0);
+            dmin = Math.min(dv,dmin);
+            dmax = Math.max(dv,dmax);
+            }
+          assertTrue("error in boundaries",dmax/dmin<=2);
+          }
+        }
+      }
+    }
+
+  public void test_accuracy()throws Exception
+    {
+    System.out.println("Testing accuracy near the poles");
+
+    for (int order=0; order<=HealpixBase.order_max; ++order)
+      {
+      HealpixBase base = new HealpixBase (1L<<order,Scheme.RING);
+      assertTrue("incorrect pix2ang",base.pix2ang(1).theta>0.0);
+      }
+    }
+
+  public void test_ringnestring()throws Exception
+    {
+    System.out.println("Testing identity ring2nest(nest2ring(i))==i");
+    Random rng = new Random(5);
+
+    for (int order=0; order<=HealpixBase.order_max; ++order)
+      {
+      HealpixBase base = new HealpixBase (1L<<order,Scheme.RING);
+      for (int m=0; m<nsamples; ++m)
+        {
+        long pix = (long)(rng.nextDouble()*base.getNpix());
+        assertEquals ("ringnestring problem",
+          base.ring2nest(base.nest2ring(pix)),pix);
+        }
+      }
+    }
+
+  public void test_pixzphipix()throws Exception
+    {
+    System.out.println("Testing identity pix2zphi(zphi2pix(i))==i");
+    int omax=HealpixBase.order_max;
+    Random rng = new Random(5);
+    for (int order=0; order<=omax; ++order)
+      {
+      HealpixBase base1 = new HealpixBase (1L<<order,Scheme.RING),
+                  base2 = new HealpixBase (1L<<order,Scheme.NESTED);
+      for (int m=0; m<nsamples; ++m)
+        {
+        long pix = (long)(rng.nextDouble()*base1.getNpix());
+        assertEquals ("pixzphipix problem",
+          pix, base1.zphi2pix(base1.pix2zphi(pix)));
+        assertEquals ("pixzphipix problem",
+          pix, base2.zphi2pix(base2.pix2zphi(pix)));
+        }
+      }
+    for (long nside=3; nside<(1L<<omax); nside+=nside/2+1)
+      {
+      HealpixBase base = new HealpixBase (nside,Scheme.RING);
+      for (int m=0; m<nsamples; ++m)
+        {
+        long pix = (long)(rng.nextDouble()*base.getNpix());
+        assertEquals ("pixzphipix problem",
+          pix, base.zphi2pix(base.pix2zphi(pix)));
+        }
+      }
+    }
+
+  public void test_zphipixzphi() throws Exception
+    {
+    System.out.println
+      ("Testing near-identity zphi2pix(pix2zphi(i))approx i");
+    int omax=HealpixBase.order_max;
+    Random rng = new Random(5);
+    for (int order=0; order<=omax; ++order)
+      {
+      HealpixBase base1 = new HealpixBase (1L<<order,Scheme.RING),
+                  base2 = new HealpixBase (1L<<order,Scheme.NESTED);
+      double mincos = Math.min (Math.cos(base1.maxPixrad()),0.999999999999999);
+      for (int m=0; m<nsamples; ++m)
+        {
+        Zphi zp1 = random_zphi(rng);
+        Zphi zp2 = base1.pix2zphi(base1.zphi2pix(zp1));
+        double cd1 = HealpixUtils.cosdist_zphi(zp1.z,zp1.phi,zp2.z,zp2.phi);
+        assertTrue("zphipixzphi problem "+cd1+" "+mincos,cd1>=mincos);
+        zp2 = base2.pix2zphi(base2.zphi2pix(zp1));
+        cd1 = HealpixUtils.cosdist_zphi(zp1.z,zp1.phi,zp2.z,zp2.phi);
+        assertTrue("zphipixzphi problem",cd1>=mincos);
+        }
+      }
+    for (long nside=3; nside<(1L<<omax); nside+=nside/2+1)
+      {
+      HealpixBase base = new HealpixBase (nside,Scheme.RING);
+      double mincos = Math.min (Math.cos(base.maxPixrad()),0.999999999999999);
+      for (int m=0; m<nsamples; ++m)
+        {
+        Zphi zp1 = random_zphi(rng);
+        Zphi zp2 = base.pix2zphi(base.zphi2pix(zp1));
+        double cd1 = HealpixUtils.cosdist_zphi(zp1.z,zp1.phi,zp2.z,zp2.phi);
+        assertTrue("zphipixzphi problem",cd1>=mincos);
+        }
+      }
+    }
+
+  public void test_neighbours() throws Exception
+    {
+    System.out.println("Testing neighbour function");
+    int omax=HealpixBase.order_max;
+    Random rng = new Random(5);
+    for (int order=0; order<=omax; ++order)
+      {
+      HealpixBase base1 = new HealpixBase (1L<<order,Scheme.RING),
+                  base2 = new HealpixBase (1L<<order,Scheme.NESTED);
+      double maxang = 2.01*base1.maxPixrad();
+      for (int m=0; m<nsamples; ++m)
+        {
+        long pix = (long)(rng.nextDouble()*base1.getNpix());
+        Vec3 v = base1.pix2vec(pix);
+        long [] nb = base1.neighbours(pix);
+        long [] nb2 = base2.neighbours(base2.ring2nest(pix));
+        int nnb=0;
+        for (int n=0; n<8; ++n)
+          {
+          if (nb[n]<0)
+            assertTrue("neighbour problem 1",nb2[n]<0);
+          else
+            {
+            ++nnb;
+            assertEquals("neighbour problem 2",base1.ring2nest(nb[n]),nb2[n]);
+            assertTrue("neighbour problem 3",base1.pix2vec(nb[n]).angle(v)<maxang);
+            }
+          }
+        assertTrue("neighbour problem 4 "+order+" "+nnb,(nnb>=7)||((order==0)&&(nnb>=6)));
+        }
+      }
+    for (long nside=3; nside<(1L<<omax); nside+=nside/2+1)
+      {
+      HealpixBase base = new HealpixBase (nside,Scheme.RING);
+      double maxang = 2.01*base.maxPixrad();
+      for (int m=0; m<nsamples; ++m)
+        {
+        long pix = (long)(rng.nextDouble()*base.getNpix());
+        Vec3 v = base.pix2vec(pix);
+        long[] nb = base.neighbours(pix);
+        int nnb=0;
+        for (int n=0; n<8; ++n)
+          if (nb[n]>=0)
+            {
+            ++nnb;
+            assertTrue("neighbour problem 5",base.pix2vec(nb[n]).angle(v)<maxang);
+            }
+        assertTrue("neighbour problem 6",nnb>=7);
+        }
+      }
+    }
+  public void test_query_disc_strict() throws Exception
+    {
+    System.out.println("Testing non-inclusive queryDisc()");
+    Random rng = new Random(5);
+    for (int order=0; order<=5; ++order)
+      {
+      HealpixBase base = new HealpixBase (1L<<order,Scheme.NESTED);
+      boolean[] map = new boolean[(int)base.getNpix()];
+      Vec3[] vmap = new Vec3[(int)base.getNpix()];
+      for (int m=0; m<base.getNpix(); ++m)
+        {
+        map[m]=false;
+        vmap[m]=base.pix2vec(m);
+        }
+      for (int m=0; m<nsamples; ++m)
+        {
+        Pointing ptg = random_dir (rng);
+        double rad = Math.PI * rng.nextDouble();
+        RangeSet rs = base.queryDisc(ptg,rad);
+        Vec3 vptg = new Vec3(ptg);
+        double cosrad=Math.cos(rad);
+        for (int i=0; i<rs.nranges(); ++i)
+          for (long j=rs.ivbegin(i); j<rs.ivend(i); ++j)
+            map[(int)j]=true;
+        for (int i=0; i<base.getNpix(); ++i)
+          {
+          boolean inside = vmap[i].dot(vptg)>cosrad;
+          assertFalse ("query_disc_strict problem",inside^map[i]);
+          }
+        for (int i=0; i<rs.nranges(); ++i)
+          for (long j=rs.ivbegin(i); j<rs.ivend(i); ++j)
+            map[(int)j]=false;
+        }
+      }
+    }
+
+  public void test_query_disc() throws Exception
+    {
+    System.out.println("Testing queryDisc() empirically");
+    int omax=17;
+    Random rng = new Random(5);
+    for (int order=0; order<=omax; ++order)
+      {
+      HealpixBase rbase = new HealpixBase (1L<<order,Scheme.RING),
+                  nbase = new HealpixBase (1L<<order,Scheme.NESTED);
+      int niter=Math.max(1,Math.min(nsamples/1000,100000>>order));
+      for (int m=0; m<niter; ++m)
+        {
+        Pointing ptg = random_dir (rng);
+        double rad = Math.PI * rng.nextDouble();
+        RangeSet rs = rbase.queryDisc(ptg,rad);
+        long nval = rs.nval();
+        rs = nbase.queryDisc(ptg,rad);
+        assertEquals("queryDisc problem 1", nval,rs.nval());
+        rs = rbase.queryDiscInclusive(ptg,rad,4);
+        long nv1 = rs.nval();
+        rs = nbase.queryDiscInclusive(ptg,rad,4);
+        long nv2 = rs.nval();
+        assertTrue("queryDisc problem 2", nv1>=nv2);
+        assertTrue("queryDisc problem 3", nv2>=nval);
+        }
+      }
+    }
+
+  public void testQueryPolygon() throws Exception
+    {
+    System.out.println("Testing queryPolygon()");
+    HealpixBase base = new HealpixBase(1024,Scheme.NESTED);
+    Pointing[] corner = new Pointing[4];
+    corner[0]=new Pointing(new Vec3(1,0.01,0.01));
+    corner[1]=new Pointing(new Vec3(1,1,-0.3));
+    corner[2]=new Pointing(new Vec3(0.01,1,0.01));
+    corner[3]=new Pointing(new Vec3(0.01,0.01,1));
+    RangeSet lrs=base.queryPolygon(corner);
+    assertEquals("QueryPolygon problem",lrs.nval(),1696714);
+    lrs=base.queryPolygonInclusive(corner,4);
+    assertEquals("QueryPolygon problem",lrs.nval(),1700206);
+    base = new HealpixBase(1024,Scheme.RING);
+    lrs=base.queryPolygon(corner);
+    assertEquals("QueryPolygon problem",lrs.nval(),1696714);
+    lrs=base.queryPolygonInclusive(corner,4);
+    assertEquals("QueryPolygon problem",lrs.nval(),1700206);
+    }
+
+  public void testQueryPolygon2() throws Exception
+    {
+    System.out.println("Testing queryPolygon() empirically");
+    int omax=17;
+    Random rng = new Random(5);
+    for (int order=0; order<=omax; ++order)
+      {
+      HealpixBase rbase = new HealpixBase (1L<<order,Scheme.RING),
+                  nbase = new HealpixBase (1L<<order,Scheme.NESTED);
+      int niter=Math.max(1,Math.min(nsamples/1000,100000>>order));
+      for (int m=0; m<niter; ++m)
+        {
+        Pointing[] corner = new Pointing[3];
+        corner[0]=random_dir(rng);
+        corner[1]=random_dir(rng);
+        corner[2]=random_dir(rng);
+        RangeSet rs = rbase.queryPolygon(corner);
+        long nval = rs.nval();
+        rs = nbase.queryPolygon(corner);
+        assertEquals("queryPolygon problem 1", nval,rs.nval());
+        rs = rbase.queryPolygonInclusive(corner,4);
+        long nv1 = rs.nval();
+        rs = nbase.queryPolygonInclusive(corner,4);
+        long nv2 = rs.nval();
+        assertTrue("queryPolygon problem 2", nv1>=nv2);
+        assertTrue("queryPolygon problem 3", nv2>=nval);
+        }
+      }
+    }
+
+  public void testSmallPoly()  throws Exception
+    {
+    System.out.println("Testing small polygon");
+    HealpixBase base = new HealpixBase(1024,Scheme.NESTED);
+    Pointing[] corner = new Pointing[4];
+    corner[0]=new Pointing(2.7190983373838,1.50840508184223);
+    corner[1]=new Pointing(2.7190980835706067,1.5084057923700163);
+    corner[2]=new Pointing(2.719101654815075,1.5084144044115078);
+    corner[3]=new Pointing(2.719101908630556,1.5084136938829422);
+    RangeSet lrs=base.queryPolygon(corner);
+    }
+
+  public void test() throws Exception
+    {
+    int nside=256;
+    HealpixBase base  = new HealpixBase(nside,Scheme.NESTED);
+    HealpixBase base2 = new HealpixBase(nside,Scheme.RING);
+    for (int i=0; i<12*nside*nside; ++i)
+      {
+      assertEquals ("pixel mismatch_nest",i,base.ang2pix(base.pix2ang(i)));
+      assertEquals ("pixel mismatch_nest",i,base.vec2pix(base.pix2vec(i)));
+      assertEquals ("pixel mismatch_ring",i,base2.ang2pix(base2.pix2ang(i)));
+      assertEquals ("pixel mismatch_ring",i,base2.vec2pix(base2.pix2vec(i)));
+      assertEquals ("pixel mismatch",i,base.ring2nest(base2.ang2pix(base.pix2ang(i))));
+      assertEquals ("pixel mismatch_ringnestring",i,base.ring2nest(base.nest2ring(i)));
+      }
+    }
+
+  }
diff -Nru healpix-java-3.40/src/java/src/healpix/essentials/test/HealpixMapTest.java healpix-java-3.50/src/java/src/healpix/essentials/test/HealpixMapTest.java
--- healpix-java-3.40/src/java/src/healpix/essentials/test/HealpixMapTest.java	1969-12-31 19:00:00.000000000 -0500
+++ healpix-java-3.50/src/java/src/healpix/essentials/test/HealpixMapTest.java	2015-07-05 02:10:50.000000000 -0400
@@ -0,0 +1,51 @@
+/*
+ *  This file is part of Healpix Java.
+ *
+ *  This code 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 code 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 code; 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.sourceforge.net
+ */
+package healpix.essentials.test;
+
+import junit.framework.TestCase;
+import java.util.Random;
+import java.text.DecimalFormat;
+
+import healpix.essentials.*;
+
+/** Tests for the HealpixMap class
+
+    @copyright 2014 Max-Planck-Society
+    @author Martin Reinecke */
+public class HealpixMapTest extends TestCase {
+
+  public void test_swapScheme()throws Exception
+    {
+    System.out.println("Testing swapScheme()");
+
+    for (int order=0; order<=8; ++order)
+      {
+      HealpixMapFloat map = new HealpixMapFloat (1L<<order,Scheme.RING);
+      for (int i=0; i<map.getNpix(); ++i)
+        map.setPixel(i,i);
+      map.swapScheme();
+      for (int i=0; i<map.getNpix(); ++i)
+        assertEquals("inconsistency",map.nest2ring(i),(int)map.getPixel(i));
+      map.swapScheme();
+      for (int i=0; i<map.getNpix(); ++i)
+        assertEquals("inconsistency",i,(int)map.getPixel(i));
+      }
+    }
+  }
diff -Nru healpix-java-3.40/src/java/src/healpix/essentials/test/HealpixProcTest.java healpix-java-3.50/src/java/src/healpix/essentials/test/HealpixProcTest.java
--- healpix-java-3.40/src/java/src/healpix/essentials/test/HealpixProcTest.java	1969-12-31 19:00:00.000000000 -0500
+++ healpix-java-3.50/src/java/src/healpix/essentials/test/HealpixProcTest.java	2015-07-05 02:10:50.000000000 -0400
@@ -0,0 +1,238 @@
+/*
+ *  This file is part of Healpix Java.
+ *
+ *  This code 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 code 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 code; 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.sourceforge.net
+ */
+package healpix.essentials.test;
+
+import junit.framework.TestCase;
+import java.util.Random;
+import java.text.DecimalFormat;
+
+import healpix.essentials.*;
+
+/** Tests for the HealpixProc class
+
+    @copyright 2014 Max-Planck-Society
+    @author Martin Reinecke */
+public class HealpixProcTest extends TestCase {
+
+  static private final int nsamples=10000; // influences number of correctness tests
+  static private final DecimalFormat form = new DecimalFormat("##0.00");
+
+  private Zphi random_zphi(Random rng)
+    { return new Zphi(2*rng.nextDouble()-1,2*Math.PI*rng.nextDouble()); }
+
+  private Pointing random_dir(Random rng)
+    { return new Pointing(Math.acos(2*rng.nextDouble()-1),2*Math.PI*rng.nextDouble()); }
+
+  public void test_accuracy()throws Exception
+    {
+    System.out.println("Testing accuracy near the poles");
+
+    for (int order=0; order<=HealpixBase.order_max; ++order)
+      assertTrue("incorrect pix2ang",
+        HealpixProc.pix2angRing(order,1).theta>0.0);
+    }
+
+  public void test_ringnestring()throws Exception
+    {
+    System.out.println("Testing identity ring2nest(nest2ring(i))==i");
+    Random rng = new Random(5);
+
+    for (int o=0; o<=HealpixBase.order_max; ++o)
+      {
+      for (int m=0; m<nsamples; ++m)
+        {
+        long pix = (long)(rng.nextDouble()*HealpixProc.order2Npix(o));
+        assertEquals ("ringnestring problem",
+          HealpixProc.ring2nest(o,HealpixProc.nest2ring(o,pix)),pix);
+        }
+      }
+    }
+
+  public void test_pixangpix()throws Exception
+    {
+    System.out.println("Testing identity pix2ang(ang2pix(i))==i");
+    int omax=HealpixBase.order_max;
+    Random rng = new Random(5);
+    for (int o=0; o<=omax; ++o)
+      {
+      for (int m=0; m<nsamples; ++m)
+        {
+        long pix = (long)(rng.nextDouble()*HealpixProc.order2Npix(o));
+        assertEquals ("pixangpix problem",
+          pix, HealpixProc.ang2pixNest(o,HealpixProc.pix2angNest(o,pix)));
+        assertEquals ("pixangpix problem",
+          pix, HealpixProc.ang2pixRing(o,HealpixProc.pix2angRing(o,pix)));
+        }
+      }
+    }
+
+  public void test_neighbours() throws Exception
+    {
+    System.out.println("Testing neighbour function");
+    int omax=HealpixBase.order_max;
+    Random rng = new Random(5);
+    for (int o=0; o<=omax; ++o)
+      {
+      double maxang = 2.01*HealpixProc.maxPixrad(o);
+      for (int m=0; m<nsamples; ++m)
+        {
+        long pix = (long)(rng.nextDouble()*HealpixProc.order2Npix(o));
+        Vec3 v = HealpixProc.pix2vecRing(o,pix);
+        long [] nb = HealpixProc.neighboursRing(o,pix);
+        long [] nb2 = HealpixProc.neighboursNest(o,HealpixProc.ring2nest(o,pix));
+        int nnb=0;
+        for (int n=0; n<8; ++n)
+          {
+          if (nb[n]<0)
+            assertTrue("neighbour problem 1",nb2[n]<0);
+          else
+            {
+            ++nnb;
+            assertEquals("neighbour problem 2",HealpixProc.ring2nest(o,nb[n]),nb2[n]);
+            assertTrue("neighbour problem 3",HealpixProc.pix2vecRing(o,nb[n]).angle(v)<maxang);
+            }
+          }
+        assertTrue("neighbour problem 4 "+o+" "+nnb,(nnb>=7)||((o==0)&&(nnb>=6)));
+        }
+      }
+    }
+
+  public void test_query_disc_strict() throws Exception
+    {
+    System.out.println("Testing non-inclusive queryDisc()");
+    Random rng = new Random(5);
+    for (int o=0; o<=5; ++o)
+      {
+      int npix=(int)HealpixProc.order2Npix(o);
+      boolean[] map = new boolean[npix];
+      Vec3[] vmap = new Vec3[npix];
+      for (int m=0; m<npix; ++m)
+        {
+        map[m]=false;
+        vmap[m]=HealpixProc.pix2vecRing(o,m);
+        }
+      for (int m=0; m<nsamples; ++m)
+        {
+        Pointing ptg = random_dir (rng);
+        double rad = Math.PI * rng.nextDouble();
+        RangeSet rs = HealpixProc.queryDiscRing(o,ptg,rad);
+        Vec3 vptg = new Vec3(ptg);
+        double cosrad=Math.cos(rad);
+        for (int i=0; i<rs.nranges(); ++i)
+          for (long j=rs.ivbegin(i); j<rs.ivend(i); ++j)
+            map[(int)j]=true;
+        for (int i=0; i<npix; ++i)
+          {
+          boolean inside = vmap[i].dot(vptg)>cosrad;
+          assertFalse ("query_disc_strict problem",inside^map[i]);
+          }
+        for (int i=0; i<rs.nranges(); ++i)
+          for (long j=rs.ivbegin(i); j<rs.ivend(i); ++j)
+            map[(int)j]=false;
+        }
+      }
+    }
+
+  public void test_query_disc() throws Exception
+    {
+    System.out.println("Testing queryDisc() empirically");
+    int omax=17;
+    Random rng = new Random(5);
+    for (int o=0; o<=omax; ++o)
+      {
+      int niter=Math.max(1,Math.min(nsamples/1000,100000>>o));
+      for (int m=0; m<niter; ++m)
+        {
+        Pointing ptg = random_dir (rng);
+        double rad = Math.PI * rng.nextDouble();
+        RangeSet rs = HealpixProc.queryDiscRing(o,ptg,rad);
+        long nval = rs.nval();
+        rs = HealpixProc.queryDiscNest(o,ptg,rad);
+        assertEquals("queryDisc problem 1", nval,rs.nval());
+        rs = HealpixProc.queryDiscInclusiveRing(o,ptg,rad,4);
+        long nv1 = rs.nval();
+        rs = HealpixProc.queryDiscInclusiveNest(o,ptg,rad,4);
+        long nv2 = rs.nval();
+        assertTrue("queryDisc problem 2", nv1>=nv2);
+        assertTrue("queryDisc problem 3", nv2>=nval);
+        }
+      }
+    }
+
+  public void testQueryPolygon() throws Exception
+    {
+    System.out.println("Testing queryPolygon()");
+    Pointing[] corner = new Pointing[4];
+    corner[0]=new Pointing(new Vec3(1,0.01,0.01));
+    corner[1]=new Pointing(new Vec3(1,1,-0.3));
+    corner[2]=new Pointing(new Vec3(0.01,1,0.01));
+    corner[3]=new Pointing(new Vec3(0.01,0.01,1));
+    RangeSet lrs=HealpixProc.queryPolygonNest(10,corner);
+    assertEquals("QueryPolygon problem",lrs.nval(),1696714);
+    lrs=HealpixProc.queryPolygonInclusiveNest(10,corner,4);
+    assertEquals("QueryPolygon problem",lrs.nval(),1700206);
+    lrs=HealpixProc.queryPolygonRing(10,corner);
+    assertEquals("QueryPolygon problem",lrs.nval(),1696714);
+    lrs=HealpixProc.queryPolygonInclusiveRing(10,corner,4);
+    assertEquals("QueryPolygon problem",lrs.nval(),1700206);
+    }
+
+  public void testQueryPolygon2() throws Exception
+    {
+    System.out.println("Testing queryPolygon() empirically");
+    int omax=17;
+    Random rng = new Random(5);
+    for (int o=0; o<=omax; ++o)
+      {
+      int niter=Math.max(1,Math.min(nsamples/1000,100000>>o));
+      for (int m=0; m<niter; ++m)
+        {
+        Pointing[] corner = new Pointing[3];
+        corner[0]=random_dir(rng);
+        corner[1]=random_dir(rng);
+        corner[2]=random_dir(rng);
+        RangeSet rs = HealpixProc.queryPolygonRing(o,corner);
+        long nval = rs.nval();
+        rs = HealpixProc.queryPolygonNest(o,corner);
+        assertEquals("queryPolygon problem 1", nval,rs.nval());
+        rs = HealpixProc.queryPolygonInclusiveRing(o,corner,4);
+        long nv1 = rs.nval();
+        rs = HealpixProc.queryPolygonInclusiveNest(o,corner,4);
+        long nv2 = rs.nval();
+        assertTrue("queryPolygon problem 2", nv1>=nv2);
+        assertTrue("queryPolygon problem 3", nv2>=nval);
+        }
+      }
+    }
+
+  public void test() throws Exception
+    {
+    int o=8;
+    for (int i=0; i<HealpixProc.order2Npix(o); ++i)
+      {
+      assertEquals ("pixel mismatch_nest",i,HealpixProc.ang2pixNest(o,HealpixProc.pix2angNest(o,i)));
+      assertEquals ("pixel mismatch_nest",i,HealpixProc.vec2pixNest(o,HealpixProc.pix2vecNest(o,i)));
+      assertEquals ("pixel mismatch_ring",i,HealpixProc.ang2pixRing(o,HealpixProc.pix2angRing(o,i)));
+      assertEquals ("pixel mismatch_ring",i,HealpixProc.vec2pixRing(o,HealpixProc.pix2vecRing(o,i)));
+      assertEquals ("pixel mismatch",i,HealpixProc.ring2nest(o,HealpixProc.ang2pixRing(o,HealpixProc.pix2angNest(o,i))));
+      assertEquals ("pixel mismatch_ringnestring",i,HealpixProc.ring2nest(o,HealpixProc.nest2ring(o,i)));
+      }
+    }
+  }
diff -Nru healpix-java-3.40/src/java/src/healpix/essentials/test/MocQueryTest.java healpix-java-3.50/src/java/src/healpix/essentials/test/MocQueryTest.java
--- healpix-java-3.40/src/java/src/healpix/essentials/test/MocQueryTest.java	1969-12-31 19:00:00.000000000 -0500
+++ healpix-java-3.50/src/java/src/healpix/essentials/test/MocQueryTest.java	2015-07-14 05:06:15.000000000 -0400
@@ -0,0 +1,369 @@
+/*
+ *  This file is part of Healpix Java.
+ *
+ *  This code 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 code 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 code; 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.sourceforge.net
+ */
+package healpix.essentials.test;
+
+import healpix.essentials.*;
+import junit.framework.TestCase;
+import java.io.*;
+import java.util.Arrays;
+import java.util.ArrayList;
+
+/** Tests for the MocQuery class
+
+    @copyright 2015 Max-Planck-Society
+    @author Martin Reinecke */
+public class MocQueryTest extends TestCase
+  {
+  private ArrayList<Vec3> rawToPoly(double[] inp) throws Exception
+    {
+    HealpixUtils.check((inp.length>=6)&&((inp.length&1)==0),
+      "bad input array");
+    ArrayList<Vec3> res = new ArrayList<Vec3>();
+    for (int i=0; i<inp.length; i+=2)
+      res.add(new Vec3(new Pointing(Math.PI/2 - Math.toRadians(inp[i+1]),
+        Math.toRadians(inp[i]))));
+    return res;
+    }
+  private void checkPoly(ArrayList<Vec3> poly, int o1, int o2, String out)
+    throws Exception
+    {
+    Moc moc = MocQuery.queryGeneralPolygonInclusive (poly,o1,o1);
+    if (out!="")
+      MocFitsIO.mocToFits(moc,out+"_inc_"+o1+".fits");
+    for (int o=o1+1; o<=o2; ++o)
+      {
+      Moc moc2 = MocQuery.queryGeneralPolygonInclusive (poly,o1,o2);
+      assertTrue("inconsistency",moc.contains(moc2));
+      if (out!="")
+        MocFitsIO.mocToFits(moc2,out+"_inc_"+o+".fits");
+      moc=moc2;
+      }
+    Moc moc2 = MocQuery.queryGeneralPolygon(poly,o1);
+    if (out!="")
+      MocFitsIO.mocToFits(moc2,out+".fits");
+    assertTrue("inconsistency",moc.contains(moc2));
+    }
+  public void test1() throws Exception
+    {
+    double[] polyraw=new double[]{
+      83.6479647404001,  22.06796566083695,
+      83.57919759304697, 22.014902754311912,
+      83.54565527259793, 22.05666932013043,
+      83.54535325267885, 22.05666728060237,
+      83.54535545323692, 22.056387364445676,
+      83.54535985432697, 22.05582753212609,
+      83.54536865640274, 22.05470786746255,
+      83.54537525786826, 22.05386811894398,
+      83.53952949498002, 21.952773396955234,
+      83.63157603991105, 21.995362438376056,
+      83.64144959973622, 21.965751089665403,
+      83.69912966373616, 22.00612703969729 };
+
+    checkPoly(rawToPoly(polyraw),13,15,"");
+    }
+  public void test2() throws Exception
+    {
+    double[] polyraw=new double[]{
+      83.69572488226052, 22.01842407483951,
+      83.66469321144844, 22.05155150183524,
+      83.66439120028902, 22.051549680680765,
+      83.62952475535761, 22.02838142338798,
+      83.58771024980035, 22.04715033027345,
+      83.5874082491367,  22.04714836793211,
+      83.58741036646086, 22.0468684509572,
+      83.58741671838312, 22.046028700022926,
+      83.57147626994606, 21.99805614401068,
+      83.59369254263831, 21.934377044862455,
+      83.59369043939574, 21.93465696148893,
+      83.59368833614487, 21.934936878119167,
+      83.59338236664615, 21.935494760357145,
+      83.59338026277467, 21.93577467699384,
+      83.64687451268995, 21.966904215256918,
+      83.60550939897153, 22.00919444338953,
+      83.66653272555045, 22.004534367269507,
+      83.69542484507058, 22.018142392123163 };
+
+    checkPoly(rawToPoly(polyraw),13,15,"");
+    }
+
+  public void test3() throws Exception
+    {
+    ArrayList<Vec3> vert=new ArrayList<Vec3>();
+    vert.add(new Vec3(new Pointing(1.1523428941043317,1.000795791041251)));
+    vert.add(new Vec3(new Pointing(1.1523106929911657,1.0008281306683644)));
+    vert.add(new Vec3(new Pointing(1.1521818924889993,1.0009574985526972)));
+    vert.add(new Vec3(new Pointing(1.1519887035905163,1.001151578519077)));
+    vert.add(new Vec3(new Pointing(1.151859918897493,1.0012809839336458)));
+    vert.add(new Vec3(new Pointing(1.1514894198468866,1.001263637028638)));
+    vert.add(new Vec3(new Pointing(1.1513659202048774,1.0012578536443903)));
+    vert.add(new Vec3(new Pointing(1.1511859573237597,1.0011139425394953)));
+    vert.add(new Vec3(new Pointing(1.1510060020113047,1.0009700085527964)));
+    vert.add(new Vec3(new Pointing(1.1508556031353578,1.0008613172356937)));
+    vert.add(new Vec3(new Pointing(1.150673007120061,1.0007849744501682)));
+    vert.add(new Vec3(new Pointing(1.1503938085112773,1.0008057187152946)));
+    vert.add(new Vec3(new Pointing(1.150205908484378,1.0008646491036832)));
+    vert.add(new Vec3(new Pointing(1.149953611594119,1.000988341677547)));
+    vert.add(new Vec3(new Pointing(1.1497335179693469,1.0010796806589697)));
+    vert.add(new Vec3(new Pointing(1.1494247698862567,1.0010651879076278)));
+    vert.add(new Vec3(new Pointing(1.1492448165599576,1.0009211385295873)));
+    vert.add(new Vec3(new Pointing(1.149000469199188,1.0008418420185987)));
+    vert.add(new Vec3(new Pointing(1.1485894925444542,1.000279935669881)));
+    vert.add(new Vec3(new Pointing(1.1486539077047668,1.0002151640462313)));
+    vert.add(new Vec3(new Pointing(1.1490324086471566,1.0000296562389843)));
+    vert.add(new Vec3(new Pointing(1.1492203271505665,0.9999707639528252)));
+    vert.add(new Vec3(new Pointing(1.1495639559481354,0.9998853760122856)));
+    vert.add(new Vec3(new Pointing(1.149848517849616,0.9997294255486839)));
+    vert.add(new Vec3(new Pointing(1.1499773768285775,0.9995999921162992)));
+    vert.add(new Vec3(new Pointing(1.1501062421175312,0.9994705737522844)));
+    vert.add(new Vec3(new Pointing(1.1501733657022064,0.9993382245815566)));
+    vert.add(new Vec3(new Pointing(1.150157309455921,0.9989646985587307)));
+    vert.add(new Vec3(new Pointing(1.1502783613271745,0.9982588937208289)));
+    vert.add(new Vec3(new Pointing(1.150367358658019,0.9975854875791592)));
+    vert.add(new Vec3(new Pointing(1.1503145561122339,0.9966002329829549)));
+    vert.add(new Vec3(new Pointing(1.1501837017642849,0.9960177261452899)));
+    vert.add(new Vec3(new Pointing(1.1500880289072624,0.9953352142578803)));
+    vert.add(new Vec3(new Pointing(1.1498339618638964,0.9947464292684306)));
+    vert.add(new Vec3(new Pointing(1.1496599663238942,0.9944665891792631)));
+    vert.add(new Vec3(new Pointing(1.1495211017074738,0.9940867625529576)));
+    vert.add(new Vec3(new Pointing(1.1494032633666398,0.993945254823653)));
+    vert.add(new Vec3(new Pointing(1.1492854324600088,0.9938037321908275)));
+    vert.add(new Vec3(new Pointing(1.1491647775622915,0.9937298631728655)));
+    vert.add(new Vec3(new Pointing(1.1489093237140704,0.9939204821489465)));
+    vert.add(new Vec3(new Pointing(1.1487240963858985,0.9939111896936369)));
+    vert.add(new Vec3(new Pointing(1.148418211419246,0.9938280074878991)));
+    vert.add(new Vec3(new Pointing(1.148203527561705,0.9937833060402974)));
+    vert.add(new Vec3(new Pointing(1.1480562505373242,0.9936062948138628)));
+    vert.add(new Vec3(new Pointing(1.1479678899060295,0.9935000768652547)));
+    vert.add(new Vec3(new Pointing(1.1479089851456499,0.9934292602260698)));
+    vert.add(new Vec3(new Pointing(1.1478263164713338,0.9931876107503619)));
+    vert.add(new Vec3(new Pointing(1.147658188833066,0.9927719711268423)));
+    vert.add(new Vec3(new Pointing(1.147605019627341,0.9925656960713723)));
+    vert.add(new Vec3(new Pointing(1.147513838399067,0.9925271325090353)));
+    vert.add(new Vec3(new Pointing(1.1469790356795493,0.9927375232998785)));
+    vert.add(new Vec3(new Pointing(1.1467586597155184,0.9928281691313717)));
+    vert.add(new Vec3(new Pointing(1.1466646212864107,0.9928573452285496)));
+    vert.add(new Vec3(new Pointing(1.146570583168876,0.9928865238140747)));
+    vert.add(new Vec3(new Pointing(1.1464822508174166,0.9927802065018877)));
+    vert.add(new Vec3(new Pointing(1.1464233649158908,0.9927093236024059)));
+    vert.add(new Vec3(new Pointing(1.1463350395636842,0.9926029922143758)));
+    vert.add(new Vec3(new Pointing(1.1464082297063476,0.9923351250888106)));
+    vert.add(new Vec3(new Pointing(1.1465403155639036,0.9921381737414078)));
+    vert.add(new Vec3(new Pointing(1.146801650920068,0.9918120793817878)));
+    vert.add(new Vec3(new Pointing(1.146992632145478,0.9916860897831967)));
+    vert.add(new Vec3(new Pointing(1.147336526500701,0.9916018945040467)));
+    vert.add(new Vec3(new Pointing(1.1475540582351127,0.991579108720834)));
+    vert.add(new Vec3(new Pointing(1.148297344412475,0.9908370227283142)));
+    vert.add(new Vec3(new Pointing(1.14831771135701,0.9903631889078771)));
+    vert.add(new Vec3(new Pointing(1.1483410904887272,0.9898216751345671)));
+    vert.add(new Vec3(new Pointing(1.14817642568152,0.9893381849506938)));
+    vert.add(new Vec3(new Pointing(1.1478619397258643,0.9887449725688633)));
+    vert.add(new Vec3(new Pointing(1.1476621504872502,0.9883612311158905)));
+    vert.add(new Vec3(new Pointing(1.1473389454791498,0.987970892009681)));
+    vert.add(new Vec3(new Pointing(1.1470745474697959,0.9876514390156884)));
+    vert.add(new Vec3(new Pointing(1.1467220762850698,0.9872253830842613)));
+    vert.add(new Vec3(new Pointing(1.1465134990729606,0.9870445283107344)));
+    vert.add(new Vec3(new Pointing(1.1463576636239432,0.9870701715700294)));
+    vert.add(new Vec3(new Pointing(1.1461311065061512,0.987295784658764)));
+    vert.add(new Vec3(new Pointing(1.145969291549504,0.9874569649988388)));
+    vert.add(new Vec3(new Pointing(1.1456780489082319,0.9877471487418389)));
+    vert.add(new Vec3(new Pointing(1.1453544826095992,0.9880696643744283)));
+    vert.add(new Vec3(new Pointing(1.1451309779989192,0.9882276968098427)));
+    vert.add(new Vec3(new Pointing(1.1449223325837785,0.9880468062013319)));
+    vert.add(new Vec3(new Pointing(1.144684321314146,0.9878303468533963)));
+    vert.add(new Vec3(new Pointing(1.1444786880119573,0.9875815784705101)));
+    vert.add(new Vec3(new Pointing(1.1444055321874065,0.9871359210384268)));
+    vert.add(new Vec3(new Pointing(1.1443527978610553,0.9869292081606309)));
+    vert.add(new Vec3(new Pointing(1.1443588066568586,0.9867935954286845)));
+    vert.add(new Vec3(new Pointing(1.1443294428641322,0.9867580408743656)));
+    vert.add(new Vec3(new Pointing(1.1441178863108807,0.9866447588708069)));
+    vert.add(new Vec3(new Pointing(1.143627025593574,0.9865504721602422)));
+    vert.add(new Vec3(new Pointing(1.1430714198687517,0.9865206748900628)));
+    vert.add(new Vec3(new Pointing(1.142486453971728,0.9864552736851653)));
+    vert.add(new Vec3(new Pointing(1.1421130353865951,0.9865032583536448)));
+    vert.add(new Vec3(new Pointing(1.1418013514800418,0.9865545719393494)));
+    vert.add(new Vec3(new Pointing(1.1415280685012117,0.9864378231638371)));
+    vert.add(new Vec3(new Pointing(1.1413195436592867,0.9862564662025781)));
+    vert.add(new Vec3(new Pointing(1.1411140566169835,0.9860071695710151)));
+    vert.add(new Vec3(new Pointing(1.1410583793726072,0.9858680266790968)));
+    vert.add(new Vec3(new Pointing(1.1411585594318707,0.9857032675075046)));
+    vert.add(new Vec3(new Pointing(1.1415471911174158,0.9853159421723982)));
+    vert.add(new Vec3(new Pointing(1.1417091373202277,0.9851545968685336)));
+    vert.add(new Vec3(new Pointing(1.141935878135893,0.9849287531836823)));
+    vert.add(new Vec3(new Pointing(1.1421919741278386,0.9847385729150904)));
+    vert.add(new Vec3(new Pointing(1.1427212823451636,0.9846653708690231)));
+    vert.add(new Vec3(new Pointing(1.1429388730086534,0.9846432208437782)));
+    vert.add(new Vec3(new Pointing(1.1431888603402285,0.9845888377168718)));
+    vert.add(new Vec3(new Pointing(1.143221257341095,0.9845566013231962)));
+    vert.add(new Vec3(new Pointing(1.1431393920272823,0.9843141087835374)));
+    vert.add(new Vec3(new Pointing(1.142940242012983,0.9839291446460309)));
+    vert.add(new Vec3(new Pointing(1.1427704685698539,0.9835797337470248)));
+    vert.add(new Vec3(new Pointing(1.1426917873195213,0.9832693018292363)));
+    vert.add(new Vec3(new Pointing(1.142613142293535,0.9829588475331977)));
+    vert.add(new Vec3(new Pointing(1.1426935245487904,0.9825551447276581)));
+    vert.add(new Vec3(new Pointing(1.1428587549013667,0.9823262384230973)));
+    vert.add(new Vec3(new Pointing(1.1432802997807938,0.9819076068355195)));
+    vert.add(new Vec3(new Pointing(1.1435428818201463,0.981582241584326)));
+    vert.add(new Vec3(new Pointing(1.1438023569877103,0.9813247693528765)));
+    vert.add(new Vec3(new Pointing(1.1440879942426359,0.981170799141964)));
+    vert.add(new Vec3(new Pointing(1.1443087617014966,0.9810812052364875)));
+    vert.add(new Vec3(new Pointing(1.1444939405572025,0.9810915890969772)));
+    vert.add(new Vec3(new Pointing(1.1446435321631656,0.9812019262076423)));
+    vert.add(new Vec3(new Pointing(1.1449657419610033,0.9815937325674373)));
+    vert.add(new Vec3(new Pointing(1.145170814762998,0.9818430040096161)));
+    vert.add(new Vec3(new Pointing(1.145405212420505,0.9821278286770655)));
+    vert.add(new Vec3(new Pointing(1.1455810307686392,0.982341407316913)));
+    vert.add(new Vec3(new Pointing(1.1456396407122253,0.9824125926080799)));
+    vert.add(new Vec3(new Pointing(1.1457568663384885,0.9825549518114552)));
+    vert.add(new Vec3(new Pointing(1.1458447905784235,0.982661711260155)));
+    vert.add(new Vec3(new Pointing(1.146056176224855,0.9827752848212115)));
+    vert.add(new Vec3(new Pointing(1.1464203363305736,0.982931223860804)));
+    vert.add(new Vec3(new Pointing(1.1465700046565381,0.983041338988599)));
+    vert.add(new Vec3(new Pointing(1.146931084242241,0.9832649203344934)));
+    vert.add(new Vec3(new Pointing(1.147304554977569,0.983217580321881)));
+    vert.add(new Vec3(new Pointing(1.14755456833011,0.983163460791517)));
+    vert.add(new Vec3(new Pointing(1.1476518102952684,0.9830670054161794)));
+    vert.add(new Vec3(new Pointing(1.147911138996274,0.9828098319777566)));
+    vert.add(new Vec3(new Pointing(1.1480146153175843,0.9825780284118409)));
+    vert.add(new Vec3(new Pointing(1.1478512630860116,0.982093928824457)));
+    vert.add(new Vec3(new Pointing(1.1477465895705665,0.981680894029768)));
+    vert.add(new Vec3(new Pointing(1.1477037064890643,0.9812712698299393)));
+    vert.add(new Vec3(new Pointing(1.1476901713851657,0.980897208503522)));
+    vert.add(new Vec3(new Pointing(1.147738413955949,0.9805266127850084)));
+    vert.add(new Vec3(new Pointing(1.1479718818582025,0.9801664735990022)));
+    vert.add(new Vec3(new Pointing(1.148205397839398,0.9798064091969002)));
+    vert.add(new Vec3(new Pointing(1.1483708576902831,0.9795782695316553)));
+    vert.add(new Vec3(new Pointing(1.1487928200059858,0.9791611823574279)));
+    vert.add(new Vec3(new Pointing(1.1493382912635042,0.9787512843635041)));
+    vert.add(new Vec3(new Pointing(1.1502609222180684,0.9788716216588957)));
+    vert.add(new Vec3(new Pointing(1.1504396821178993,0.9790173766494347)));
+    vert.add(new Vec3(new Pointing(1.1507908399518807,0.9794440181022032)));
+    vert.add(new Vec3(new Pointing(1.1509893471305994,0.9798280210118206)));
+    vert.add(new Vec3(new Pointing(1.1511815695494167,0.9803471360053592)));
+    vert.add(new Vec3(new Pointing(1.1513477656945341,0.9807630544316528)));
+    vert.add(new Vec3(new Pointing(1.1516604798024512,0.98135646536512)));
+    vert.add(new Vec3(new Pointing(1.1517033801181038,0.981765361770002)));
+    vert.add(new Vec3(new Pointing(1.1517170406506425,0.9821387451013951)));
+    vert.add(new Vec3(new Pointing(1.1515842233393097,0.9823346503008543)));
+    vert.add(new Vec3(new Pointing(1.1513896921866162,0.9825271705205277)));
+    vert.add(new Vec3(new Pointing(1.1511627565046656,0.9827518193104232)));
+    vert.add(new Vec3(new Pointing(1.1508710094941494,0.9830407197788995)));
+    vert.add(new Vec3(new Pointing(1.1506441165054242,0.9832654717657893)));
+    vert.add(new Vec3(new Pointing(1.150482061529942,0.9834260365777083)));
+    vert.add(new Vec3(new Pointing(1.1503524244193444,0.9835545050450514)));
+    vert.add(new Vec3(new Pointing(1.1502258785647448,0.983615364692989)));
+    vert.add(new Vec3(new Pointing(1.150040689827067,0.9836052230787131)));
+    vert.add(new Vec3(new Pointing(1.1497289561324662,0.9836559547866632)));
+    vert.add(new Vec3(new Pointing(1.1496348192975478,0.9836847052609023)));
+    vert.add(new Vec3(new Pointing(1.1494727890458836,0.9838453720714817)));
+    vert.add(new Vec3(new Pointing(1.1494049018076335,0.9839772939956009)));
+    vert.add(new Vec3(new Pointing(1.149324740233309,0.9843798294222985)));
+    vert.add(new Vec3(new Pointing(1.1492739766976383,0.9848178951560865)));
+    vert.add(new Vec3(new Pointing(1.1492880620951265,0.9851916630592842)));
+    vert.add(new Vec3(new Pointing(1.1494023951081926,0.9854012904878543)));
+    vert.add(new Vec3(new Pointing(1.149519781095103,0.9855432489469033)));
+    vert.add(new Vec3(new Pointing(1.1497839272856774,0.9858626006164312)));
+    vert.add(new Vec3(new Pointing(1.1501482692615095,0.986017767907073)));
+    vert.add(new Vec3(new Pointing(1.1506158045877952,0.9859411952965156)));
+    vert.add(new Vec3(new Pointing(1.1510863719564317,0.9857970535978254)));
+    vert.add(new Vec3(new Pointing(1.1514010989298469,0.9856784621213586)));
+    vert.add(new Vec3(new Pointing(1.1517158310959092,0.9855599035665571)));
+    vert.add(new Vec3(new Pointing(1.1520923005998371,0.9854447044733927)));
+    vert.add(new Vec3(new Pointing(1.152556811551436,0.9854358697505938)));
+    vert.add(new Vec3(new Pointing(1.152936329868326,0.9852531893604244)));
+    vert.add(new Vec3(new Pointing(1.1534980080389958,0.9851480997557343)));
+    vert.add(new Vec3(new Pointing(1.1542448858126413,0.9850530625072047)));
+    vert.add(new Vec3(new Pointing(1.1548713566503563,0.9848839302619462)));
+    vert.add(new Vec3(new Pointing(1.155238694559804,0.9849714230186063)));
+    vert.add(new Vec3(new Pointing(1.155511913488695,0.9850876232716619)));
+    vert.add(new Vec3(new Pointing(1.1556879733525678,0.9852999969140172)));
+    vert.add(new Vec3(new Pointing(1.1559784112498703,0.9857213321874994)));
+    vert.add(new Vec3(new Pointing(1.1559865844022958,0.9862288863472906)));
+    vert.add(new Vec3(new Pointing(1.1560385791492556,0.9871444375227638)));
+    vert.add(new Vec3(new Pointing(1.1560116805212006,0.9877515244318255)));
+    vert.add(new Vec3(new Pointing(1.1558379990039347,0.9881818725706057)));
+    vert.add(new Vec3(new Pointing(1.155543873841697,0.9885383490226638)));
+    vert.add(new Vec3(new Pointing(1.1552557042400238,0.9887599602232404)));
+    vert.add(new Vec3(new Pointing(1.1549352096290768,0.9890137597369755)));
+    vert.add(new Vec3(new Pointing(1.1546147391191914,0.9892676311236104)));
+    vert.add(new Vec3(new Pointing(1.1542354927708685,0.9894508532485825)));
+    vert.add(new Vec3(new Pointing(1.1538621301597058,0.9894990936671686)));
+    vert.add(new Vec3(new Pointing(1.1536181187451178,0.9894187147674598)));
+    vert.add(new Vec3(new Pointing(1.1533447121031735,0.9893029412643478)));
+    vert.add(new Vec3(new Pointing(1.1529537305101472,0.9890455986187472)));
+    vert.add(new Vec3(new Pointing(1.1524980830083356,0.9888524937214215)));
+    vert.add(new Vec3(new Pointing(1.1523481741773312,0.9887430639190622)));
+    vert.add(new Vec3(new Pointing(1.1520629738824093,0.988897439436812)));
+    vert.add(new Vec3(new Pointing(1.1518395192779805,0.9890550816485132)));
+    vert.add(new Vec3(new Pointing(1.1515513932259047,0.9892771221299574)));
+    vert.add(new Vec3(new Pointing(1.1513250228779512,0.9895024356245301)));
+    vert.add(new Vec3(new Pointing(1.1510957407699558,0.9897953995250245)));
+    vert.add(new Vec3(new Pointing(1.1508988210950766,0.9900562178915127)));
+    vert.add(new Vec3(new Pointing(1.150763665085474,0.9903202764372446)));
+    vert.add(new Vec3(new Pointing(1.1507843367123325,0.990558526439852)));
+    vert.add(new Vec3(new Pointing(1.1507992237525468,0.9909320025905168)));
+    vert.add(new Vec3(new Pointing(1.1508522671724446,0.9911380213792874)));
+    vert.add(new Vec3(new Pointing(1.1509376417668262,0.9913118073666528)));
+    vert.add(new Vec3(new Pointing(1.1510230276226834,0.9914855800960104)));
+    vert.add(new Vec3(new Pointing(1.1511701646336845,0.9916624962872871)));
+    vert.add(new Vec3(new Pointing(1.1513467444499845,0.9918747650352789)));
+    vert.add(new Vec3(new Pointing(1.151493907126133,0.9920516301034698)));
+    vert.add(new Vec3(new Pointing(1.15167051772407,0.9922638375354705)));
+    vert.add(new Vec3(new Pointing(1.1517825427272692,0.9925404659613722)));
+    vert.add(new Vec3(new Pointing(1.1518945962236837,0.9928170667717601)));
+    vert.add(new Vec3(new Pointing(1.151944936626454,0.9930905238387734)));
+    vert.add(new Vec3(new Pointing(1.1519364038488704,0.9932932756669433)));
+    vert.add(new Vec3(new Pointing(1.1519545044629247,0.9935989574717053)));
+    vert.add(new Vec3(new Pointing(1.1518899290891478,0.9936634411834805)));
+    vert.add(new Vec3(new Pointing(1.1518576419864373,0.9936956844356148)));
+    vert.add(new Vec3(new Pointing(1.1515670755926695,0.9939859156123069)));
+    vert.add(new Vec3(new Pointing(1.1514056634584344,0.9941471877691483)));
+    vert.add(new Vec3(new Pointing(1.151209167317511,0.9944083526588667)));
+    vert.add(new Vec3(new Pointing(1.1510098905412778,0.9947371775119466)));
+    vert.add(new Vec3(new Pointing(1.1509074670044037,0.9949692293531077)));
+    vert.add(new Vec3(new Pointing(1.1507939027845748,0.9954717874109883)));
+    vert.add(new Vec3(new Pointing(1.1507154681212395,0.9958744790360815)));
+    vert.add(new Vec3(new Pointing(1.150728328381526,0.9963155562525036)));
+    vert.add(new Vec3(new Pointing(1.1507145219246022,0.9966536818156724)));
+    vert.add(new Vec3(new Pointing(1.150698010346289,0.9970594382294491)));
+    vert.add(new Vec3(new Pointing(1.1507515235186312,0.9972653214392541)));
+    vert.add(new Vec3(new Pointing(1.15074330622707,0.9974681979653209)));
+    vert.add(new Vec3(new Pointing(1.150794120124925,0.9977416918927585)));
+    vert.add(new Vec3(new Pointing(1.1508449617882088,0.9980151735411477)));
+    vert.add(new Vec3(new Pointing(1.150810006084698,0.9981151193696918)));
+    vert.add(new Vec3(new Pointing(1.1508045689258863,0.9982503689627922)));
+    vert.add(new Vec3(new Pointing(1.1507669084789147,0.9984179465727627)));
+    vert.add(new Vec3(new Pointing(1.1507882982747644,0.9986561219049502)));
+    vert.add(new Vec3(new Pointing(1.1508097091375338,0.9988942928018621)));
+    vert.add(new Vec3(new Pointing(1.1508955843794588,0.9990677867461779)));
+    vert.add(new Vec3(new Pointing(1.1509814707456794,0.9992412674747779)));
+    vert.add(new Vec3(new Pointing(1.1510968986908656,0.999450015299713)));
+    vert.add(new Vec3(new Pointing(1.1511559609826625,0.9995205731460943)));
+    vert.add(new Vec3(new Pointing(1.151370737557223,0.9995646668380104)));
+    vert.add(new Vec3(new Pointing(1.1514620182432866,0.9996028778795772)));
+    vert.add(new Vec3(new Pointing(1.1515855148424001,0.9996087523184793)));
+    vert.add(new Vec3(new Pointing(1.1516794788958802,0.9995793575868965)));
+    vert.add(new Vec3(new Pointing(1.15174122717978,0.9995822953104395)));
+    vert.add(new Vec3(new Pointing(1.1518647237644064,0.9995881703312073)));
+    vert.add(new Vec3(new Pointing(1.151894256435611,0.9996234359315822)));
+    vert.add(new Vec3(new Pointing(1.1519855379350588,0.9996616359063851)));
+    vert.add(new Vec3(new Pointing(1.152015071556617,0.9996968986628608)));
+    checkPoly(vert,13,17,"");
+    }
+  }
diff -Nru healpix-java-3.40/src/java/src/healpix/essentials/test/MocTest.java healpix-java-3.50/src/java/src/healpix/essentials/test/MocTest.java
--- healpix-java-3.40/src/java/src/healpix/essentials/test/MocTest.java	1969-12-31 19:00:00.000000000 -0500
+++ healpix-java-3.50/src/java/src/healpix/essentials/test/MocTest.java	2015-07-05 02:56:22.000000000 -0400
@@ -0,0 +1,117 @@
+/*
+ *  This file is part of Healpix Java.
+ *
+ *  This code 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 code 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 code; 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.sourceforge.net
+ */
+package healpix.essentials.test;
+
+import healpix.essentials.*;
+import junit.framework.TestCase;
+import java.io.*;
+import java.util.Random;
+import java.util.Arrays;
+
+/** Tests for the Moc class
+
+    @copyright 2015 Max-Planck-Society
+    @author Martin Reinecke */
+public class MocTest extends TestCase
+  {
+  private static Moc randomMoc(int num, long start, int dist)
+    {
+    Random rng = new Random();
+    Moc moc = new Moc();
+    long curval=start+(1L<<58);
+    for (int i=0; i<num; ++i)
+      {
+      long v1=curval+1+rng.nextInt(dist);
+      long v2=v1+1+rng.nextInt(dist);
+      moc.addPixelRange(29,v1,v2);
+      curval=v2;
+      }
+    return moc;
+    }
+
+  public void testSimple() throws Exception
+    {
+    Moc moc=new Moc();
+    moc.addPixelRange(0,4,5);
+    moc.addPixelRange(0,6,7);
+    moc.addPixelRange(2,4,17);
+    moc.addPixelRange(10,3000000,3000001);
+
+    assertEquals("inconsistency",moc,moc.complement().complement());
+    assertEquals("inconsistency",moc,MocStringIO.mocFromString(" 0/4, 6 2/ \t 4 -16 10/3000000 \t\n "));
+    assertEquals("inconsistency",moc,MocStringIO.mocFromString("0/6 2/ 5 2/4 2/6- 16 0/4  10/3000000"));
+    assertEquals("inconsistency",moc,MocStringIO.mocFromString
+      ("{\"0\":[6] , \"2\": [5 ], \"2\":[  4,6,7,8,9,10,11,12,13,14,15,16], \"0\":[4],  \"10\":[3000000]}"));
+    assertEquals("inconsistency",moc,MocStringIO.mocFromString(MocStringIO.mocToStringASCII(moc)));
+    assertEquals("inconsistency",moc,MocStringIO.mocFromString(MocStringIO.mocToStringJSON(moc)));
+    assertEquals("inconsistency",moc,Moc.fromUniq(moc.toUniq()));
+    assertEquals("inconsistency",moc.maxOrder(),10);
+    Moc xtmp = moc.degradedToOrder(8,false);
+    assertTrue("inconsistency",moc.contains(xtmp));
+    assertFalse("inconsistency",xtmp.contains(moc));
+    assertTrue("inconsistency",xtmp.overlaps(moc));
+    xtmp=moc.degradedToOrder(8,true);
+    assertFalse("inconsistency",moc.contains(xtmp));
+    assertTrue("inconsistency",xtmp.contains(moc));
+    assertEquals("inconsistency",moc,Moc.fromCompressed(moc.toCompressed()));
+    }
+
+  public void testPeano() throws Exception
+    {
+    HealpixBase base = new HealpixBase (8192,Scheme.NESTED);
+    RangeSet lrs=base.queryDisc(new Pointing(new Vec3(1,0,0)),Constants.halfpi/9.);
+    Moc moc=new Moc(lrs,13);
+
+     long[] arr=moc.toUniq();
+    for (int i=0; i<arr.length; ++i)
+      {
+      int order=HealpixUtils.uniq2order(arr[i]);
+      long shift=1L<<(2*order+2);
+      arr[i]=HealpixUtils.nest2peano(arr[i]-shift,order)+shift;
+      }
+    Arrays.sort(arr);
+    Moc pmoc=Moc.fromUniq(arr);
+    arr=pmoc.toUniq();
+    for (int i=0; i<arr.length; ++i)
+      {
+      int order=HealpixUtils.uniq2order(arr[i]);
+      long shift=1L<<(2*order+2);
+      arr[i]=HealpixUtils.peano2nest(arr[i]-shift,order)+shift;
+      }
+    Arrays.sort(arr);
+    Moc moc2=Moc.fromUniq(arr);
+    assertEquals(moc,moc2);
+    }
+
+  public void testOps() throws Exception
+    {
+    int niter = 100;
+    Moc full = MocStringIO.mocFromString("0/0-11");
+    Moc empty = MocStringIO.mocFromString("");
+    for (int iter=0; iter<niter; ++iter)
+      {
+      Moc a = randomMoc(1000, 0, 100);
+      assertEquals(a.complement().complement(),a);
+      assertFalse(a.overlaps(a.complement()));
+      assertEquals(a.union(a.complement()),full);
+      assertEquals(a.intersection(a.complement()),empty);
+      }
+    }
+  }
diff -Nru healpix-java-3.40/src/java/src/healpix/essentials/test/RangeSetTest.java healpix-java-3.50/src/java/src/healpix/essentials/test/RangeSetTest.java
--- healpix-java-3.40/src/java/src/healpix/essentials/test/RangeSetTest.java	1969-12-31 19:00:00.000000000 -0500
+++ healpix-java-3.50/src/java/src/healpix/essentials/test/RangeSetTest.java	2015-07-05 02:10:50.000000000 -0400
@@ -0,0 +1,317 @@
+/*
+ *  This file is part of Healpix Java.
+ *
+ *  This code 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 code 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 code; 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.sourceforge.net
+ */
+package healpix.essentials.test;
+
+import healpix.essentials.RangeSet;
+import junit.framework.TestCase;
+import java.io.*;
+import java.util.Random;
+
+/** Tests for the RangeSet class
+
+    @copyright 2014 Max-Planck-Society
+    @author Martin Reinecke */
+public class RangeSetTest extends TestCase {
+
+  private static RangeSet randomRangeSet(Random rng, int num, long start,
+    int dist)
+    {
+    RangeSet rs = new RangeSet(num);
+    long curval=start;
+    for (int i=0; i<num; ++i)
+      {
+      long v1=curval+1+rng.nextInt(dist);
+      long v2=v1+1+rng.nextInt(dist);
+      rs.append(v1,v2);
+      curval=v2;
+      }
+    return rs;
+    }
+
+  public void testAppend()
+    {
+    RangeSet b = new RangeSet();
+    b.append(1,11);
+    assertEquals(b,new RangeSet(new long[]{1,11}));
+    b.append(10,15);
+    assertEquals(b,new RangeSet(new long[]{1,15}));
+    b.append(1,15);
+    assertEquals(b,new RangeSet(new long[]{1,15}));
+    b.append(7,15);
+    assertEquals(b,new RangeSet(new long[]{1,15}));
+    b.append(30,41);
+    assertEquals(b,new RangeSet(new long[]{1,15,30,41}));
+    try
+      {
+      b.append(29,31);
+      fail("Should have raised an IllegalArgumentException");
+      }
+    catch (IllegalArgumentException expected) {}
+    }
+  public void testContains()
+    {
+    RangeSet b=new RangeSet(new long[]{1,11,30,41});
+    assertTrue(!b.contains(0));
+    assertTrue(b.contains(1));
+    assertTrue(b.contains(5));
+    assertTrue(b.contains(10));
+    assertTrue(!b.contains(11));
+    assertTrue(!b.contains(29));
+    assertTrue(b.contains(30));
+    assertTrue(b.contains(35));
+    assertTrue(b.contains(40));
+    assertTrue(!b.contains(41));
+    }
+  public void testAdd()
+    {
+    RangeSet b = new RangeSet();
+    b.add(5, 11);
+    assertEquals(b,new RangeSet(new long[]{5,11}));
+    b.add(1, 7);
+    assertEquals(b,new RangeSet(new long[]{1,11}));
+    b.add(1, 11);
+    assertEquals(b,new RangeSet(new long[]{1,11}));
+    b.add(30, 41);
+    assertEquals(b,new RangeSet(new long[]{1,11,30,41}));
+    b.add(1, 11);
+    assertEquals(b,new RangeSet(new long[]{1,11,30,41}));
+    b.add(-1,0);
+    assertEquals(b,new RangeSet(new long[]{-1,0,1,11,30,41}));
+    b.add(-2,-1);
+    assertEquals(b,new RangeSet(new long[]{-2,0,1,11,30,41}));
+    b.add(-2,-1);
+    assertEquals(b,new RangeSet(new long[]{-2,0,1,11,30,41}));
+    b.add(2, 11);
+    assertEquals(b,new RangeSet(new long[]{-2,0,1,11,30,41}));
+    b.add(1, 10);
+    assertEquals(b,new RangeSet(new long[]{-2,0,1,11,30,41}));
+    b.add(15, 21);
+    assertEquals(b,new RangeSet(new long[]{-2,0,1,11,15,21,30,41}));
+    }
+  public void testRemove()
+    {
+    RangeSet b = new RangeSet(new long[]{0,11,20,31});
+    b.remove(5,25);
+    assertEquals(b,new RangeSet(new long[]{0,5,25,31}));
+    b.remove(31,32);
+    assertEquals(b,new RangeSet(new long[]{0,5,25,31}));
+    b.remove(35,38);
+    assertEquals(b,new RangeSet(new long[]{0,5,25,31}));
+    b.remove(-90,-80);
+    assertEquals(b,new RangeSet(new long[]{0,5,25,31}));
+    b.remove(27,29);
+    assertEquals(b,new RangeSet(new long[]{0,5,25,27,29,31}));
+    b.remove(25,26);
+    assertEquals(b,new RangeSet(new long[]{0,5,26,27,29,31}));
+    b.remove(4,6);
+    assertEquals(b,new RangeSet(new long[]{0,4,26,27,29,31}));
+    b.remove(-20,40);
+    assertEquals(b,new RangeSet(new long[]{}));
+    b.remove(-20,40);
+    assertEquals(b,new RangeSet(new long[]{}));
+    }
+  public void testIntersect2()
+    {
+    RangeSet b = new RangeSet(new long[]{0,11,20,31});
+    b.intersect(2,29);
+    assertEquals(b,new RangeSet(new long[]{2,11,20,29}));
+    b.intersect(-8,50);
+    assertEquals(b,new RangeSet(new long[]{2,11,20,29}));
+    b.intersect(2,50);
+    assertEquals(b,new RangeSet(new long[]{2,11,20,29}));
+    b.intersect(2,29);
+    assertEquals(b,new RangeSet(new long[]{2,11,20,29}));
+    b.intersect(-18,29);
+    assertEquals(b,new RangeSet(new long[]{2,11,20,29}));
+    b.intersect(3,11);
+    assertEquals(b,new RangeSet(new long[]{3,11}));
+    b = new RangeSet(new long[]{0,11,20,31});
+    b.intersect(3,15);
+    assertEquals(b,new RangeSet(new long[]{3,11}));
+    b = new RangeSet(new long[]{0,11,20,31});
+    b.intersect(17,30);
+    assertEquals(b,new RangeSet(new long[]{20,30}));
+    b = new RangeSet(new long[]{0,11,20,31});
+    b.intersect(11,20);
+    assertEquals(b,new RangeSet(new long[]{}));
+    b = new RangeSet(new long[]{0,11,20,31});
+    b.intersect(-8,-7);
+    assertEquals(b,new RangeSet(new long[]{}));
+    b = new RangeSet(new long[]{0,11,20,31});
+    b.intersect(31,35);
+    assertEquals(b,new RangeSet(new long[]{}));
+    }
+  public void testUnion()
+    {
+    assertEquals(new RangeSet(new long[]{1,11,20,31,40,56}),
+                 new RangeSet(new long[]{20,31,40,51}).union
+                 (new RangeSet(new long[]{1,11,45,56})));
+    assertEquals(new RangeSet(new long[]{1,11,45,56}),
+                 new RangeSet(new long[]{}).union
+                 (new RangeSet(new long[]{1,11,45,56})));
+    assertEquals(new RangeSet(new long[]{1,11,45,56}),
+                 new RangeSet(new long[]{1,11,45,56}).union
+                 (new RangeSet(new long[]{})));
+    }
+
+  public void testIntersect()
+    {
+    assertEquals(new RangeSet(new long[]{22,24,45,51}),
+                 new RangeSet(new long[]{20,31,40,51}).intersection
+                 (new RangeSet(new long[]{1,11,22,24,45,56})));
+    assertEquals(new RangeSet(new long[]{20,31,40,51,90,101,110,121,200,201}),
+                 new RangeSet(new long[]{10,101,110,121,200,221}).intersection
+                 (new RangeSet(new long[]{20,31,40,51,90,201})));
+    assertEquals(new RangeSet(new long[]{}),
+                 new RangeSet(new long[]{20,31,40,51}).intersection
+                 (new RangeSet(new long[]{})));
+    assertEquals(new RangeSet(new long[]{}),
+                 new RangeSet(new long[]{}).intersection
+                 (new RangeSet(new long[]{20,31,40,51})));
+    }
+  public void testDifference()
+    {
+    assertEquals(new RangeSet(new long[]{20,31,40,45}),
+                 new RangeSet(new long[]{20,31,40,51}).difference
+                 (new RangeSet(new long[]{1,11,45,56})));
+    assertEquals(new RangeSet(new long[]{}),
+                 new RangeSet(new long[]{}).difference
+                 (new RangeSet(new long[]{1,11,45,56})));
+    assertEquals(new RangeSet(new long[]{1,11,45,56}),
+                 new RangeSet(new long[]{1,11,45,56}).difference
+                 (new RangeSet(new long[]{})));
+    }
+
+  public void testContainsRS()
+    {
+    RangeSet b = new RangeSet(new long[]{20,31,40,51});
+
+    assertFalse(b.contains(0,11));
+    assertFalse(b.contains(10,21));
+    assertFalse(b.contains(19,20));
+    assertTrue(b.contains(20,21));
+    assertTrue(b.contains(21,22));
+    assertTrue(b.contains(20,31));
+    assertFalse(b.contains(25,36));
+    assertTrue(b.contains(30,31));
+    assertFalse(b.contains(31,32));
+    assertFalse(b.contains(35,38));
+    assertFalse(b.contains(35,46));
+    assertTrue(b.contains(40,41));
+    assertFalse(b.contains(45,56));
+    assertFalse(b.contains(60,71));
+    }
+  public void testContainsRS2()
+    {
+    RangeSet b = new RangeSet(new long[]{20,31,40,51});
+
+    assertTrue(b.contains(new RangeSet(new long[]{20,31,40,51})));
+    assertTrue(b.contains(new RangeSet(new long[]{20,21})));
+    assertTrue(b.contains(new RangeSet(new long[]{50,51})));
+    assertFalse(b.contains(new RangeSet(new long[]{19,31,40,51})));
+    assertFalse(b.contains(new RangeSet(new long[]{20,31,40,52})));
+    assertFalse(b.contains(new RangeSet(new long[]{20,51})));
+    assertFalse(b.contains(new RangeSet(new long[]{0,1})));
+    assertFalse(b.contains(new RangeSet(new long[]{0,20,31,40,51,100})));
+    }
+  public void testOverlaps()
+    {
+    RangeSet b = new RangeSet(new long[]{20,31,40,51});
+
+    assertFalse(b.overlaps(0,11));
+    assertTrue(b.overlaps(10,21));
+    assertFalse(b.overlaps(19,20));
+    assertTrue(b.overlaps(20,21));
+    assertTrue(b.overlaps(21,22));
+    assertTrue(b.overlaps(20,31));
+    assertTrue(b.overlaps(25,36));
+    assertTrue(b.overlaps(30,37));
+    assertFalse(b.overlaps(31,32));
+    assertFalse(b.overlaps(35,38));
+    assertTrue(b.overlaps(35,46));
+    assertTrue(b.overlaps(40,41));
+    assertTrue(b.overlaps(45,56));
+    assertFalse(b.overlaps(60,71));
+    }
+  public void testOverlaps2()
+    {
+    RangeSet b = new RangeSet(new long[]{20,31,40,51});
+
+    assertTrue(b.overlaps(new RangeSet(new long[]{20,31,40,51})));
+    assertTrue(b.overlaps(new RangeSet(new long[]{20,21})));
+    assertTrue(b.overlaps(new RangeSet(new long[]{50,51})));
+    assertTrue(b.overlaps(new RangeSet(new long[]{19,31,40,51})));
+    assertTrue(b.overlaps(new RangeSet(new long[]{20,31,40,52})));
+    assertTrue(b.overlaps(new RangeSet(new long[]{20,51})));
+    assertFalse(b.overlaps(new RangeSet(new long[]{0,1})));
+    assertFalse(b.overlaps(new RangeSet(new long[]{0,20,31,40,51,100})));
+    }
+
+  public void testIterator()
+    {
+    RangeSet b = new RangeSet(new long[]{20,31,40,51});
+    RangeSet.ValueIterator it =b.valueIterator();
+    for (int i=0; i<b.nranges(); ++i)
+      for (long j=b.ivbegin(i); j<b.ivend(i); ++j)
+        {
+        assertTrue(it.hasNext());
+        assertEquals("value mismatch", j, it.next());
+        }
+    assertFalse(it.hasNext());
+    }
+
+  public void testCompress() throws Exception
+    {
+    RangeSet r = new RangeSet(new long[]{10,20,30,40,50,51});
+    assertEquals(r,RangeSet.fromCompressed(r.toCompressed()));
+    }
+
+  private static void rsOps(RangeSet a, RangeSet b) throws Exception
+    {
+    assertFalse(b.overlaps(a.difference(b)));
+    assertTrue(a.union(b).nval()>=a.nval());
+    assertTrue(a.union(b).nval()>=b.nval());
+    assertTrue(a.intersection(b).nval()<=a.nval());
+    assertTrue(a.intersection(b).nval()<=b.nval());
+    assertTrue(a.union(b).contains(a));
+    assertTrue(a.union(b).contains(b));
+    assertFalse(a.difference(b).overlaps(b));
+    assertFalse(b.difference(a).overlaps(a));
+    assertEquals(a.union(b).nval(),a.nval()+b.nval()-a.intersection(b).nval());
+    assertEquals(a.union(b).difference(a.intersection(b)).nval(),
+                 a.union(b).nval()-a.intersection(b).nval());
+    assertEquals(a,RangeSet.fromCompressed(a.toCompressed()));
+    }
+
+  public static void testOps() throws Exception
+    {
+    int niter = 100;
+    Random rng = new Random(42);
+    for (int iter=0; iter<niter; ++iter)
+      {
+      RangeSet a = randomRangeSet(rng, 1000, 0, 100);
+      RangeSet b = randomRangeSet(rng, 1000, 0, 100);
+      RangeSet c = randomRangeSet(rng, 10, 10000, 100);
+      rsOps(a,b);
+      rsOps(a,c);
+      rsOps(c,a);
+      }
+    }
+  }
diff -Nru healpix-java-3.40/src/java/src/healpix/essentials/Vec3.java healpix-java-3.50/src/java/src/healpix/essentials/Vec3.java
--- healpix-java-3.40/src/java/src/healpix/essentials/Vec3.java	1969-12-31 19:00:00.000000000 -0500
+++ healpix-java-3.50/src/java/src/healpix/essentials/Vec3.java	2015-04-01 08:52:19.000000000 -0400
@@ -0,0 +1,175 @@
+/*
+ *  This file is part of Healpix Java.
+ *
+ *  This code 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 code 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 code; 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.sourceforge.net
+ */
+
+package healpix.essentials;
+
+/** Cartesian 3-vector.
+    Instead of using the javax.vecmath.Vector3d class, this separate class was
+    implemented for two reasons: first, to avoid the external dependency from
+    vecmath.jar, and also because the function Vector3d.angle(Vector3d v1) is
+    too inaccurate for usage in Healpix for very small angles.
+
+    @copyright (C) 2011-2015 Max-Planck-Society
+    @author Martin Reinecke */
+public class Vec3
+  {
+  public double x, y, z;
+
+  /** Default constructor. */
+  public Vec3() {}
+
+  public Vec3 (Vec3 v)
+    { x=v.x; y=v.y; z=v.z; }
+  /** Creation from individual components */
+  public Vec3 (double x1, double y1, double z1)
+    { x=x1; y=y1; z=z1; }
+  /** Conversion from {@link Pointing} */
+  public Vec3 (Pointing ptg)
+    {
+    double sth = FastMath.sin(ptg.theta);
+    x=sth*FastMath.cos(ptg.phi);
+    y=sth*FastMath.sin(ptg.phi);
+    z=FastMath.cos(ptg.theta);
+    }
+  /** Conversion from {@link Zphi} */
+  public Vec3 (Zphi zphi)
+    {
+    double sth = Math.sqrt((1.0-zphi.z)*(1.0+zphi.z));
+    x=sth*FastMath.cos(zphi.phi);
+    y=sth*FastMath.sin(zphi.phi);
+    z=zphi.z;
+    }
+
+  public Vec3 (double[] arr)
+    {
+    if(arr.length!=3) throw new IllegalArgumentException("Wrong array size");
+    x = arr[0]; y = arr[1]; z = arr[2];
+    }
+
+  /** Vector length
+      @return the length of the vector. */
+  public final double length()
+    { return Math.sqrt(lengthSquared()); }
+
+  /** Squared vector length
+      @return the squared length of the vector. */
+  public final double lengthSquared()
+    { return x*x + y*y + z*z; }
+
+  /** Normalize the vector */
+  public void normalize()
+    {
+    double d = 1./length();
+    x *= d; y *= d; z *= d;
+    }
+  /** Return normalized vector */
+  public Vec3 norm()
+    {
+    double d = 1./length();
+    return new Vec3(x*d,y*d,z*d);
+    }
+
+  /** Angle between two vectors.
+      @param v1 another vector
+      @return the angle in radians between this vector and {@code v1};
+        constrained to the range [0,PI]. */
+  public final double angle(Vec3 v1)
+    { return FastMath.atan2(cross(v1).length(), dot(v1)); }
+
+  /** Vector cross product.
+      @param v another vector
+      @return the vector cross product between this vector and {@code v} */
+  public Vec3 cross(Vec3 v)
+    { return new Vec3(y*v.z - v.y*z, z*v.x - v.z*x, x*v.y - v.x*y); }
+
+  /** Vector scaling.
+    * @param n the scale number to be multiply to the coordinates {@code x,y,z}
+    * @return the vector with coordinates multiplied by {@code n}
+    */
+  public Vec3 mul(double n)
+    { return new Vec3(n*x, n*y, n*z); }
+
+  /** Invert the signs of all components */
+  public void flip()
+    { x=-x; y=-y; z=-z; }
+  public Vec3 flipped()
+    { return new Vec3(-x,-y,-z); }
+
+  /** Scale the vector by a given factor
+      @param n the scale factor */
+  public void scale(double n)
+    { x*=n; y*=n; z*=n; }
+
+  /** Computes the dot product of the this vector and {@code v1}.
+    * @param v1 another vector
+    * @return dot product */
+  public final double dot(Vec3 v1)
+    { return x*v1.x + y*v1.y + z*v1.z; }
+
+  /** Vector addition
+    * @param v the vector to be added
+    * @return addition result */
+  public Vec3 add(Vec3 v)
+    { return new Vec3(x+v.x, y+v.y, z+v.z); }
+
+  /** Vector subtraction
+    * @param v the vector to be subtracted
+    * @return subtraction result */
+  public Vec3 sub(Vec3 v)
+    { return new Vec3(x-v.x, y-v.y, z-v.z); }
+
+  public String toString()
+    {
+    StringBuilder s = new StringBuilder();
+    s.append("vec3(");s.append(x);
+    s.append(",");s.append(y);
+    s.append(",");s.append(z);
+    s.append(")");
+    return s.toString();
+    }
+
+  public double[] toArray()
+    { return new double[]{x,y,z}; }
+
+  public void toArray(double[] arr)
+    {
+    if(arr.length!=3) throw new IllegalArgumentException("wrong array size");
+    arr[0] = x; arr[1] = y; arr[2] = z;
+    }
+
+  public boolean equals(Object o)
+    {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+    Vec3 vec3 = (Vec3) o;
+    if (Double.compare(vec3.x, x) != 0) return false;
+    if (Double.compare(vec3.y, y) != 0) return false;
+    if (Double.compare(vec3.z, z) != 0) return false;
+    return true;
+    }
+
+  public int hashCode()
+    {
+    int result = Double.valueOf(x).hashCode();
+    result = 31 * result + Double.valueOf(y).hashCode();
+    result = 31 * result + Double.valueOf(z).hashCode();
+    return result;
+    }
+  }
diff -Nru healpix-java-3.40/src/java/src/healpix/essentials/Zphi.java healpix-java-3.50/src/java/src/healpix/essentials/Zphi.java
--- healpix-java-3.40/src/java/src/healpix/essentials/Zphi.java	1969-12-31 19:00:00.000000000 -0500
+++ healpix-java-3.50/src/java/src/healpix/essentials/Zphi.java	2013-04-03 09:15:40.000000000 -0400
@@ -0,0 +1,77 @@
+/*
+ *  This file is part of Healpix Java.
+ *
+ *  This code 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 code 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 code; 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.sourceforge.net
+ */
+
+package healpix.essentials;
+
+/** Class for storing a position on the unit sphere as a (z,phi)-tuple.
+
+    @copyright (C) 2011 Max-Planck-Society
+    @author Martin Reinecke */
+public final  class Zphi
+  {
+  /** Cosine of the colatitude, or z component of unit vector; Range [-1;1]. */
+  public double z;
+
+  /** Longitude in radians; Range [0; 2Pi]. */
+  public double phi;
+
+  /** Default constructor */
+  public Zphi() {}
+
+  /** Creation from individual components */
+  public Zphi (double z_, double phi_)
+    { z=z_; phi=phi_; }
+
+  /** Conversion from {@link Vec3} */
+  public Zphi (Vec3 v)
+    { z = v.z/v.length(); phi = FastMath.atan2(v.y,v.x); }
+
+  /** Conversion from {@link Pointing} */
+  public Zphi (Pointing ptg)
+    { z = FastMath.cos(ptg.theta); phi=ptg.phi; }
+
+  public String toString()
+    {
+    StringBuilder s = new StringBuilder();
+    s.append("zphi(");s.append(z);
+    s.append(",");s.append(phi);
+    s.append(")");
+    return s.toString();
+    }
+
+  public boolean equals(Object o)
+    {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+    Zphi zphi = (Zphi) o;
+    if (Double.compare(zphi.phi, phi) != 0) return false;
+    if (Double.compare(zphi.z, z) != 0) return false;
+    return true;
+    }
+
+  public int hashCode()
+    {
+    long temp = z != +0.0d ? Double.doubleToLongBits(z) : 0L;
+    int result = (int) (temp ^ (temp >>> 32));
+    temp = phi != +0.0d ? Double.doubleToLongBits(phi) : 0L;
+    result = 31 * result + (int) (temp ^ (temp >>> 32));
+    return result;
+    }
+  }


More information about the Debian-astro-maintainers mailing list