[geographiclib] 01/06: Imported Upstream version 1.44

Sebastiaan Couwenberg sebastic at moszumanska.debian.org
Sun Aug 16 09:21:21 UTC 2015


This is an automated email from the git hooks/post-receive script.

sebastic pushed a commit to branch master
in repository geographiclib.

commit 1b3c332fee5a4b20615f944aa88be8af754d2fd1
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Sun Aug 16 10:32:10 2015 +0200

    Imported Upstream version 1.44
---
 00README.txt                                       |   3 +
 CMakeLists.txt                                     |  24 +-
 NEWS                                               | 103 ++++-
 configure                                          |  37 +-
 configure.ac                                       |  20 +-
 doc/GeographicLib.dox.in                           | 209 ++++++++---
 doc/Makefile.am                                    |   8 +-
 doc/Makefile.in                                    |   8 +-
 doc/NETGeographicLib.dox                           |  16 +-
 doc/geodesic-c.dox                                 |  73 +++-
 doc/geodesic-for.dox                               |  49 ++-
 doc/geodseries30.html                              |  32 +-
 doc/scripts/GeographicLib/DMS.js                   |  67 +++-
 doc/scripts/GeographicLib/Geodesic.js              | 135 ++++---
 doc/scripts/GeographicLib/GeodesicLine.js          |  53 ++-
 doc/scripts/GeographicLib/Interface.js             |  40 +-
 doc/scripts/GeographicLib/Math.js                  |  79 +++-
 doc/scripts/geod-calc.html                         | 120 ++++--
 doc/scripts/geod-google-instructions.html          |  14 +-
 doc/scripts/geod-google.html                       |   9 +-
 doc/tmseries30.html                                |   2 +
 dotnet/NETGeographicLib/AlbersEqualArea.h          |  22 +-
 dotnet/NETGeographicLib/AzimuthalEquidistant.h     |  30 +-
 dotnet/NETGeographicLib/CassiniSoldner.h           |  11 +-
 dotnet/NETGeographicLib/DMS.cpp                    |   4 +-
 dotnet/NETGeographicLib/DMS.h                      |  50 ++-
 dotnet/NETGeographicLib/Ellipsoid.h                |   5 +-
 dotnet/NETGeographicLib/GARS.cpp                   |  57 +++
 dotnet/NETGeographicLib/GARS.h                     | 109 ++++++
 dotnet/NETGeographicLib/GeoCoords.cpp              |  16 +-
 dotnet/NETGeographicLib/GeoCoords.h                |  33 +-
 dotnet/NETGeographicLib/Geocentric.h               |   3 +-
 dotnet/NETGeographicLib/Geodesic.h                 |  29 +-
 dotnet/NETGeographicLib/GeodesicExact.h            |  29 +-
 dotnet/NETGeographicLib/GeodesicLine.h             |   8 +-
 dotnet/NETGeographicLib/GeodesicLineExact.h        |   8 +-
 dotnet/NETGeographicLib/Geohash.h                  |   4 +-
 dotnet/NETGeographicLib/Geoid.h                    |  19 +-
 dotnet/NETGeographicLib/Georef.cpp                 |  57 +++
 dotnet/NETGeographicLib/Georef.h                   | 119 ++++++
 dotnet/NETGeographicLib/Gnomonic.h                 |  39 +-
 dotnet/NETGeographicLib/LambertConformalConic.h    |  29 +-
 dotnet/NETGeographicLib/LocalCartesian.h           |  15 +-
 dotnet/NETGeographicLib/NETGeographicLib.cpp       |   8 +
 dotnet/NETGeographicLib/NETGeographicLib.h         |  27 ++
 dotnet/NETGeographicLib/OSGB.h                     |   3 +-
 dotnet/NETGeographicLib/PolarStereographic.h       |   3 +-
 dotnet/NETGeographicLib/PolygonArea.h              |  42 +--
 dotnet/NETGeographicLib/Rhumb.h                    |  22 +-
 dotnet/NETGeographicLib/TransverseMercator.h       |   8 +-
 dotnet/NETGeographicLib/TransverseMercatorExact.h  |   8 +-
 dotnet/NETGeographicLib/UTMUPS.h                   |   2 -
 dotnet/Projections/Form1.Designer.cs               |   1 -
 dotnet/Projections/MagneticPanel.cs                |   3 +
 dotnet/Projections/MiscPanel.Designer.cs           |  29 +-
 dotnet/Projections/MiscPanel.cs                    |  33 +-
 dotnet/Projections/Projections-vs13.csproj         |   1 -
 dotnet/examples/CS/example-GARS.cs                 |  36 ++
 dotnet/examples/CS/example-Georef.cs               |  38 ++
 dotnet/examples/ManagedCPP/example-GARS.cpp        |  32 ++
 dotnet/examples/ManagedCPP/example-Georef.cpp      |  34 ++
 dotnet/examples/VB/example-GARS.vb                 |  23 ++
 dotnet/examples/VB/example-Georef.vb               |  25 ++
 examples/CMakeLists.txt                            |   5 +-
 examples/GeoidToGTX.cpp                            |   8 +-
 examples/JacobiConformal.hpp                       |  14 +-
 examples/Makefile.am                               |   2 +
 examples/Makefile.in                               |   2 +
 examples/example-GARS.cpp                          |  40 ++
 examples/example-Georef.cpp                        |  42 +++
 include/GeographicLib/Accumulator.hpp              |  14 +-
 include/GeographicLib/AlbersEqualArea.hpp          |  19 +-
 include/GeographicLib/AzimuthalEquidistant.hpp     |  30 +-
 include/GeographicLib/CassiniSoldner.hpp           |  16 +-
 include/GeographicLib/CircularEngine.hpp           |  18 +-
 include/GeographicLib/Config.h                     |   4 +-
 include/GeographicLib/Constants.hpp                |  10 +-
 include/GeographicLib/DMS.hpp                      |  36 +-
 include/GeographicLib/Ellipsoid.hpp                |   5 +-
 include/GeographicLib/GARS.hpp                     | 143 +++++++
 include/GeographicLib/GeoCoords.hpp                |  35 +-
 include/GeographicLib/Geocentric.hpp               |   5 +-
 include/GeographicLib/Geodesic.hpp                 |  29 +-
 include/GeographicLib/GeodesicExact.hpp            |  21 +-
 include/GeographicLib/GeodesicLine.hpp             |  22 +-
 include/GeographicLib/GeodesicLineExact.hpp        |  24 +-
 include/GeographicLib/Geohash.hpp                  |  51 +--
 include/GeographicLib/Geoid.hpp                    |  35 +-
 include/GeographicLib/Georef.hpp                   | 160 ++++++++
 include/GeographicLib/Gnomonic.hpp                 |  26 +-
 include/GeographicLib/GravityCircle.hpp            |  14 +-
 include/GeographicLib/LambertConformalConic.hpp    |  21 +-
 include/GeographicLib/LocalCartesian.hpp           |  14 +-
 include/GeographicLib/MGRS.hpp                     |  41 +-
 include/GeographicLib/MagneticCircle.hpp           |   2 +-
 include/GeographicLib/Math.hpp                     | 238 +++++++++---
 include/GeographicLib/OSGB.hpp                     |   3 +-
 include/GeographicLib/PolarStereographic.hpp       |   3 +-
 include/GeographicLib/PolygonArea.hpp              |  30 +-
 include/GeographicLib/Rhumb.hpp                    |  19 +-
 include/GeographicLib/SphericalHarmonic.hpp        |  19 +-
 include/GeographicLib/TransverseMercator.hpp       |  19 +-
 include/GeographicLib/TransverseMercatorExact.hpp  |  14 +-
 include/GeographicLib/UTMUPS.hpp                   |   5 +-
 include/GeographicLib/Utility.hpp                  |  24 +-
 include/Makefile.am                                |   2 +
 include/Makefile.in                                |   2 +
 include/Makefile.mk                                |   2 +
 java/direct/pom.xml                                |   4 +-
 java/inverse/pom.xml                               |   4 +-
 java/planimeter/pom.xml                            |   4 +-
 java/pom.xml                                       |   2 +-
 .../main/java/net/sf/geographiclib/GeoMath.java    | 103 ++++-
 .../main/java/net/sf/geographiclib/Geodesic.java   | 184 +++++----
 .../java/net/sf/geographiclib/GeodesicLine.java    |  49 +--
 .../java/net/sf/geographiclib/PolygonArea.java     |  15 +-
 .../java/net/sf/geographiclib/package-info.java    |  48 ++-
 legacy/C/geodesic.c                                | 302 ++++++++-------
 legacy/C/geodesic.h                                |  77 ++--
 legacy/Fortran/geoddirect.for                      |   8 +-
 legacy/Fortran/geodesic.for                        | 417 +++++++++++++--------
 legacy/Fortran/geodesic.inc                        |   4 +
 legacy/Fortran/geodinverse.for                     |   8 +-
 man/CartConvert.1                                  |  30 +-
 man/CartConvert.1.html                             |  22 +-
 man/CartConvert.pod                                |  31 +-
 man/CartConvert.usage                              |  42 ++-
 man/ConicProj.1                                    |  23 +-
 man/ConicProj.1.html                               |  10 +-
 man/ConicProj.pod                                  |  22 +-
 man/ConicProj.usage                                |  28 +-
 man/GeoConvert.1                                   | 180 +++++----
 man/GeoConvert.1.html                              |  88 +++--
 man/GeoConvert.pod                                 | 165 ++++----
 man/GeoConvert.usage                               | 163 ++++----
 man/GeodSolve.1                                    |  60 +--
 man/GeodSolve.1.html                               |  25 +-
 man/GeodSolve.pod                                  |  59 +--
 man/GeodSolve.usage                                |  66 ++--
 man/GeodesicProj.1                                 |  40 +-
 man/GeodesicProj.1.html                            |  16 +-
 man/GeodesicProj.pod                               |  39 +-
 man/GeodesicProj.usage                             |  50 ++-
 man/GeoidEval.1                                    |  22 +-
 man/GeoidEval.1.html                               |   8 +-
 man/GeoidEval.pod                                  |  18 +-
 man/GeoidEval.usage                                |  22 +-
 man/Gravity.1                                      |  24 +-
 man/Gravity.1.html                                 |  10 +-
 man/Gravity.pod                                    |  23 +-
 man/Gravity.usage                                  |  32 +-
 man/MagneticField.1                                |  27 +-
 man/MagneticField.1.html                           |  10 +-
 man/MagneticField.pod                              |  26 +-
 man/MagneticField.usage                            |  39 +-
 man/Planimeter.1                                   |   8 +-
 man/Planimeter.1.html                              |   8 +-
 man/Planimeter.pod                                 |   7 +-
 man/Planimeter.usage                               |  21 +-
 man/RhumbSolve.1                                   |  36 +-
 man/RhumbSolve.1.html                              |  14 +-
 man/RhumbSolve.pod                                 |  37 +-
 man/RhumbSolve.usage                               |  47 +--
 man/TransverseMercatorProj.1                       |  21 +-
 man/TransverseMercatorProj.1.html                  |  10 +-
 man/TransverseMercatorProj.pod                     |  20 +-
 man/TransverseMercatorProj.usage                   |  26 +-
 matlab/Makefile.am                                 |   4 +-
 matlab/Makefile.in                                 |   4 +-
 matlab/geographiclib/Contents.m                    |  11 +-
 matlab/geographiclib/cassini_fwd.m                 |  21 +-
 matlab/geographiclib/eqdazim_fwd.m                 |   8 +-
 matlab/geographiclib/eqdazim_inv.m                 |   4 +-
 matlab/geographiclib/gedistance.m                  |  23 +-
 matlab/geographiclib/gedoc.m                       |   2 -
 matlab/geographiclib/geocent_fwd.m                 |  15 +-
 matlab/geographiclib/geocent_inv.m                 |   7 +-
 matlab/geographiclib/geoddistance.m                | 286 ++++++++------
 matlab/geographiclib/geoddoc.m                     |   2 -
 matlab/geographiclib/geodreckon.m                  |  45 +--
 matlab/geographiclib/geoid_height.m                |   7 +-
 matlab/geographiclib/gereckon.m                    |  34 +-
 matlab/geographiclib/gnomonic_fwd.m                |  12 +-
 matlab/geographiclib/gnomonic_inv.m                |  12 +-
 matlab/geographiclib/mgrs_fwd.m                    |  48 ++-
 matlab/geographiclib/mgrs_inv.m                    |  77 ++--
 matlab/geographiclib/polarst_fwd.m                 |  21 +-
 matlab/geographiclib/polarst_inv.m                 |  14 +-
 matlab/geographiclib/private/A2m1f.m               |   4 +-
 matlab/geographiclib/private/AngDiff.m             |   9 +-
 matlab/geographiclib/private/AngNormalize.m        |   5 +-
 matlab/geographiclib/private/AngNormalize2.m       |   8 -
 matlab/geographiclib/private/C1pf.m                |   4 +-
 matlab/geographiclib/private/C2f.m                 |   4 +-
 matlab/geographiclib/private/LatFix.m              |   9 +
 matlab/geographiclib/private/atan2dx.m             |  25 ++
 matlab/geographiclib/private/sincosdx.m            |  27 ++
 matlab/geographiclib/projdoc.m                     |   2 -
 matlab/geographiclib/tranmerc_fwd.m                |  33 +-
 matlab/geographiclib/tranmerc_inv.m                |  31 +-
 matlab/geographiclib/utmups_fwd.m                  |  10 +-
 maxima/geod.mac                                    |  26 +-
 maxima/geodesic.mac                                | 172 +++++----
 pom.xml                                            |   2 +-
 python/README.txt                                  |   2 +-
 python/geographiclib/__init__.py                   |   3 +
 python/geographiclib/geodesic.py                   | 167 +++++----
 python/geographiclib/geodesicline.py               |  67 ++--
 python/geographiclib/geomath.py                    |  65 +++-
 python/setup.py                                    |   2 +-
 src/AlbersEqualArea.cpp                            |  27 +-
 src/AzimuthalEquidistant.cpp                       |   9 +-
 src/CassiniSoldner.cpp                             |  27 +-
 src/DMS.cpp                                        |  78 ++--
 src/Ellipsoid.cpp                                  |  37 +-
 src/EllipticFunction.cpp                           |   8 +-
 src/GARS.cpp                                       | 122 ++++++
 src/GeoCoords.cpp                                  |  20 +-
 src/Geocentric.cpp                                 |  15 +-
 src/Geodesic.cpp                                   | 184 +++++----
 src/GeodesicExact.cpp                              |  99 ++---
 src/GeodesicLine.cpp                               |  31 +-
 src/GeodesicLineExact.cpp                          |  30 +-
 src/GeographicLib.pro                              |   6 +-
 src/Geohash.cpp                                    |  44 ++-
 src/Geoid.cpp                                      |  21 +-
 src/Georef.cpp                                     | 135 +++++++
 src/Gnomonic.cpp                                   |   9 +-
 src/GravityCircle.cpp                              |  12 +-
 src/GravityModel.cpp                               |   4 +-
 src/LambertConformalConic.cpp                      |  25 +-
 src/LocalCartesian.cpp                             |  14 +-
 src/MGRS.cpp                                       |  89 ++---
 src/MagneticCircle.cpp                             |   2 +-
 src/Makefile.am                                    |   4 +
 src/Makefile.in                                    |  10 +-
 src/Makefile.mk                                    |   4 +
 src/NormalGravity.cpp                              |  29 +-
 src/PolarStereographic.cpp                         |  21 +-
 src/PolygonArea.cpp                                |   7 +-
 src/Rhumb.cpp                                      |   8 +-
 src/TransverseMercator.cpp                         |  52 ++-
 src/TransverseMercatorExact.cpp                    |  10 +-
 src/UTMUPS.cpp                                     |  18 +-
 tools/CartConvert.cpp                              |  46 ++-
 tools/ConicProj.cpp                                |  26 +-
 tools/GeoConvert.cpp                               |  48 +--
 tools/GeodSolve.cpp                                |  73 ++--
 tools/GeodesicProj.cpp                             |  26 +-
 tools/GeoidEval.cpp                                |  16 +-
 tools/Gravity.cpp                                  |  20 +-
 tools/MagneticField.cpp                            |  18 +-
 tools/Planimeter.cpp                               |  13 +-
 tools/RhumbSolve.cpp                               |  53 +--
 tools/TransverseMercatorProj.cpp                   |  27 +-
 tools/tests.cmake                                  |  72 +++-
 windows/Geographic-vc10.vcxproj                    |   5 +-
 windows/Geographic-vc10x.vcxproj                   |   5 +-
 windows/Geographic-vc13n.vcxproj                   |   4 +
 windows/Geographic-vc9.vcproj                      |  16 +
 windows/NETGeographic-vc10.vcxproj                 |   4 +
 windows/NETGeographic-vc13.vcxproj                 |   8 +-
 262 files changed, 6026 insertions(+), 3366 deletions(-)

diff --git a/00README.txt b/00README.txt
index ea3cec8..3080e1b 100644
--- a/00README.txt
+++ b/00README.txt
@@ -45,6 +45,8 @@ Files
       Gnomonic.[ch]pp -- Ellipsoidal gnomonic projection
       OSGB.[ch]pp -- Ordnance Survey grid system
       Geohash.[ch]pp -- conversions for geohashes
+      GARS.[ch]pp -- conversions for GARS
+      Georef.[ch]pp -- conversions for georefs
       Ellipsoid.[ch]pp -- ellipsoid properties
       Rhumb.[ch]pp -- rhumb line calculations
 
@@ -65,6 +67,7 @@ Files
       Planimeter.cpp -- computer polygon areas
       RhumbSolve.cpp -- calculate rhumb lines
       geographiclib-get-geoids -- download geoid datasets
+      geographiclib-get-gravity -- download gravity models
       geographiclib-get-magnetic -- download geomagnetic models
 
     windows/
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5e350a0..b51b720 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,7 +2,7 @@ project (GeographicLib)
 
 # Version information
 set (PROJECT_VERSION_MAJOR 1)
-set (PROJECT_VERSION_MINOR 43)
+set (PROJECT_VERSION_MINOR 44)
 set (PROJECT_VERSION_PATCH 0)
 set (PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}")
 if (PROJECT_VERSION_PATCH GREATER 0)
@@ -43,7 +43,7 @@ endif ()
 # The library version tracks the numbering given by libtool in the
 # autoconf set up.
 set (LIBVERSION_API 14)
-set (LIBVERSION_BUILD 14.1.0)
+set (LIBVERSION_BUILD 14.2.0)
 string (TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWER)
 string (TOUPPER ${PROJECT_NAME} PROJECT_NAME_UPPER)
 
@@ -238,7 +238,8 @@ test_big_endian (GEOGRAPHICLIB_WORDS_BIGENDIAN)
 # Make the compiler more picky.
 if (MSVC)
   string (REGEX REPLACE "/W[0-4]" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
-  set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
+  # Turn on parallel builds for Visual Studio
+  set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4 /MP")
 else ()
   set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
   # check for C++11 support.  This flag is *not* propagated to clients
@@ -271,9 +272,13 @@ set (CMAKE_REQUIRED_FLAGS "${CMAKE_CXX_FLAGS}")
 check_cxx_source_compiles (
   "#include <cmath>
 int main() {
-  return int(std::hypot(3.0, 4.0) + std::expm1(0.5) + std::log1p(2.0) +
-             std::asinh(10.0) + std::atanh(0.8) + std::cbrt(8.0)) +
-             std::fma(1.0, 2.0, 3.0) + std::isfinite(4.0) + std::isnan(0.0);
+  int q;
+  return int(std::hypot(3.0, 4.0) + std::expm1(0.5) +
+             std::log1p(2.0) + std::asinh(10.0) +
+             std::atanh(0.8) + std::cbrt(8.0) +
+             std::fma(1.0, 2.0, 3.0) + std::remquo(100.0, 90.0, &q) +
+             std::remainder(100.0, 90.0)) +
+             std::isfinite(4.0) + std::isnan(0.0);
 }\n" CXX11_MATH)
 if (CXX11_MATH)
   add_definitions (-DGEOGRAPHICLIB_CXX11_MATH=1)
@@ -403,7 +408,8 @@ configure_file (
 # The documentation depends on doxygen.
 if (GEOGRAPHICLIB_DOCUMENTATION)
   set (DOXYGEN_SKIP_DOT ON)
-  find_package (Doxygen)
+  # Version 1.8.7 or later needed for …
+  find_package (Doxygen 1.8.7)
 endif ()
 
 # The man pages are written as pod files and converted to nroff format,
@@ -429,9 +435,9 @@ if (MAINTAINER)
   add_dependencies (distrib-all distrib-man)
 endif ()
 
-# Set a default build type for single-configuration cmake generators if
-# no build type is set.
 if (NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE)
+  # Set a default build type for single-configuration cmake generators
+  # if no build type is set.
   set (CMAKE_BUILD_TYPE Release)
 endif ()
 
diff --git a/NEWS b/NEWS
index 78f46e3..b4e3c16 100644
--- a/NEWS
+++ b/NEWS
@@ -4,7 +4,108 @@ For more information, see
 
     http://geographiclib.sourceforge.net/
 
-The current version of the library is 1.43.
+The current version of the library is 1.44.
+
+Changes between 1.44 (released 2015-08-14) and 1.43 versions:
+
+  * Various changes to improve accuracy, e.g., by minimizing round-off
+    errors:
+    + Add Math::sincosd, Math::sind, Math::cosd which take their
+      arguments in degrees.  These functions do exact range reduction
+      and thus they obey exactly the elementary properties of the
+      trigonometric functions, e.g., sin 9d = cos 81d =
+      - sin 123456789d.
+    + Math::AngNormalize now works for any angles, instead of angles in
+      the range [-540d, 540d); the function Math::AngNormalize2 is now
+      deprecated.
+    + This means that there is now no restriction on longitudes and
+      azimuths; any values can be used.
+    + Improve the accuracy of Math::atan2d.
+    + DMS::Decode avoids unnecessary round-off errors; thus 7:33:36 and
+      7.56 result in identical values.  DMS::Encode rounds ties to even.
+      These changes have also been made to DMS.js.
+    + More accurate rounding in MGRS::Reverse and mgrs_inv.m; this
+      change only makes a difference at sub-meter precisions.
+    + With MGRS::Forward and mgrs_fwd.m, ensure that digits in lower
+      precision results match those at higher precision; as a result,
+      strings of trailing 9s are less likely to be generated.  This
+      change only makes a difference at sub-meter precisions.
+    + Replace the series for A2 in the Geodesic class with one with
+      smaller truncation errors.
+    + Geodesic::Inverse sets s12 to zero for coincident points at pole
+      (instead of returning a tiny quantity).
+    + Math::LatFix returns its argument if it is in [-90d, 90d]; if not,
+      it returns NaN.
+    + Using Math::LatFix, routines which don't check their arguments now
+      interpret a latitude outside the legal range of [-90d, 90d] as a
+      NaN; such routines will return NaNs instead of finite but
+      incorrect results; caution: code that (dangerously) relied on the
+      "reasonable" results being returned for values of the latitude
+      outside the allowed range will now malfunction.
+
+  * All the utility programs accept the -w option to swap the
+    latitude-longitude order on input and output (and where appropriate
+    on the command-line arguments).  CartConvert now accepts the -p
+    option to set the precision; now all of the utilities except
+    GeoidEval accept -p.
+
+  * Add classes for GARS, the Global Area Reference System, and for
+    Georef, the World Geographic Reference System.
+
+  * Changes to DMS::Decode and DMS.js:
+    + tighten up the rules:
+      o 30:70.0 and 30:60 are illegal (minutes and second must be
+        strictly less than 60), however
+      o 30:60.0 and 30:60. are legal (floating point 60 is OK, since it
+        might have been generated by rounding 59.99...);
+    + generalize a+b concept, introduced in version 1.42, to any number
+      of pieces; thus 8+0:40-0:0:10 is interpreted as 8:39:50.
+
+  * Documentation fixes:
+    + update man pages to refer to GeoConvert(1) on handling of
+      geographic coordinates;
+    + document limitations of the series used for TransverseMercator;
+    + hide the documentation of the computation of the gradient of the
+      geoid height (now deprecated) in the Geoid class;
+    + warn about the possible misinterpretation of 7.0E+1 by
+      DMS::Decode;
+    + swaplatlong optional argument of DMS::DecodeLatLon and various
+      functions in the GeoCoords class is now called longfirst;
+    + require Doxygen 1.8.7 or later.
+
+  * More systematic treatment of version numbers:
+    + Python: __init__.py defines __version__ and __version_info__;
+    + JavaScript:
+      o Math.js defines Constants.version and Constants.version_string;
+      o version number included as comment in packed script
+        geographiclib.js;
+      o geod-calc.html and geod-google.html report the version number;
+      o http://geographiclib.sourceforge.net/scripts/ gives access to
+        earlier versions of geographiclib.js as geographiclib-m.nn.js;
+    + Fortran: add geover subroutine to return version numbers;
+    + Maxima: geodesic.mac defines geod_version;
+    + CGI scripts: these report the version numbers of the utilities.
+
+  * BUG FIXES:
+    + NormalGravity now works properly for a sphere (omega = f = J2 =
+      0), instead of returning NaNs (problem found by htallon);
+    + CassiniSoldner::Forward and cassini_fwd.m now returns the correct
+      azimuth for points at the pole.
+
+  * MATLAB-specific fixes:
+    + mgrs_fwd now treats treats prec > 11 as prec = 11;
+    + illegal letter combinations are now correctly detected by
+      mgrs_inv;
+    + fixed bug where mgrs_inv returned the wrong results for prec = 0
+      strings and center = 0;
+    + mgrs_inv now decodes prec = 11 strings properly;
+    + routines now return array results with the right shape;
+    + routines now properly handle mixed scalar and array arguments.
+
+  * Add Accumulator<T>::operator*=(T y).
+
+  * Geohash uses "invalid" instead of "nan" when the latitude or
+    longitude is a nan.
 
 Changes between 1.43 (released 2015-05-23) and 1.42 versions:
 
diff --git a/configure b/configure
index b86f85b..a630f37 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for GeographicLib 1.43.
+# Generated by GNU Autoconf 2.69 for GeographicLib 1.44.
 #
 # Report bugs to <charles at karney.com>.
 #
@@ -590,8 +590,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='GeographicLib'
 PACKAGE_TARNAME='geographiclib'
-PACKAGE_VERSION='1.43'
-PACKAGE_STRING='GeographicLib 1.43'
+PACKAGE_VERSION='1.44'
+PACKAGE_STRING='GeographicLib 1.44'
 PACKAGE_BUGREPORT='charles at karney.com'
 PACKAGE_URL=''
 
@@ -1343,7 +1343,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures GeographicLib 1.43 to adapt to many kinds of systems.
+\`configure' configures GeographicLib 1.44 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1414,7 +1414,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of GeographicLib 1.43:";;
+     short | recursive ) echo "Configuration of GeographicLib 1.44:";;
    esac
   cat <<\_ACEOF
 
@@ -1525,7 +1525,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-GeographicLib configure 1.43
+GeographicLib configure 1.44
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1966,7 +1966,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by GeographicLib $as_me 1.43, which was
+It was created by GeographicLib $as_me 1.44, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2943,7 +2943,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='geographiclib'
- VERSION='1.43'
+ VERSION='1.44'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -3037,7 +3037,7 @@ END
 fi
 
 GEOGRAPHICLIB_VERSION_MAJOR=1
-GEOGRAPHICLIB_VERSION_MINOR=43
+GEOGRAPHICLIB_VERSION_MINOR=44
 GEOGRAPHICLIB_VERSION_PATCH=0
 
 cat >>confdefs.h <<_ACEOF
@@ -3085,9 +3085,9 @@ fi
 ac_config_headers="$ac_config_headers include/GeographicLib/Config-ac.h"
 
 
-LT_CURRENT=15
+LT_CURRENT=16
 LT_REVISION=0
-LT_AGE=1
+LT_AGE=2
 
 
 
@@ -15628,8 +15628,10 @@ int
 main ()
 {
 return int(std::hypot(3.0, 4.0) + std::expm1(0.5) +
-                    std::log1p(2.0) + std::asinh(10.0) + std::atanh(0.8) +
-                    std::fma(1.0, 2.0, 3.0) + std::cbrt(8.0)) +
+                    std::log1p(2.0) + std::asinh(10.0) +
+                    std::atanh(0.8) + std::cbrt(8.0) +
+                    std::fma(1.0, 2.0, 3.0) + std::remquo(100.0, 90.0, &q) +
+                    std::remainder(100.0, 90.0)) +
                     std::isfinite(4.0) + std::isnan(0.0);
   ;
   return 0;
@@ -15642,7 +15644,7 @@ else
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 
-# Check for doxygen.
+# Check for doxygen.  Version 1.8.7 or later needed for …
 for ac_prog in doxygen
 do
   # Extract the first word of "$ac_prog", so it can be a program name with args.
@@ -15685,7 +15687,8 @@ fi
   test -n "$DOXYGEN" && break
 done
 
- if test "$DOXYGEN"; then
+ if test "$DOXYGEN" && test `"$DOXYGEN" --version |
+         sed 's/\b\([0-9]\)\b/0\1/g'` '>' 01.08.06.99; then
   HAVE_DOXYGEN_TRUE=
   HAVE_DOXYGEN_FALSE='#'
 else
@@ -16378,7 +16381,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by GeographicLib $as_me 1.43, which was
+This file was extended by GeographicLib $as_me 1.44, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -16444,7 +16447,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-GeographicLib config.status 1.43
+GeographicLib config.status 1.44
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
diff --git a/configure.ac b/configure.ac
index 1fe599e..454faae 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,7 +1,7 @@
 dnl
 dnl Copyright (C) 2009, Francesco P. Lovergine <frankie at debian.org>
 
-AC_INIT([GeographicLib],[1.43],[charles at karney.com])
+AC_INIT([GeographicLib],[1.44],[charles at karney.com])
 AC_CANONICAL_SYSTEM
 AC_PREREQ(2.61)
 AC_CONFIG_SRCDIR(src/Geodesic.cpp)
@@ -9,7 +9,7 @@ AC_CONFIG_MACRO_DIR(m4)
 AM_INIT_AUTOMAKE
 
 GEOGRAPHICLIB_VERSION_MAJOR=1
-GEOGRAPHICLIB_VERSION_MINOR=43
+GEOGRAPHICLIB_VERSION_MINOR=44
 GEOGRAPHICLIB_VERSION_PATCH=0
 AC_DEFINE_UNQUOTED([GEOGRAPHICLIB_VERSION_MAJOR],
         [$GEOGRAPHICLIB_VERSION_MAJOR],[major version number])
@@ -34,9 +34,9 @@ dnl Library code modified:              REVISION++
 dnl Interfaces changed/added/removed:   CURRENT++ REVISION=0
 dnl Interfaces added:                   AGE++
 dnl Interfaces removed:                 AGE=0
-LT_CURRENT=15
+LT_CURRENT=16
 LT_REVISION=0
-LT_AGE=1
+LT_AGE=2
 AC_SUBST(LT_CURRENT)
 AC_SUBST(LT_REVISION)
 AC_SUBST(LT_AGE)
@@ -63,15 +63,19 @@ AX_CHECK_COMPILE_FLAG([-std=c++11],
 # Check for C++11 math functions
 AC_TRY_COMPILE([#include <cmath>],
         [return int(std::hypot(3.0, 4.0) + std::expm1(0.5) +
-                    std::log1p(2.0) + std::asinh(10.0) + std::atanh(0.8) +
-                    std::fma(1.0, 2.0, 3.0) + std::cbrt(8.0)) +
+                    std::log1p(2.0) + std::asinh(10.0) +
+                    std::atanh(0.8) + std::cbrt(8.0) +
+                    std::fma(1.0, 2.0, 3.0) + std::remquo(100.0, 90.0, &q) +
+                    std::remainder(100.0, 90.0)) +
                     std::isfinite(4.0) + std::isnan(0.0);],
         [CXXFLAGS="$CXXFLAGS -DGEOGRAPHICLIB_CXX11_MATH=1"],
         [CXXFLAGS="$CXXFLAGS -DGEOGRAPHICLIB_CXX11_MATH=0"])
 
-# Check for doxygen.
+# Check for doxygen.  Version 1.8.7 or later needed for …
 AC_CHECK_PROGS([DOXYGEN], [doxygen])
-AM_CONDITIONAL([HAVE_DOXYGEN], [test "$DOXYGEN"])
+AM_CONDITIONAL([HAVE_DOXYGEN],
+        [test "$DOXYGEN" && test `"$DOXYGEN" --version |
+         sed 's/\b\([[0-9]]\)\b/0\1/g'` '>' 01.08.06.99])
 
 AC_CHECK_PROGS([POD2MAN], [pod2man])
 AC_CHECK_PROGS([POD2HTML], [pod2html])
diff --git a/doc/GeographicLib.dox.in b/doc/GeographicLib.dox.in
index 61e137c..2f98425 100644
--- a/doc/GeographicLib.dox.in
+++ b/doc/GeographicLib.dox.in
@@ -12,7 +12,7 @@ namespace GeographicLib {
 \mainpage GeographicLib library
 \author Charles F. F. Karney (charles at karney.com)
 \version @PROJECT_VERSION@
-\date 2015-05-23
+\date 2015-08-14
 
 \section abstract Abstract
 
@@ -34,8 +34,8 @@ the script for displaying
 <a href="../scripts/geod-google.html">geodesics in Google Maps</a>
 
 This library is <i>not</i> a general purpose projection library; use
-<a href="http://trac.osgeo.org/proj/">proj.4</a> for that.  On the other
-hand, it does provide the core functionality offered by
+<a href="https://github.com/OSGeo/proj.4/wiki">proj.4</a> for that.  On
+the other hand, it does provide the core functionality offered by
 <a href="http://earth-info.nima.mil/GandG/geotrans/">GEOTRANS</a>.
 
 \section download Download
@@ -1097,9 +1097,9 @@ typically throw errors (an exception is GeodesicLine).  However, calling
 the class functions with NaNs as arguments is not an error; NaNs are
 returned as appropriate.  "INV" is treated as an invalid zone
 designation by UTMUPS.  "INVALID" is the corresponding invalid MGRS
-string.  (Similarly "nan" is the equivalent invalid Geohash.)  NaNs allow
-the projection of polylines which are separated by NaNs; in this format
-they can be easily plotted in MATLAB.
+string (and similarly for GARS, Geohash, and Georef strings).  NaNs
+allow the projection of polylines which are separated by NaNs; in this
+format they can be easily plotted in MATLAB.
 
 A note about portability.  For the most part, the code uses standard C++
 and should be able to be deployed on any system with a modern C++
@@ -1225,7 +1225,14 @@ These examples include a "stripped" version of the JavaScript code, \code
 <script type="text/javascript"
         src="http://geographiclib.sf.net/scripts/geographiclib.js">
 </script> \endcode
-which loads faster.
+which loads faster.  This file gives you the latest version of the
+library.  If you need to use a specific version of this file, include a
+version number as in \code
+<script type="text/javascript"
+        src="http://geographiclib.sf.net/scripts/geographiclib-1.43.js">
+</script> \endcode
+You can visit http://geographiclib.sf.net/scripts/ to see which versions
+are available.
 
 \section python Python implementation
 
@@ -1239,26 +1246,29 @@ otherwise).  This contains implementations of the classes
 - Geodesic
 - GeodesicLine
 - PolygonAreaT
-.
-You can also download the python interface independent of the rest of
-GeographicLib from
+
+You can install the python interface independent of the rest of
+GeographicLib using pip \verbatim
+  pip install geographiclib \endverbatim
+This requires root privileges and you might first need to install the
+python-pip package.
+
+Alternatively download
 - <a href="http://pypi.python.org/pypi/geographiclib">
   http://pypi.python.org/pypi/geographiclib</a>
 .
-and then unpack the .tar.gz or .zip file.
-
-You can "install" these routines, so that they are in python's default
-path with, for example \verbatim
+and unpack the .tar.gz or .zip file.  You can "install" these routines,
+so that they are in python's default path with, for example \verbatim
   cd geographiclib-1.16
   python setup.py install
 \endverbatim
 (this will require root privileges).  Or else you can set the path
-within python using \code
+within python using \code{.py}
 >>> import sys
 >>> sys.path.append("/usr/local/lib/python/site-packages")
 \endcode
 
-An example of using this interface is \code
+An example of using this interface is \code{.py}
 >>> from geographiclib.geodesic import Geodesic
 >>> # The geodesic inverse problem
 ... Geodesic.WGS84.Inverse(-41.32, 174.81, 40.96, -5.50)
@@ -1278,7 +1288,7 @@ An example of using this interface is \code
 
 Another illustrative exercise is finding the point midway between JFK
 Airport to Singapore Changi Airport
-\code
+\code{.py}
 from geographiclib.geodesic import Geodesic
 
 # Coordinates of airports
@@ -1290,7 +1300,7 @@ g = Geodesic.WGS84.Inverse(lat1, lon1, lat2, lon2)
 
 # Compute midpoint starting at 1
 h = Geodesic.WGS84.Direct(lat1, lon1, g['azi1'], g['s12']/2)
-print(h['lat2'], h['lon2']);
+print(h['lat2'], h['lon2'])
 \endcode
 
 (Note: The initial version of setup.py was provided by Andrew MacIntyre
@@ -2493,7 +2503,7 @@ a regular grid and writes on the result in a
 <a href="http://vdatum.noaa.gov/dev/gtx_info.html#dev_gtx_binary">.gtx</a>
 file.  On an 8-processor Intel 2.66 GHz machine using OpenMP
 (-DHAVE_OPENMP=1), it takes about 40 minutes of elapsed time to compute
-the geoid height for EGM2008 on a 1' gride.  (Without these
+the geoid height for EGM2008 on a 1' grid.  (Without these
 optimizations, the computation would have taken about 200 days!)
 \include GeoidToGTX.cpp
 
@@ -3165,11 +3175,11 @@ where
 \end{align}
 \f]
 \verbatim
-A2 = (1 + 1/4 * eps^2
-        + 9/64 * eps^4
-        + 25/256 * eps^6
-        + 1225/16384 * eps^8
-        + 3969/65536 * eps^10) * (1 - eps);
+A2 = (1 - 3/4 * eps^2
+        - 7/64 * eps^4
+        - 11/256 * eps^6
+        - 375/16384 * eps^8
+        - 931/65536 * eps^10) / (1 + eps);
 \endverbatim
 \verbatim
 C2[1] = + 1/2 * eps
@@ -5223,7 +5233,7 @@ where
 \mathsf F_k(x,y)=
 \begin{bmatrix}
      \cos kd \sin kp\\
-\frac{\sin kd}d \cos kp
+     {\displaystyle\frac{\sin kd}d} \cos kp
 \end{bmatrix},
 \f]
 \f$d=\frac12(x-y)\f$, \f$p=\frac12(x+y)\f$, and, in the limit
@@ -5239,7 +5249,7 @@ where
 \f[
  \mathsf A(x,y) = 2\begin{bmatrix}
   \cos d \cos p & -d\sin d \sin p \\
-- \frac{\sin d}d \sin p &   \cos d \cos p
+- {\displaystyle\frac{\sin d}d} \sin p &   \cos d \cos p
 \end{bmatrix},
 \f]
 and \f$\lim_{d\rightarrow0}(\sin d)/d = 1\f$.  The standard Clenshaw
@@ -5277,7 +5287,8 @@ where
 \mathsf F_k(x,y)=
 \begin{bmatrix}
      \cos\bigl( (k+k_0)d \bigr) \sin \bigl( (k+k_0)p + x_0 \bigr)\\
-     \frac{\sin\bigl( (k+k_0)d \bigr)}d \cos \bigl( (k+k_0)p + x_0 \bigr)
+     {\displaystyle\frac{\sin\bigl( (k+k_0)d \bigr)}d}
+     \cos \bigl( (k+k_0)p + x_0 \bigr)
 \end{bmatrix}.
 \f]
 The recursion for \f$\mathsf B_k\f$ is identical to the previous case;
@@ -6204,7 +6215,7 @@ relations between φ, β, θ, and μ.  In addition, the
 expansions converge for <i>b</i>/<i>a</i> ∈ (0, ∞).
 (Some authors use the eccentricity as the expansion parameter, but the
 resulting series only converge for <i>b</i>/<i>a</i> ∈
-(0, √2).  These expansions were obtained with the the maxima
+(0, √2).)  These expansions were obtained with the the maxima
 code, <a href="auxlat.mac">auxlat.mac</a>.
 
 Here are the relations between φ, β, θ, and μ carried
@@ -6716,16 +6727,18 @@ Here's what you should know:
    recommended for installation for all users on a system.
  - Configuring with <code>-D GEOGRAPHICLIB_PRECISION=4</code> gives quad
    precision (113-bit precision) via boost::multiprecision::float128;
-   this requires <a href="http://www.boost.org"> boost</a> (version 1.54
-   or later) and the quadmath library (the package names are libquadmath
-   and libquadmath-devel).  This requires the use of g++.
+   this requires:
+   - <a href="http://www.boost.org"> Boost</a>, version 1.54 or later,
+   - the quadmath library (the package names are libquadmath
+     and libquadmath-devel),
+   - the use of g++.
  - Configuring with <code>-D GEOGRAPHICLIB_PRECISION=5</code> gives
-   arbitrary precision via mpfr::mpreal; this requires
-   <a href="http://www.mpfr.org"> MPFR</a> (version 3.0 or later),
-   <a href="http://www.holoborodko.com/pavel/mpfr"> MPFR C++</a>
-   (version 3.6.2 or later), and a compiler which supports the explicit
-   cast operator (e.g., g++ 4.5 or later, Visual Studio 12 2013 or
-   later).
+   arbitrary precision via mpfr::mpreal; this requires:
+   - <a href="http://www.mpfr.org"> MPFR</a>, version 3.0 or later,
+   - <a href="http://www.holoborodko.com/pavel/mpfr"> MPFR C++</a>
+     (version 3.6.2 or later),
+   - a compiler which supports the explicit cast operator (e.g., g++ 4.5
+     or later, Visual Studio 12 2013 or later).
  - MPFR, MPFR C++, and Boost all come with their own licenses.  Be sure
    to respect these.
  - The indicated precision is used for <b>all</b> floating point
@@ -6896,7 +6909,7 @@ The following steps needed to be taken
        were made member variables and so initialized when the
        constructor was called.
      - Some simple static real arrays (e.g., the interpolating stencils
-       for Geoid) were changes into integer arrays.
+       for Geoid) were changed into integer arrays.
      - Some static variables where converted to static functions similar
        to the definition of pi() above.
      - All the static instances of classes where converted as follows
@@ -6921,7 +6934,7 @@ The following steps needed to be taken
        // use
        const Geodesic& geod = Geodesic::WGS84(); \endcode
        This is the so-called
-       <a href="http://www.parashift.com/c++-faq/static-init-order-on-first-use.html">
+       <a href="https://isocpp.org/wiki/faq/ctors#static-init-order-on-first-use">
        "construct on first use idiom"</a>.  This is the most disruptive
        of the changes since it requires a different calling convention
        in user code.  However the old static initializations were
@@ -6990,6 +7003,104 @@ of the
 <a href="https://sourceforge.net/p/geographiclib/code/ci/release/tree/">
 git repository for GeographicLib</a>.
 
+ - <a href="http://geographiclib.sf.net/1.44">Version 1.44</a>
+   (released 2015-08-14)
+   - Various changes to improve accuracy, e.g., by minimizing round-off
+     errors:
+     - Add Math::sincosd, Math::sind, Math::cosd which take their
+       arguments in degrees.  These functions do exact range reduction
+       and thus they obey exactly the elementary properties of the
+       trigonometric functions, e.g., sin 9° = cos 81° = −
+       sin 123456789°.
+     - Math::AngNormalize now works for any angles, instead of angles in
+       the range [−540°, 540°); the function
+       Math::AngNormalize2 is now <b>deprecated</b>.
+     - This means that there is now no restriction on longitudes and
+       azimuths; any values can be used.
+     - Improve the accuracy of Math::atan2d.
+     - DMS::Decode avoids unnecessary round-off errors; thus 7:33:36 and
+       7.56 result in identical values.  DMS::Encode rounds ties to
+       even.  These changes have also been made to DMS.js.
+     - More accurate rounding in MGRS::Reverse and mgrs_inv.m; this
+       change only makes a difference at sub-meter precisions.
+     - With MGRS::Forward and mgrs_fwd.m, ensure that digits in lower
+       precision results match those at higher precision; as a result,
+       strings of trailing 9s are less likely to be generated.  This
+       change only makes a difference at sub-meter precisions.
+     - Replace the series for <i>A</i><sub>2</sub> in the Geodesic class
+       with one with smaller truncation errors.
+     - Geodesic::Inverse sets \e s12 to zero for coincident points at
+       pole (instead of returning a tiny quantity).
+     - Math::LatFix returns its argument if it is in [−90°,
+       90°]; if not, it returns NaN.
+     - Using Math::LatFix, routines which don't check their arguments
+       now interpret a latitude outside the legal range of
+       [−90°, 90°] as a NaN; such routines will return
+       NaNs instead of finite but incorrect results; <b>caution</b>:
+       code that (dangerously) relied on the "reasonable" results being
+       returned for values of the latitude outside the allowed range
+       will now malfunction.
+   - All the \ref utilities accept the -w option to swap the
+     latitude-longitude order on input and output (and where appropriate
+     on the command-line arguments).  CartConvert now accepts the -p
+     option to set the precision; now all of the utilities except
+     GeoidEval accept -p.
+   - Add classes for GARS, the Global Area Reference System, and for
+     Georef, the World Geographic Reference System.
+   - Changes to DMS::Decode and DMS.js:
+     - tighten up the rules:
+       - 30:70.0 and 30:60 are illegal (minutes and second must be
+         strictly less than 60), however
+       - 30:60.0 and 30:60. are legal (floating point 60 is OK, since it
+         might have been generated by rounding 59.99…);
+     - generalize a+b concept, introduced in version 1.42, to any number
+       of pieces; thus 8+0:40-0:0:10 is interpreted as 8:39:50.
+   - Documentation fixes:
+     - update man pages to refer to
+       <a href="GeoConvert.1.html">GeoConvert(1)</a> on handling of
+       geographic coordinates;
+     - document limitations of the series used for TransverseMercator;
+     - hide the documentation of the computation of the gradient of the
+       geoid height (now deprecated) in the Geoid class;
+     - warn about the possible misinterpretation of 7.0E+1 by
+       DMS::Decode;
+     - \e swaplatlong optional argument of DMS::DecodeLatLon and
+       various functions in the GeoCoords class is now called \e
+       longfirst;
+     - require Doxygen 1.8.7 or later.
+   - More systematic treatment of version numbers:
+     - Python: \__init\__.py defines \__version\__ and \__version_info\__;
+     - JavaScript:
+       - Math.js defines Constants.version and Constants.version_string;
+       - version number included as comment in packed script
+         geographiclib.js;
+       - <a href="../scripts/geod-calc.html">geod-calc.html</a> and
+         <a href="../scripts/geod-google.html">geod-google.html</a>
+         report the version number;
+       - http://geographiclib.sourceforge.net/scripts/ gives access to
+         earlier versions of geographiclib.js as
+         geographiclib-<i>m.nn</i>.js;
+     - Fortran: add geover subroutine to return version numbers;
+     - Maxima: geodesic.mac defines geod_version;
+     - CGI scripts: these report the version numbers of the utilities.
+   - BUG FIXES:
+     - NormalGravity now works properly for a sphere (\e omega = \e f =
+       \e J2 = 0), instead of returning NaNs (problem found by htallon);
+     - CassiniSoldner::Forward and cassini_fwd.m now returns the correct
+       azimuth for points at the pole.
+   - MATLAB-specific fixes:
+     - mgrs_fwd now treats treats prec > 11 as prec = 11;
+     - illegal letter combinations are now correctly detected by
+       mgrs_inv;
+     - fixed bug where mgrs_inv returned the wrong results for prec = 0
+       strings and center = 0;
+     - mgrs_inv now decodes prec = 11 strings properly;
+     - routines now return array results with the right shape;
+     - routines now properly handle mixed scalar and array arguments.
+   - Add Accumulator<T>::operator*=(T y).
+   - Geohash uses "invalid" instead of "nan" when the latitude or
+     longitude is a nan.
+
  - <a href="http://geographiclib.sf.net/1.43">Version 1.43</a>
    (released 2015-05-23)
    - Add the Enhanced Magnetic Model 2015, emm2015.  This is valid for
@@ -7019,7 +7130,7 @@ git repository for GeographicLib</a>.
        geodesic has encircled the earth.  (This option also affects the
        value of longitude reported when an inverse calculation is run
        with the -f option.)
-     - The inverse calculation with the JavaScript and python libraries
+     - The inverse calculation with the JavaScript and Python libraries
        similarly sets <code>lon1</code> and <code>lon2</code> in output
        dictionary respecting the LONG_UNROLL flag.
      - The online version of
@@ -7028,7 +7139,7 @@ git repository for GeographicLib</a>.
      - To support these changes DMS::DecodeLatLon no longer reduces the
        longitude to the range [−180°, 180°) and
        Math::AngRound now coverts −0 to +0.
-   - Add Math::polyval (also to C, Java, JavaScript, Fortran, python
+   - Add Math::polyval (also to C, Java, JavaScript, Fortran, Python
      versions of the library; this is a built-in function for
      MATLAB/Octave).  This evaluates a polynomial using Horner's method.
      The Maxima-generated code fragments for the evaluation of series in
@@ -7048,7 +7159,7 @@ git repository for GeographicLib</a>.
    - Minor internal changes:
      - GeodSolve sets the geodesic mask so that unnecessary calculations
        are avoided;
-     - some routines have migrated into a math class for for python,
+     - some routines have migrated into a math class for for Python,
        Java, JavaScript libraries.
    - A reminder: because of changes in the installation directories for
      non-Windows systems introduced in version 1.42, you should remove
@@ -7374,7 +7485,7 @@ git repository for GeographicLib</a>.
      - on Linux, the installed package is relocatable;
      - on MacOSX, the installed utilities can find the shared library.
    - Use a more precise value for OSGB::CentralScale().
-   - Add Arc routines to python interface.
+   - Add Arc routines to Python interface.
    - The Geod utility has been removed; the same functionality lives on
      with <a href="GeodSolve.1.html">GeodSolve</a> (introduced in
      version 1.30).
@@ -7425,13 +7536,13 @@ git repository for GeographicLib</a>.
        for the maven support);
      - FIX BUG: avoid altering input args in Fortran implementation;
      - more systematic treatment of very short geodesic;
-     - fixes to python port so that they work with version 3.x, in
+     - fixes to Python port so that they work with version 3.x, in
        addition to 2.x (courtesy of Amato);
      - accumulate the perimeter and area of polygons via a double-wide
        accumulator in Fortran, C, and MATLAB implementations (this is
        already included in the other implementations);
      - port PolygonArea::AddEdge and
-       PolygonArea::TestEdge to JavaScript and python
+       PolygonArea::TestEdge to JavaScript and Python
        interfaces;
      - include documentation on \ref geodshort.
    - Unix scripts for downloading datasets,
@@ -7538,7 +7649,7 @@ git repository for GeographicLib</a>.
      - explicitly check version of doxygen.
    - Fix building under cygwin.
    - Document restrictions on \e f in \ref intro.
-   - Fix python interface to work with version 2.6.x.
+   - Fix Python interface to work with version 2.6.x.
 
  - <a href="http://geographiclib.sf.net/1.23">Version 1.23</a>
    (released 2012-07-17)
@@ -7574,7 +7685,7 @@ git repository for GeographicLib</a>.
      - use COMMON_INSTALL_PATH to determine layout of installation
        directories;
      - as a consequence, the installation paths for the documentation,
-       and python and matlab interfaces are shortened for Windows;
+       and Python and MATLAB interfaces are shortened for Windows;
      - zip source distribution now uses DOS line endings;
      - the tests work in debug mode for Windows;
      - default setting of GEOGRAPHICLIB_DATA does not depend on
@@ -7701,10 +7812,10 @@ git repository for GeographicLib</a>.
    - Modify <a href="GeoidEval.1.html">GeoidEval</a> so that it can be
      used to convert the height datum for LIDAR data.
    - Modest speed-up of Geodesic::Inverse.
-   - Changes in python interface:
+   - Changes in Python interface:
      - FIX BUG in transcription of Geodesic::Inverse;
      - include setup.py for easy installation;
-     - python only distribution is available at
+     - Python only distribution is available at
        http://pypi.python.org/pypi/geographiclib
    - Supply a minimal Qt qmake project file for library
      src/Geographic.pro.
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 566d3c4..fc3e397 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -31,14 +31,16 @@ HPPFILES = \
 	$(top_srcdir)/include/GeographicLib/DMS.hpp \
 	$(top_srcdir)/include/GeographicLib/Ellipsoid.hpp \
 	$(top_srcdir)/include/GeographicLib/EllipticFunction.hpp \
-	$(top_srcdir)/include/GeographicLib/Geocentric.hpp \
+	$(top_srcdir)/include/GeographicLib/GARS.hpp \
 	$(top_srcdir)/include/GeographicLib/GeoCoords.hpp \
+	$(top_srcdir)/include/GeographicLib/Geocentric.hpp \
 	$(top_srcdir)/include/GeographicLib/Geodesic.hpp \
 	$(top_srcdir)/include/GeographicLib/GeodesicExact.hpp \
 	$(top_srcdir)/include/GeographicLib/GeodesicLine.hpp \
 	$(top_srcdir)/include/GeographicLib/GeodesicLineExact.hpp \
 	$(top_srcdir)/include/GeographicLib/Geohash.hpp \
 	$(top_srcdir)/include/GeographicLib/Geoid.hpp \
+	$(top_srcdir)/include/GeographicLib/Georef.hpp \
 	$(top_srcdir)/include/GeographicLib/Gnomonic.hpp \
 	$(top_srcdir)/include/GeographicLib/LambertConformalConic.hpp \
 	$(top_srcdir)/include/GeographicLib/LocalCartesian.hpp \
@@ -58,12 +60,14 @@ ALLSOURCES = \
 	$(top_srcdir)/src/DMS.cpp \
 	$(top_srcdir)/src/Ellipsoid.cpp \
 	$(top_srcdir)/src/EllipticFunction.cpp \
-	$(top_srcdir)/src/Geocentric.cpp \
+	$(top_srcdir)/src/GARS.cpp \
 	$(top_srcdir)/src/GeoCoords.cpp \
+	$(top_srcdir)/src/Geocentric.cpp \
 	$(top_srcdir)/src/Geodesic.cpp \
 	$(top_srcdir)/src/GeodesicLine.cpp \
 	$(top_srcdir)/src/Geohash.cpp \
 	$(top_srcdir)/src/Geoid.cpp \
+	$(top_srcdir)/src/Georef.cpp \
 	$(top_srcdir)/src/Gnomonic.cpp \
 	$(top_srcdir)/src/LambertConformalConic.cpp \
 	$(top_srcdir)/src/LocalCartesian.cpp \
diff --git a/doc/Makefile.in b/doc/Makefile.in
index de41ff1..a8af3a2 100644
--- a/doc/Makefile.in
+++ b/doc/Makefile.in
@@ -278,14 +278,16 @@ HPPFILES = \
 	$(top_srcdir)/include/GeographicLib/DMS.hpp \
 	$(top_srcdir)/include/GeographicLib/Ellipsoid.hpp \
 	$(top_srcdir)/include/GeographicLib/EllipticFunction.hpp \
-	$(top_srcdir)/include/GeographicLib/Geocentric.hpp \
+	$(top_srcdir)/include/GeographicLib/GARS.hpp \
 	$(top_srcdir)/include/GeographicLib/GeoCoords.hpp \
+	$(top_srcdir)/include/GeographicLib/Geocentric.hpp \
 	$(top_srcdir)/include/GeographicLib/Geodesic.hpp \
 	$(top_srcdir)/include/GeographicLib/GeodesicExact.hpp \
 	$(top_srcdir)/include/GeographicLib/GeodesicLine.hpp \
 	$(top_srcdir)/include/GeographicLib/GeodesicLineExact.hpp \
 	$(top_srcdir)/include/GeographicLib/Geohash.hpp \
 	$(top_srcdir)/include/GeographicLib/Geoid.hpp \
+	$(top_srcdir)/include/GeographicLib/Georef.hpp \
 	$(top_srcdir)/include/GeographicLib/Gnomonic.hpp \
 	$(top_srcdir)/include/GeographicLib/LambertConformalConic.hpp \
 	$(top_srcdir)/include/GeographicLib/LocalCartesian.hpp \
@@ -305,12 +307,14 @@ ALLSOURCES = \
 	$(top_srcdir)/src/DMS.cpp \
 	$(top_srcdir)/src/Ellipsoid.cpp \
 	$(top_srcdir)/src/EllipticFunction.cpp \
-	$(top_srcdir)/src/Geocentric.cpp \
+	$(top_srcdir)/src/GARS.cpp \
 	$(top_srcdir)/src/GeoCoords.cpp \
+	$(top_srcdir)/src/Geocentric.cpp \
 	$(top_srcdir)/src/Geodesic.cpp \
 	$(top_srcdir)/src/GeodesicLine.cpp \
 	$(top_srcdir)/src/Geohash.cpp \
 	$(top_srcdir)/src/Geoid.cpp \
+	$(top_srcdir)/src/Georef.cpp \
 	$(top_srcdir)/src/Gnomonic.cpp \
 	$(top_srcdir)/src/LambertConformalConic.cpp \
 	$(top_srcdir)/src/LocalCartesian.cpp \
diff --git a/doc/NETGeographicLib.dox b/doc/NETGeographicLib.dox
index d4cdf7c..2ace891 100644
--- a/doc/NETGeographicLib.dox
+++ b/doc/NETGeographicLib.dox
@@ -11,8 +11,8 @@
 /**
 \mainpage NETGeographicLib library
 \author Scott Heiman (mrmtdew2 at outlook.com)
-\version 1.40
-\date 2014-12-18
+\version 1.44
+\date 2015-08-01
 
 \section abstract-net Abstract
 
@@ -41,14 +41,15 @@ The NETGeographicLib class names are identical to the GeographicLib class names.
 All NETGeographicLib classes are in the NETGeographicLib namespace.
 
 NETGeographicLib exposes most of the GeographicLib classes.  The exceptions
-are SphericalEngine, GeographicLib::Math, and GeographicLib::Utility.  The
+are SphericalEngine, GeographicLib::Math, and most of GeographicLib::Utility.  The
 SphericalEngine class is a template class which (according to the comments in
 the SphericalEngine.h file) is not usually accessible to developers.  The
 GeographicLib::Math class contains several specialized functions required by
 GeographicLib classes.  They have limited use outside GeographicLib.  This class
 may be exposed in a future release if there is demand for it.  The functions
 provided by GeographicLib::Utility duplicate functions provided by existing .NET
-controls (DateTime).
+controls (DateTime).  The GeographicLib::Utility::fractionalyear function is
+available to .NET programmers by calling NETGeographicLib::Utility::FractionalYear.
 
 The SphericalCoefficients class replaces the SphericalEngine::coeff class.
 
@@ -59,7 +60,10 @@ in the header files contain a section labeled "INTERFACE DIFFERENCES" that detai
 the differences between the NETGeographicLib interfaces and the GeographicLib
 interfaces.  The differences are summarized in the text that follows.
 
-Default values for function parameters are not supported in .NET.
+Default values for function parameters are not supported in .NET.  If
+the documentation refers to a default value for a parameter, it applies
+only to GeographicLib.  However, such a "default" value often provides a
+reasonable choice for this parameter.
 
 Several GeographicLib class functions accept or return a "capabilities mask" as
 an unsigned integer.  The NETGeographicLib classes accept and return the capabilities
@@ -153,7 +157,7 @@ The following table lists the source code that demonstrates specific classes.
 <TR><TD>GravityPanel.cs</TD><TD>NormalGravity, GravityModel, GravityCircle</TD></TR>
 <TR><TD>LocalCartesianPanel.cs</TD><TD>LocalCartesian</TD></TR>
 <TR><TD>MagneticPanel.cs</TD><TD>MagneticModel, MagneticCircle</TD></TR>
-<TR><TD>MiscPanel.cs</TD><TD>DMS, Geohash</TD></TR>
+<TR><TD>MiscPanel.cs</TD><TD>DMS, Geohash, GARS, Georef</TD></TR>
 <TR><TD>PolarStereoPanel.cs</TD><TD>PolarStereographic</TD></TR>
 <TR><TD>PolyPanel.cs</TD><TD>PolygonArea</TD></TR>
 <TR><TD>ProjectionsPanel.cs</TD><TD>AzimuthalEquidistant, CassiniSoldner, Gnomonic</TD></TR>
diff --git a/doc/geodesic-c.dox b/doc/geodesic-c.dox
index 3416d80..7f7bbee 100644
--- a/doc/geodesic-c.dox
+++ b/doc/geodesic-c.dox
@@ -11,7 +11,7 @@
 /**
 \mainpage Geodesic routines implemented in C
 \author Charles F. F. Karney (charles at karney.com)
-\version 1.43
+\version 1.44
 
 \section abstract-c Abstract
 
@@ -27,27 +27,27 @@ about any C compiler.
 \section download-c Downloading the source
 
 The C library is part of %GeographicLib which available for download at
-- <a href="https://sf.net/projects/geographiclib/files/distrib/GeographicLib-1.43.tar.gz">
-  GeographicLib-1.43.tar.gz</a>
-- <a href="https://sf.net/projects/geographiclib/files/distrib/GeographicLib-1.43.zip">
-  GeographicLib-1.43.zip</a>
+- <a href="https://sf.net/projects/geographiclib/files/distrib/GeographicLib-1.44.tar.gz">
+  GeographicLib-1.44.tar.gz</a>
+- <a href="https://sf.net/projects/geographiclib/files/distrib/GeographicLib-1.44.zip">
+  GeographicLib-1.44.zip</a>
 .
 as either a compressed tar file (tar.gz) or a zip file.  After unpacking
-the source, the C library can be found in GeographicLib-1.43/legacy/C.
+the source, the C library can be found in GeographicLib-1.44/legacy/C.
 The library consists of two files geodesic.c and geodesic.h.
 
 The library is also included as part of
-<a href="http://trac.osgeo.org/proj/">proj.4</a> starting with version
-4.9.0, where is used as the computational backend for
-<a href="http://trac.osgeo.org/proj/wiki/man_geod">geod(1)</a>.
+<a href="https://github.com/OSGeo/proj.4/wiki">proj.4</a> starting with
+version 4.9.0, where it is used as the computational backend for
+<a href="https://github.com/OSGeo/proj.4/wiki/Mangeod">geod(1)</a>.
 Instructions for how to use the library via proj.4 are given below.
 
-\section doc Library documentation
+\section doc-c Library documentation
 
 The interface to the library is documented via doxygen in the header
 file.  To access this, see geodesic.h.
 
-\section samples Sample programs
+\section samples-c Sample programs
 
 Also included are 3 small test programs:
  - direct.c is a simple command line utility for solving the
@@ -81,18 +81,35 @@ cc -c -I/usr/local/include inverse.c
 cc -o inverse inverse.o -lproj -L/usr/local/lib -Wl,-rpath=/usr/local/lib
 echo 30 0 29.5 179.5 | ./inverse \endverbatim
 
-\section library Using the library
+\section library-c Using the library
 
-- Put @verbatim
-  #include "geodesic.h" @endverbatim
+- Put @code{.c}
+  #include "geodesic.h"
+  @endcode
   in your source code.  If you are using the library via proj.4, change
-  this to @verbatim
-  #include <geodesic.h> @endverbatim
-- make calls to the geodesic routines from your code.  The interface to
+  this to @code{.c}
+  #include <geodesic.h>
+  @endcode
+- Make calls to the geodesic routines from your code.  The interface to
   the library is documented in geodesic.h.
 - Compile and link as described above.
+- If linking with proj.4, you might want to check that the version of
+  proj.4 contains the geodesic routines.  You can do this with @code{.c}
+  #include <proj_api.h>
+  #if PJ_VERSION >= 490
+  #include <geodesic.h>
+  #endif
+  ...
+  @endcode
 
-\section external External links
+- You can check the version of the geodesic library with, e.g.,
+  @code{.c}
+  #if GEODESIC_VERSION >= GEODESIC_VERSION_NUM(1,40,0)
+  ...
+  #endif
+  @endcode
+
+\section external-c External links
 
 - These algorithms are derived in C. F. F. Karney,
   <a href="https://dx.doi.org/10.1007/s00190-012-0578-z">
@@ -110,9 +127,27 @@ echo 30 0 29.5 179.5 | ./inverse \endverbatim
 - <a href="../java/index.html">The Java library</a>.
 - <a href="../Fortran/index.html">The Fortran library</a>.
 - Documentation on the C++ classes: GeographicLib::Geodesic,
-  GeographicLib::GeodesicLine, GeographicLib::PolygonArea.
+  GeographicLib::GeodesicLine, GeographicLib::PolygonAreaT.
 - The section in the %GeographicLib documentation on geodesics: \ref
   geodesic.
 - <a href="http://geographiclib.sf.net/geodesic-papers/biblio.html">
   An online geodesic bibliography</a>.
+- The wikipedia page,
+  <a href="https://en.wikipedia.org/wiki/Geodesics_on_an_ellipsoid">
+  Geodesics on an ellipsoid</a>.
+
+\section changes-c Change log
+
+ - <a href="http://geographiclib.sf.net/1.44">Version 1.44</a>
+   (released 2015-08-14)
+
+   - Improve accuracy of calculations by evaluating trigonometric
+     functions more carefully and replacing the series for the reduced
+     length with one with a smaller truncation error.
+   - The allowed ranges for longitudes and azimuths is now unlimited;
+     it used to be [−540°, 540°).
+   - Enforce the restriction of latitude to [−90°, 90°] by
+     returning NaNs if the latitude is outside this range.
+   - The inverse calculation sets \e s12 to zero for coincident points
+     at pole (instead of returning a tiny quantity).
 **********************************************************************/
diff --git a/doc/geodesic-for.dox b/doc/geodesic-for.dox
index 7845375..bd002eb 100644
--- a/doc/geodesic-for.dox
+++ b/doc/geodesic-for.dox
@@ -11,7 +11,7 @@
 /**
 \mainpage Geodesic routines implemented in Fortran
 \author Charles F. F. Karney (charles at karney.com)
-\version 1.43
+\version 1.44
 
 \section abstract-for Abstract
 
@@ -25,22 +25,22 @@ compile correctly with just about any Fortran compiler.
 \section download-for Downloading the source
 
 The Fortran library is part of %GeographicLib which available for download at
-- <a href="https://sf.net/projects/geographiclib/files/distrib/GeographicLib-1.43.tar.gz">
-  GeographicLib-1.43.tar.gz</a>
-- <a href="https://sf.net/projects/geographiclib/files/distrib/GeographicLib-1.43.zip">
-  GeographicLib-1.43.zip</a>
+- <a href="https://sf.net/projects/geographiclib/files/distrib/GeographicLib-1.44.tar.gz">
+  GeographicLib-1.44.tar.gz</a>
+- <a href="https://sf.net/projects/geographiclib/files/distrib/GeographicLib-1.44.zip">
+  GeographicLib-1.44.zip</a>
 .
 as either a compressed tar file (tar.gz) or a zip file.  After unpacking
 the source, the Fortran library can be found in
-GeographicLib-1.43/legacy/Fortran.  The library consists of the file
+GeographicLib-1.44/legacy/Fortran.  The library consists of the file
 geodesic.for.
 
-\section doc Library documentation
+\section doc-for Library documentation
 
 The interface to the library is documented via doxygen in the source
 file.  To access this, see geodesic.for.
 
-\section samples Sample programs
+\section samples-for Sample programs
 
 Also included are 3 small test programs:
  - geoddirect.for is a simple command line utility for solving the
@@ -80,21 +80,22 @@ The corresponding source files
  - ngscommon.for
  .
 are derived from the NGS source files
- - forward.for, version 2.0, dated 2002-10-28
- - inverse.for, version 3.0, dated 2012-11-27
+ - forward.for, version 2.0, dated 2002-08-21
+ - inverse.for, version 3.0, dated 2012-11-04
  .
 and are therefore in the public domain.
 
-\section library Using the library
+\section library-for Using the library
 
-- Optionall put @verbatim
-  include "geodesic.inc" @endverbatim
+- Optionally put @code{.for}
+  include "geodesic.inc"
+  @endcode
   in declaration section of your subroutines.
 - make calls to the geodesic routines from your code.  The interface to
   the library is documented in geodesic.for.
 - Compile and link as described above.
 
-\section external External links
+\section external-for External links
 
 - These algorithms are derived in C. F. F. Karney,
   <a href="https://dx.doi.org/10.1007/s00190-012-0578-z">
@@ -112,11 +113,27 @@ and are therefore in the public domain.
 - <a href="../C/index.html">The C library</a>.
 - <a href="../java/index.html">The Java library</a>.
 - Documentation on the C++ classes: GeographicLib::Geodesic,
-  GeographicLib::GeodesicLine, GeographicLib::PolygonArea.
+  GeographicLib::GeodesicLine, GeographicLib::PolygonAreaT.
 - The section in the %GeographicLib documentation on geodesics: \ref
   geodesic.
 - <a href="http://geographiclib.sf.net/geodesic-papers/biblio.html">
   An online geodesic bibliography</a>.
-**********************************************************************/
+- The wikipedia page,
+  <a href="https://en.wikipedia.org/wiki/Geodesics_on_an_ellipsoid">
+  Geodesics on an ellipsoid</a>.
+
+\section changes-for Change log
+
+ - <a href="http://geographiclib.sf.net/1.44">Version 1.44</a>
+   (released 2015-08-14)
 
+   - Improve accuracy of calculations by evaluating trigonometric
+     functions more carefully and replacing the series for the reduced
+     length with one with a smaller truncation error.
+   - The allowed ranges for longitudes and azimuths is now unlimited;
+     it used to be [−540°, 540°).
+   - The sample programs, geoddirect and geodinverse, enforce the
+     restriction of latitude to [−90°, 90°].
+   - The inverse calculation sets \e s12 to zero for coincident points
+     at pole (instead of returning a tiny quantity).
 **********************************************************************/
diff --git a/doc/geodseries30.html b/doc/geodseries30.html
index 98ed2de..fc8f6c9 100644
--- a/doc/geodseries30.html
+++ b/doc/geodseries30.html
@@ -3,6 +3,8 @@
     <title>
       Series for geodesic calculations
     </title>
+    <meta http-equiv="Content-Type"
+	  content="text/html; charset=ISO-8859-1">
   <body>
     <h2>
       Series for geodesic calculations
@@ -524,21 +526,21 @@ C1'[28] = + 137344334847260471742767128830849077140799/3817741892241658452955877
 C1'[29] = + 2381352350093111938327626556685002210278872879/37975078602127776631552109325582336000000 * eps^29;
 C1'[30] = + 20034557328168749612075941075238883149/182929433787470496587153418485760 * eps^30;
 
-A2 = (1 + 1/4 * eps^2
-        + 9/64 * eps^4
-        + 25/256 * eps^6
-        + 1225/16384 * eps^8
-        + 3969/65536 * eps^10
-        + 53361/1048576 * eps^12
-        + 184041/4194304 * eps^14
-        + 41409225/1073741824 * eps^16
-        + 147744025/4294967296 * eps^18
-        + 2133423721/68719476736 * eps^20
-        + 7775536041/274877906944 * eps^22
-        + 457028729521/17592186044416 * eps^24
-        + 1690195005625/70368744177664 * eps^26
-        + 25145962430625/1125899906842624 * eps^28
-        + 93990019574025/4503599627370496 * eps^30) * (1 - eps);
+A2 = (1 - 3/4 * eps^2
+        - 7/64 * eps^4
+        - 11/256 * eps^6
+        - 375/16384 * eps^8
+        - 931/65536 * eps^10
+        - 10143/1048576 * eps^12
+        - 29403/4194304 * eps^14
+        - 5705271/1073741824 * eps^16
+        - 17892875/4294967296 * eps^18
+        - 230480679/68719476736 * eps^20
+        - 758158843/274877906944 * eps^22
+        - 40605577103/17592186044416 * eps^24
+        - 137919912459/70368744177664 * eps^26
+        - 1897157659375/1125899906842624 * eps^28
+        - 6593830148475/4503599627370496 * eps^30) / (1 + eps);
 
 C2[1] = + 1/2 * eps
         + 1/16 * eps^3
diff --git a/doc/scripts/GeographicLib/DMS.js b/doc/scripts/GeographicLib/DMS.js
index 7e312f1..c79b65b 100644
--- a/doc/scripts/GeographicLib/DMS.js
+++ b/doc/scripts/GeographicLib/DMS.js
@@ -5,7 +5,7 @@
  * See the documentation for the C++ class.  The conversion is a literal
  * conversion from C++.
  *
- * Copyright (c) Charles Karney (2011-2014) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2011-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -40,8 +40,6 @@ GeographicLib.DMS = {};
 
   // return val, ind
   d.Decode = function(dms) {
-    var vals = {};
-    var errormsg = new String("");
     var dmsa = dms;
     dmsa = dmsa.replace(/\u00b0/g, 'd');
     dmsa = dmsa.replace(/\u00ba/g, 'd');
@@ -54,8 +52,43 @@ GeographicLib.DMS = {};
     dmsa = dmsa.replace(/\u201d/g, '"');
     dmsa = dmsa.replace(/\u2212/g, '-');
     dmsa = dmsa.replace(/''/g, '"');
-    dmsa = dmsa.replace(/^\s+/, "");
-    dmsa = dmsa.replace(/\s+$/, "");
+    dmsa = dmsa.trim();
+    var errormsg = new String("");
+    var end = dmsa.length;
+    var v = 0, i = 0, mi, pi, vals;
+    var ind1 = d.NONE, ind2;
+    var p, pa, pb;
+    // p is pointer to the next piece that needs decoding
+    for (p = 0; p < end; p = pb, ++i) {
+      pa = p;
+      // Skip over initial hemisphere letter (for i == 0)
+      if (i == 0 && d.lookup(d.hemispheres_, dmsa.charAt(pa)) >= 0)
+        ++pa;
+      // Skip over initial sign (checking for it if i == 0)
+      if (i > 0 || (pa < end && d.lookup(d.signs_, dmsa.charAt(pa)) >= 0))
+        ++pa;
+      // Find next sign
+      mi = dmsa.substr(pa, end - pa).indexOf('-');
+      pi = dmsa.substr(pa, end - pa).indexOf('+');
+      if (mi < 0) mi = end; else mi += pa;
+      if (pi < 0) pi = end; else pi += pa;
+      pb = Math.min(mi, pi);
+      vals = d.InternalDecode(dmsa.substr(p, pb - p));
+      v += vals.val; ind2 = vals.ind;
+      if (ind1 == d.NONE)
+        ind1 = ind2;
+      else if (!(ind2 == d.NONE || ind1 == ind2))
+        throw new Error("Incompatible hemisphere specifies in " +
+                        dmsa.substr(0, pb));
+    }
+    if (i == 0)
+      throw new Error("Empty or incomplete DMS string " + dmsa);
+    return {val: v, ind: ind1};
+  };
+
+  d.InternalDecode = function(dmsa) {
+    var vals = {};
+    var errormsg = new String("");
     do {                       // Executed once (provides the ability to break)
       var sign = 1;
       var beg = 0, end = dmsa.length;
@@ -147,7 +180,7 @@ GeographicLib.DMS = {};
               " component of " + dmsa.substr(beg, end - beg);
             break;
           }
-          if (digcount > 1) {
+          if (digcount > 0) {
             fcurrent = parseFloat(dmsa.substr(p - intcount - digcount - 1,
                                               intcount + digcount));
             icurrent = 0;
@@ -182,7 +215,7 @@ GeographicLib.DMS = {};
             dmsa.substr(beg, end - beg);
           break;
         }
-        if (digcount > 1) {
+        if (digcount > 0) {
           fcurrent = parseFloat(dmsa.substr(p - intcount - digcount,
                                             intcount + digcount));
           icurrent = 0;
@@ -196,18 +229,20 @@ GeographicLib.DMS = {};
         break;
       }
       // Note that we accept 59.999999... even though it rounds to 60.
-      if (ipieces[1] >= 60) {
+      if (ipieces[1] >= 60 || fpieces[1] > 60) {
         errormsg = "Minutes " + fpieces[1] + " not in range [0, 60)";
         break;
       }
-      if (ipieces[2] >= 60) {
+      if (ipieces[2] >= 60 || fpieces[2] > 60) {
         errormsg = "Seconds " + fpieces[2] + " not in range [0, 60)";
         break;
       }
       vals.ind = ind1;
       // Assume check on range of result is made by calling routine (which
       // might be able to offer a better diagnostic).
-      vals.val = sign * (fpieces[0] + (fpieces[1] + fpieces[2] / 60) / 60);
+      vals.val = sign *
+        ( fpieces[2] ? (60*(60*fpieces[0] + fpieces[1]) + fpieces[2]) / 3600 :
+          ( fpieces[1] ? (60*fpieces[0] + fpieces[1]) / 60 : fpieces[0] ) );
       return vals;
     } while (false);
     vals.val = d.NumMatch(dmsa);
@@ -231,7 +266,7 @@ GeographicLib.DMS = {};
     t = t.substr(p0, p1 + 1 - p0); // Length at least 3
     if (t === "NAN" || t === "1.#QNAN" || t === "1.#SNAN" || t === "1.#IND" ||
         t === "1.#R")
-      return sign * Number.NaN;
+      return Number.NaN;
     else if (t === "INF" || t === "1.#INF")
       return sign * Number.POSITIVE_INFINITY;
     return 0;
@@ -260,8 +295,6 @@ GeographicLib.DMS = {};
     var lat = ia === d.LATITUDE ? a : b, lon = ia === d.LATITUDE ? b : a;
     if (Math.abs(lat) > 90)
       throw new Error("Latitude " + lat + "d not in [-90d, 90d]");
-    if (lon < -540 || lon >= 540)
-      throw new Error("Latitude " + lon + "d not in [-540d, 540d)");
     vals.lat = lat;
     vals.lon = lon;
     return vals;
@@ -282,8 +315,6 @@ GeographicLib.DMS = {};
     if (ind === d.LATITUDE)
       throw new Error("Azimuth " + azistr +
                       " has a latitude hemisphere, N/S");
-    if (azi < -540 || azi >= 540)
-      throw new Error("Azimuth " + azistr + " not in range [-540d, 540d)");
     azi = m.AngNormalize(azi);
     return azi;
   };
@@ -313,6 +344,12 @@ GeographicLib.DMS = {};
     // fractional part.
     var
     idegree = Math.floor(angle),
+    fdegree = (angle - idegree) * scale + 0.5,
+    f = Math.floor(fdegree);
+    // Implement the "round ties to even" rule
+    fdegree = (f == fdegree && (f & 1)) ? f - 1 : f;
+    fdegree /= scale;
+
     fdegree = Math.floor((angle - idegree) * scale + 0.5) / scale;
     if (fdegree >= 1) {
       idegree += 1;
diff --git a/doc/scripts/GeographicLib/Geodesic.js b/doc/scripts/GeographicLib/Geodesic.js
index 322d1ae..c99ee0c 100644
--- a/doc/scripts/GeographicLib/Geodesic.js
+++ b/doc/scripts/GeographicLib/Geodesic.js
@@ -12,7 +12,7 @@
  *    https://dx.doi.org/10.1007/s00190-012-0578-z
  *    Addenda: http://geographiclib.sf.net/geod-addenda.html
  *
- * Copyright (c) Charles Karney (2011-2014) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2011-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -108,7 +108,7 @@ GeographicLib.GeodesicLine = {};
       S = p * q / 4,            // S = r^3 * s
       r2 = m.sq(r),
       r3 = r * r2,
-      // The discrimant of the quadratic equation for T3.  This is
+      // The discriminant of the quadratic equation for T3.  This is
       // zero on the evolute curve p^(1/3)+q^(1/3) = 1
       disc = S * (S + 2 * r3);
       var u = r;
@@ -218,12 +218,12 @@ GeographicLib.GeodesicLine = {};
   // The scale factor A2-1 = mean value of (d/dsigma)I2 - 1
   g.A2m1f = function(eps) {
     var coeff = [
-      // A2/(1-eps)-1, polynomial in eps2 of order 3
-      25, 36, 64, 0, 256,
+      // (eps+1)*A2-1, polynomial in eps2 of order 3
+      -11, -28, -192, 0, 256,
     ];
     var p = Math.floor(g.nA2_/2);
     var t = m.polyval(p, coeff, 0, m.sq(eps)) / coeff[p + 1];
-    return t * (1 - eps) - eps;
+    return (t - eps) / (1 + eps);
   };
 
   // The coefficients C2[l] in the Fourier expansion of B2
@@ -449,38 +449,58 @@ GeographicLib.GeodesicLine = {};
   // return s12b, m12b, m0, M12, M21
   g.Geodesic.prototype.Lengths = function(eps, sig12,
                                           ssig1, csig1, dn1, ssig2, csig2, dn2,
-                                          cbet1, cbet2, scalep,
+                                          cbet1, cbet2, outmask,
                                           C1a, C2a) {
-    var vals = {};
     // Return m12b = (reduced length)/_b; also calculate s12b =
     // distance/_b, and m0 = coefficient of secular term in
     // expression for reduced length.
-    g.C1f(eps, C1a);
-    g.C2f(eps, C2a);
-    var
-    A1m1 = g.A1m1f(eps),
-    AB1 = (1 + A1m1) * (g.SinCosSeries(true, ssig2, csig2, C1a) -
-                        g.SinCosSeries(true, ssig1, csig1, C1a)),
-    A2m1 = g.A2m1f(eps),
-    AB2 = (1 + A2m1) * (g.SinCosSeries(true, ssig2, csig2, C2a) -
-                        g.SinCosSeries(true, ssig1, csig1, C2a));
-    vals.m0 = A1m1 - A2m1;
-    var J12 = vals.m0 * sig12 + (AB1 - AB2);
-    // Missing a factor of _b.
-    // Add parens around (csig1 * ssig2) and (ssig1 * csig2) to
-    // ensure accurate cancellation in the case of coincident
-    // points.
-    vals.m12b = dn2 * (csig1 * ssig2) - dn1 * (ssig1 * csig2) -
-      csig1 * csig2 * J12;
-    // Missing a factor of _b
-    vals.s12b = (1 + A1m1) * sig12 + AB1;
-    if (scalep) {
+    outmask &= g.OUT_MASK;
+    var vals = {};
+
+    var m0x = 0, J12 = 0, A1 = 0, A2 = 0;
+    if (outmask & (g.DISTANCE | g.REDUCEDLENGTH | g.GEODESICSCALE)) {
+      A1 = g.A1m1f(eps);
+      g.C1f(eps, C1a);
+      if (outmask & (g.REDUCEDLENGTH | g.GEODESICSCALE)) {
+        A2 = g.A2m1f(eps);
+        g.C2f(eps, C2a);
+        m0x = A1 - A2;
+        A2 = 1 + A2;
+      }
+      A1 = 1 + A1;
+    }
+    if (outmask & g.DISTANCE) {
+      var B1 = g.SinCosSeries(true, ssig2, csig2, C1a) -
+        g.SinCosSeries(true, ssig1, csig1, C1a);
+      // Missing a factor of _b
+      vals.s12b = A1 * (sig12 + B1);
+      if (outmask & (g.REDUCEDLENGTH | g.GEODESICSCALE)) {
+        var B2 = g.SinCosSeries(true, ssig2, csig2, C2a) -
+          g.SinCosSeries(true, ssig1, csig1, C2a);
+        J12 = m0x * sig12 + (A1 * B1 - A2 * B2);
+      }
+    } else if (outmask & (g.REDUCEDLENGTH | g.GEODESICSCALE)) {
+      // Assume here that nC1_ >= nC2_
+      for (var l = 1; l <= g.nC2_; ++l)
+        C2a[l] = A1 * C1a[l] - A2 * C2a[l];
+      J12 = m0x * sig12 + (g.SinCosSeries(true, ssig2, csig2, C2a) -
+                           g.SinCosSeries(true, ssig1, csig1, C2a));
+    }
+    if (outmask & g.REDUCEDLENGTH) {
+      vals.m0 = m0x;
+      // Missing a factor of _b.
+      // Add parens around (csig1 * ssig2) and (ssig1 * csig2) to ensure
+      // accurate cancellation in the case of coincident points.
+      vals.m12b = dn2 * (csig1 * ssig2) - dn1 * (ssig1 * csig2) -
+        csig1 * csig2 * J12;
+    }
+    if (outmask & g.GEODESICSCALE) {
       var csig12 = csig1 * csig2 + ssig1 * ssig2;
       var t = this._ep2 * (cbet1 - cbet2) * (cbet1 + cbet2) / (dn1 + dn2);
       vals.M12 = csig12 + (t * ssig2 - csig2 * J12) * ssig1 / dn1;
       vals.M21 = csig12 - (t * ssig1 - csig1 * J12) * ssig2 / dn2;
     }
-      return vals;
+    return vals;
   };
 
   // return sig12, salp1, calp1, salp2, calp2, dnm
@@ -567,7 +587,7 @@ GeographicLib.GeodesicLine = {};
         // in Inverse.
         var nvals = this.Lengths(this._n, Math.PI + bet12a,
                                  sbet1, -cbet1, dn1, sbet2, cbet2, dn2,
-                                 cbet1, cbet2, false, C1a, C2a);
+                                 cbet1, cbet2, g.REDUCEDLENGTH, C1a, C2a);
         m12b = nvals.m12b; m0 = nvals.m0;
         x = -1 + m12b / (cbet1 * cbet2 * m0 * Math.PI);
         betscale = x < -0.01 ? sbet12a / x :
@@ -713,7 +733,7 @@ GeographicLib.GeodesicLine = {};
         var nvals = this.Lengths(vals.eps, vals.sig12,
                                  vals.ssig1, vals.csig1, dn1,
                                  vals.ssig2, vals.csig2, dn2,
-                                 cbet1, cbet2, false, C1a, C2a);
+                                 cbet1, cbet2, g.REDUCEDLENGTH, C1a, C2a);
         vals.dlam12 = nvals.m12b;
         vals.dlam12 *= this._f1 / (vals.calp2 * cbet2);
       }
@@ -728,7 +748,13 @@ GeographicLib.GeodesicLine = {};
     // Compute longitude difference (AngDiff does this carefully).  Result is
     // in [-180, 180] but -180 is only for west-going geodesics.  180 is for
     // east-going and meridional geodesics.
-    var lon12 = m.AngDiff(m.AngNormalize(lon1), m.AngNormalize(lon2));
+    vals.lat1 = lat1 = m.LatFix(lat1); vals.lat2 = lat2 = m.LatFix(lat2);
+    var lon12 = m.AngDiff(lon1, lon2);
+    if (outmask & g.LONG_UNROLL) {
+      vals.lon1 = lon1; vals.lon2 = lon1 + lon12;
+    } else {
+      vals.lon1 = m.AngNormalize(lon1); vals.lon2 = m.AngNormalize(lon2);
+    }
     // If very close to being on the same half-meridian, then make it so.
     lon12 = m.AngRound(lon12);
     // Make longitude difference positive.
@@ -762,21 +788,19 @@ GeographicLib.GeodesicLine = {};
     // check, e.g., on verifying quadrants in atan2.  In addition, this
     // enforces some symmetries in the results returned.
 
-    var phi, sbet1, cbet1, sbet2, cbet2, s12x, m12x;
+    var sbet1, cbet1, sbet2, cbet2, s12x, m12x;
 
-    phi = lat1 * m.degree;
-    // Ensure cbet1 = +epsilon at poles
-    sbet1 = this._f1 * Math.sin(phi);
-    cbet1 = lat1 === -90 ? g.tiny_ : Math.cos(phi);
+    t = m.sincosd(lat1); sbet1 = this._f1 * t.s; cbet1 = t.c;
     // norm(sbet1, cbet1);
     t = m.hypot(sbet1, cbet1); sbet1 /= t; cbet1 /= t;
+    // Ensure cbet1 = +epsilon at poles
+    cbet1 = Math.max(g.tiny_, cbet1);
 
-    phi = lat2 * m.degree;
-    // Ensure cbet2 = +epsilon at poles
-    sbet2 = this._f1 * Math.sin(phi);
-    cbet2 = Math.abs(lat2) === 90 ? g.tiny_ : Math.cos(phi);
+    t = m.sincosd(lat2); sbet2 = this._f1 * t.s; cbet2 = t.c;
     // norm(sbet2, cbet2);
     t = m.hypot(sbet2, cbet2); sbet2 /= t; cbet2 /= t;
+    // Ensure cbet2 = +epsilon at poles
+    cbet2 = Math.max(g.tiny_, cbet2);
 
     // If cbet1 < -sbet1, then cbet2 - cbet1 is a sensitive measure of the
     // |bet1| - |bet2|.  Alternatively (cbet1 >= -sbet1), abs(sbet2) + sbet1 is
@@ -798,10 +822,8 @@ GeographicLib.GeodesicLine = {};
     dn1 = Math.sqrt(1 + this._ep2 * m.sq(sbet1)),
     dn2 = Math.sqrt(1 + this._ep2 * m.sq(sbet2));
 
-    var
-    lam12 = lon12 * m.degree,
-    slam12 = lon12 === 180 ? 0 : Math.sin(lam12),
-    clam12 = Math.cos(lam12);   // lon12 == 90 isn't interesting
+    var lam12 = lon12 * m.degree, slam12, clam12;
+    t = m.sincosd(lam12); slam12 = t.s; clam12 = t.c;
 
     var sig12, calp1, salp1, calp2, salp2;
     // index zero elements of these arrays are unused
@@ -829,9 +851,9 @@ GeographicLib.GeodesicLine = {};
       sig12 = Math.atan2(Math.max(csig1 * ssig2 - ssig1 * csig2, 0),
                          csig1 * csig2 + ssig1 * ssig2);
       nvals = this.Lengths(this._n, sig12,
-                               ssig1, csig1, dn1, ssig2, csig2, dn2,
-                               cbet1, cbet2, (outmask & g.GEODESICSCALE) !== 0,
-                               C1a, C2a);
+                           ssig1, csig1, dn1, ssig2, csig2, dn2, cbet1, cbet2,
+                           outmask | g.DISTANCE | g.REDUCEDLENGTH,
+                           C1a, C2a);
       s12x = nvals.s12b;
       m12x = nvals.m12b;
       // Ignore m0
@@ -847,6 +869,9 @@ GeographicLib.GeodesicLine = {};
       // In fact, we will have sig12 > pi/2 for meridional geodesic
       // which is not a shortest path.
       if (sig12 < 1 || m12x >= 0) {
+        // Need at least 2, to handle 90 0 90 180
+        if (sig12 < 3 * g.tiny_)
+          sig12 = m12x = s12x = 0;
         m12x *= this._b;
         s12x *= this._b;
         vals.a12 = sig12 / m.degree;
@@ -877,7 +902,7 @@ GeographicLib.GeodesicLine = {};
 
       // Figure a starting point for Newton's method
       nvals = this.InverseStart(sbet1, cbet1, dn1, sbet2, cbet2, dn2, lam12,
-                                    C1a, C2a);
+                                C1a, C2a);
       sig12 = nvals.sig12;
       salp1 = nvals.salp1;
       calp1 = nvals.calp1;
@@ -974,11 +999,12 @@ GeographicLib.GeodesicLine = {};
           tripb = (Math.abs(salp1a - salp1) + (calp1a - calp1) < g.tolb_ ||
                    Math.abs(salp1 - salp1b) + (calp1 - calp1b) < g.tolb_);
         }
+        var lengthmask = outmask |
+            (outmask & (g.REDUCEDLENGTH | g.GEODESICSCALE) ?
+             g.DISTANCE : g.NONE);
         nvals = this.Lengths(eps, sig12,
-                             ssig1, csig1, dn1, ssig2, csig2, dn2,
-                             cbet1, cbet2,
-                             (outmask & g.GEODESICSCALE) !== 0,
-                             C1a, C2a);
+                             ssig1, csig1, dn1, ssig2, csig2, dn2, cbet1, cbet2,
+                             lengthmask, C1a, C2a);
         s12x = nvals.s12b;
         m12x = nvals.m12b;
         // Ignore m0
@@ -1080,9 +1106,8 @@ GeographicLib.GeodesicLine = {};
     salp2 *= swapp * lonsign; calp2 *= swapp * latsign;
 
     if (outmask & g.AZIMUTH) {
-      // minus signs give range [-180, 180). 0- converts -0 to +0.
-      vals.azi1 = 0 - Math.atan2(-salp1, calp1) / m.degree;
-      vals.azi2 = 0 - Math.atan2(-salp2, calp2) / m.degree;
+      vals.azi1 = m.atan2d(salp1, calp1);
+      vals.azi2 = m.atan2d(salp2, calp2);
     }
 
     // Returned value in [0, 180]
diff --git a/doc/scripts/GeographicLib/GeodesicLine.js b/doc/scripts/GeographicLib/GeodesicLine.js
index a084f8e..fdabdd9 100644
--- a/doc/scripts/GeographicLib/GeodesicLine.js
+++ b/doc/scripts/GeographicLib/GeodesicLine.js
@@ -12,7 +12,7 @@
  *    https://dx.doi.org/10.1007/s00190-012-0578-z
  *    Addenda: http://geographiclib.sf.net/geod-addenda.html
  *
- * Copyright (c) Charles Karney (2011-2014) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2011-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -33,23 +33,17 @@
     this._caps = (!caps ? g.ALL : (caps | g.LATITUDE | g.AZIMUTH)) |
       g.LONG_UNROLL;
 
-    azi1 = m.AngRound(m.AngNormalize(azi1));
-    this._lat1 = lat1;
+    this._lat1 = m.LatFix(lat1);
     this._lon1 = lon1;
-    this._azi1 = azi1;
-    // alp1 is in [0, pi]
-    var alp1 = azi1 * m.degree;
-    // Enforce sin(pi) == 0 and cos(pi/2) == 0.  Better to face the ensuing
-    // problems directly than to skirt them.
-    this._salp1 =          azi1  === -180 ? 0 : Math.sin(alp1);
-    this._calp1 = Math.abs(azi1) ===   90 ? 0 : Math.cos(alp1);
-    var cbet1, sbet1, phi;
-    phi = lat1 * m.degree;
-    // Ensure cbet1 = +epsilon at poles
-    sbet1 = this._f1 * Math.sin(phi);
-    cbet1 = Math.abs(lat1) === 90 ? g.tiny_ : Math.cos(phi);
+    this._azi1 = m.AngNormalize(azi1);
+    var t;
+    t = m.sincosd(m.AngRound(this._azi1)); this._salp1 = t.s; this._calp1 = t.c;
+    var cbet1, sbet1;
+    t = m.sincosd(m.AngRound(this._lat1)); sbet1 = this._f1 * t.s; cbet1 = t.c;
     // norm(sbet1, cbet1);
-    var t = m.hypot(sbet1, cbet1); sbet1 /= t; cbet1 /= t;
+    t = m.hypot(sbet1, cbet1); sbet1 /= t; cbet1 /= t;
+    // Ensure cbet1 = +epsilon at poles
+    cbet1 = Math.max(g.tiny_, cbet1);
     this._dn1 = Math.sqrt(1 + geod._ep2 * m.sq(sbet1));
 
     // Evaluate alp0 from sin(alp1) * cos(bet1) = sin(alp0),
@@ -123,6 +117,13 @@
                                                   outmask) {
     var vals = {};
     outmask &= this._caps & g.OUT_MASK;
+    vals.lat1 = this._lat1; vals.azi1 = this._azi1;
+    vals.lon1 = outmask & g.LONG_UNROLL ?
+      this._lon1 : m.AngNormalize(this._lon1);
+    if (arcmode)
+      vals.a12 = s12_a12;
+    else
+      vals.s12 = s12_a12;
     if (!( arcmode || (this._caps & g.DISTANCE_IN & g.OUT_MASK) )) {
       // Uninitialized or impossible distance calculation requested
       vals.a12 = Number.NaN;
@@ -134,10 +135,7 @@
     if (arcmode) {
       // Interpret s12_a12 as spherical arc length
       sig12 = s12_a12 * m.degree;
-      var s12a = Math.abs(s12_a12);
-      s12a -= 180 * Math.floor(s12a / 180);
-      ssig12 = s12a ===  0 ? 0 : Math.sin(sig12);
-      csig12 = s12a === 90 ? 0 : Math.cos(sig12);
+      t = m.sincosd(s12_a12); ssig12 = t.s; csig12 = t.c;
     } else {
       // Interpret s12_a12 as distance
       var
@@ -205,8 +203,8 @@
     // tan(alp0) = cos(sig2)*tan(alp2)
     salp2 = this._salp0; calp2 = this._calp0 * csig2; // No need to normalize
 
-    if (outmask & g.DISTANCE)
-      vals.s12 = arcmode ? this._b * ((1 + this._A1m1) * sig12 + AB1) : s12_a12;
+    if (arcmode && (outmask & g.DISTANCE))
+      vals.s12 = this._b * ((1 + this._A1m1) * sig12 + AB1);
 
     if (outmask & g.LONGITUDE) {
       // tan(omg2) = sin(alp0) * tan(sig2)
@@ -225,17 +223,15 @@
         ( sig12 + (g.SinCosSeries(true, ssig2, csig2, this._C3a) -
                    this._B31));
       lon12 = lam12 / m.degree;
-      // Use AngNormalize2 because longitude might have wrapped multiple times.
       vals.lon2 = outmask & g.LONG_UNROLL ? this._lon1 + lon12 :
-        m.AngNormalize(m.AngNormalize(this._lon1) + m.AngNormalize2(lon12));
+        m.AngNormalize(m.AngNormalize(this._lon1) + m.AngNormalize(lon12));
     }
 
     if (outmask & g.LATITUDE)
-      vals.lat2 = Math.atan2(sbet2, this._f1 * cbet2) / m.degree;
+      vals.lat2 = m.atan2d(sbet2, this._f1 * cbet2);
 
     if (outmask & g.AZIMUTH)
-      // minus signs give range [-180, 180). 0- converts -0 to +0.
-      vals.azi2 = 0 - Math.atan2(-salp2, calp2) / m.degree;
+      vals.azi2 = m.atan2d(salp2, calp2);
 
     if (outmask & (g.REDUCEDLENGTH | g.GEODESICSCALE)) {
       var
@@ -289,7 +285,8 @@
         this._A4 * (B42 - this._B41);
     }
 
-    vals.a12 = arcmode ? s12_a12 : sig12 / m.degree;
+    if (!arcmode)
+      vals.a12 = sig12 / m.degree;
     return vals;
   };
 
diff --git a/doc/scripts/GeographicLib/Interface.js b/doc/scripts/GeographicLib/Interface.js
index 50257cf..e671bd8 100644
--- a/doc/scripts/GeographicLib/Interface.js
+++ b/doc/scripts/GeographicLib/Interface.js
@@ -17,7 +17,7 @@
  *    https://dx.doi.org/10.1007/s00190-012-0578-z
  *    Addenda: http://geographiclib.sf.net/geod-addenda.html
  *
- * Copyright (c) Charles Karney (2011-2014) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2011-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************
@@ -51,8 +51,8 @@
  *   GeographicLib.Geodesic.REDUCEDLENGTH
  *   GeographicLib.Geodesic.GEODESICSCALE
  *   GeographicLib.Geodesic.AREA
+ *   GeographicLib.Geodesic.ALL (all of the above)
  *   GeographicLib.Geodesic.LONG_UNROLL
- *   GeographicLib.Geodesic.ALL
  *
  **********************************************************************
  * GeographicLib.Geodesic.WGS84.InversePath(lat1, lon1, lat2, lon2, ds12, maxk);
@@ -104,13 +104,11 @@
   g.Geodesic.CheckPosition = function(lat, lon) {
     if (!(Math.abs(lat) <= 90))
       throw new Error("latitude " + lat + " not in [-90, 90]");
-    if (!(lon >= -540 && lon < 540))
-      throw new Error("longitude " + lon + " not in [-540, 540)");
   };
 
   g.Geodesic.CheckAzimuth = function(azi) {
-    if (!(azi >= -540 && azi < 540))
-      throw new Error("longitude " + azi + " not in [-540, 540)");
+    if (!(isFinite(azi)))
+      throw new Error("azimuth " + azi + " not a finite number");
     return m.AngNormalize(azi);
   };
 
@@ -123,33 +121,15 @@
     if (!outmask) outmask = g.DISTANCE | g.AZIMUTH;
     g.Geodesic.CheckPosition(lat1, lon1);
     g.Geodesic.CheckPosition(lat2, lon2);
-
-    var result = this.GenInverse(lat1, lon1, lat2, lon2, outmask);
-    lon2 = m.AngNormalize(lon2);
-    if (outmask & g.LONG_UNROLL) {
-      result.lon1 = lon1;
-      result.lon2 = lon1 + m.AngDiff(m.AngNormalize(lon1), lon2);
-    } else {
-      result.lon1 = m.AngNormalize(lon1);
-      result.lon2 = lon2;
-    }
-    result.lat1 = lat1;
-    result.lat2 = lat2;
-
-    return result;
+    return this.GenInverse(lat1, lon1, lat2, lon2, outmask);
   };
 
   g.Geodesic.prototype.Direct = function(lat1, lon1, azi1, s12, outmask) {
     if (!outmask) outmask = g.LATITUDE | g.LONGITUDE | g.AZIMUTH;
     g.Geodesic.CheckPosition(lat1, lon1);
-    azi1 = g.Geodesic.CheckAzimuth(azi1);
+    g.Geodesic.CheckAzimuth(azi1);
     g.Geodesic.CheckDistance(s12);
-
-    var result = this.GenDirect(lat1, lon1, azi1, false, s12, outmask);
-    result.lon1 = (outmask & g.LONG_UNROLL) ? lon1 : m.AngNormalize(lon1)
-    result.lat1 = lat1; result.azi1 = azi1; result.s12 = s12;
-
-    return result;
+    return this.GenDirect(lat1, lon1, azi1, false, s12, outmask);
   };
 
   g.Geodesic.prototype.InversePath =
@@ -205,10 +185,6 @@
   g.Geodesic.prototype.Circle = function(lat1, lon1, azi1, s12, k) {
     if (!(Math.abs(lat1) <= 90))
       throw new Error("lat1 must be in [-90, 90]");
-    if (!(lon1 >= -540 && lon1 < 540))
-      throw new Error("lon1 must be in [-540, 540)");
-    if (!(azi1 >= -540 && azi1 < 540))
-      throw new Error("azi1 must be in [-540, 540)");
     if (!(isFinite(s12)))
       throw new Error("s12 must be a finite number");
     lon1 = m.AngNormalize(lon1);
@@ -229,8 +205,6 @@
   g.Geodesic.prototype.Envelope = function(lat1, lon1, k, ord) {
     if (!(Math.abs(lat1) <= 90))
       throw new Error("lat1 must be in [-90, 90]");
-    if (!(lon1 >= -540 && lon1 < 540))
-      throw new Error("lon1 must be in [-540, 540)");
     lon1 = m.AngNormalize(lon1);
     if (!k || k < 4) k = 24;
     if (!ord) ord = 1;
diff --git a/doc/scripts/GeographicLib/Math.js b/doc/scripts/GeographicLib/Math.js
index 6c4f773..7db9ee4 100644
--- a/doc/scripts/GeographicLib/Math.js
+++ b/doc/scripts/GeographicLib/Math.js
@@ -3,7 +3,7 @@
  * Transcription of Math.hpp, Constants.hpp, and Accumulator.hpp into
  * JavaScript.
  *
- * Copyright (c) Charles Karney (2011-2014) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2011-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -76,32 +76,69 @@ GeographicLib.Math.AngRound = function(x) {
 };
 
 GeographicLib.Math.AngNormalize = function(x) {
-  // Place angle in [-180, 180).  Assumes x is in [-540, 540).
-  return x >= 180 ? x - 360 : (x < -180 ? x + 360 : x);
+  // Place angle in [-180, 180).
+  x = x % 360.0;
+  return x < -180 ? x + 360 : (x < 180 ? x : x - 360);
 };
 
-GeographicLib.Math.AngNormalize2 = function(x) {
-  // Place arbitrary angle in [-180, 180).
-  return GeographicLib.Math.AngNormalize(x % 360.0);
+GeographicLib.Math.LatFix = function(x) {
+  // Place angle with NaN if outside [-90, 90].
+  return Math.abs(x) > 90 ? Number.NaN : x;
 };
 
 GeographicLib.Math.AngDiff = function(x, y) {
   // Compute y - x and reduce to [-180,180] accurately.
-  // This is the same logic as the Accumulator class uses.
   var
-  d = y - x,
-  yp = d + x,
-  xpp = yp - d;
-  yp -= y;
-  xpp -= x;
-  var t =  xpp - yp;
-  // y - x =       d      + t
-  //       = round(y - x) + t
-  if ((d - 180) + t > 0)        // y - x > 180
-    d -= 360;                   // exact
-  else if ((d + 180) + t <= 0)  // y - x <= -180
-    d += 360;                   // exact
-  return d + t;
+  r = GeographicLib.Math.sum(GeographicLib.Math.AngNormalize(x),
+                             GeographicLib.Math.AngNormalize(-y)),
+  d = - GeographicLib.Math.AngNormalize(r.s);
+  t = r.t;
+  return (d == 180 && t < 0 ? -180 : d) - t;
+};
+
+GeographicLib.Math.sincosd = function(x) {
+  // In order to minimize round-off errors, this function exactly reduces
+  // the argument to the range [-45, 45] before converting it to radians.
+  var r, q;
+  r = x % 360.0;
+  q = Math.floor(r / 90 + 0.5);
+  r -= 90 * q;
+  // now abs(r) <= 45
+  r *= this.degree;
+  // Possibly could call the gnu extension sincos
+  var s = Math.sin(r), c = Math.cos(r);
+  var sinx, cosx;
+  switch (q & 3) {
+  case  0: sinx =     s; cosx =     c; break;
+  case  1: sinx =     c; cosx = 0 - s; break;
+  case  2: sinx = 0 - s; cosx = 0 - c; break;
+  default: sinx = 0 - c; cosx =     s; break; // case 3
+  }
+  return {s: sinx, c: cosx};
+};
+
+GeographicLib.Math.atan2d = function(y, x) {
+  // In order to minimize round-off errors, this function rearranges the
+  // arguments so that result of atan2 is in the range [-pi/4, pi/4] before
+  // converting it to degrees and mapping the result to the correct
+  // quadrant.
+  var q = 0;
+  if (Math.abs(y) > Math.abs(x)) { var t; t = x; x = y; y = t; q = 2; }
+  if (x < 0) { x = -x; ++q; }
+  // here x >= 0 and x >= abs(y), so angle is in [-pi/4, pi/4]
+  var ang = Math.atan2(y, x) / this.degree;
+  switch (q) {
+    // Note that atan2d(-0.0, 1.0) will return -0.  However, we expect that
+    // atan2d will not be called with y = -0.  If need be, include
+    //
+    //   case 0: ang = 0 + ang; break;
+    //
+    // and handle mpfr as in AngRound.
+  case 1: ang = (y > 0 ? 180 : -180) - ang; break;
+  case 2: ang =  90 - ang; break;
+  case 3: ang = -90 + ang; break;
+  }
+  return ang;
 };
 
 GeographicLib.Math.epsilon = Math.pow(0.5, 52);
@@ -110,6 +147,8 @@ GeographicLib.Math.digits = 53;
 
 GeographicLib.Constants = {};
 GeographicLib.Constants.WGS84 = { a: 6378137, f: 1/298.257223563 };
+GeographicLib.Constants.version = { major: 1, minor: 44, patch: 0 };
+GeographicLib.Constants.version_string = "1.44";
 
 GeographicLib.Accumulator = {};
 (function() {
diff --git a/doc/scripts/geod-calc.html b/doc/scripts/geod-calc.html
index 40e3710..e9be50f 100644
--- a/doc/scripts/geod-calc.html
+++ b/doc/scripts/geod-calc.html
@@ -1,4 +1,4 @@
-<!DOCTYPE html>
+<!DOCTYPE html>
 <html>
   <head>
     <title>Geodesic calculations for an ellipsoid done right</title>
@@ -22,11 +22,12 @@
 		   online calculator,
 		   WGS84 ellipsoid,
 		   GeographicLib" />
+    <meta http-equiv="Content-Type"
+	  content="text/html; charset=ISO-8859-1">
     <script type="text/javascript"
 	    src="http://geographiclib.sf.net/scripts/geographiclib.js">
     </script>
     <script type="text/javascript">
-<!--
 var geod = GeographicLib.Geodesic.WGS84;
 var dms = GeographicLib.DMS;
 function formatpoint(lat, lon, azi, dmsformat, prec) {
@@ -41,7 +42,7 @@ function formatpoint(lat, lon, azi, dmsformat, prec) {
   } else {
     return (lat.toFixed(prec) + " " +
 	    lon.toFixed(prec) + " " +
-	    azi .toFixed(prec));
+	    azi.toFixed(prec));
   }
 }
 
@@ -55,17 +56,27 @@ function GeodesicInverse(input, dmsformat, prec) {
       throw new Error("Need 4 input items");
     var p1 = GeographicLib.DMS.DecodeLatLon(t[0], t[1]);
     var p2 = GeographicLib.DMS.DecodeLatLon(t[2], t[3]);
-    t = geod.Inverse(p1.lat, p1.lon, p2.lat, p2.lon);
+    t = geod.Inverse(p1.lat, p1.lon, p2.lat, p2.lon,
+		     GeographicLib.Geodesic.ALL |
+		     GeographicLib.Geodesic.LONG_UNROLL);
     result.status = "OK";
     result.p1 = formatpoint(t.lat1, t.lon1, t.azi1, dmsformat, prec);
     result.p2 = formatpoint(t.lat2, t.lon2, t.azi2, dmsformat, prec);
     result.s12 = t.s12.toFixed(prec);
+    result.a12 = t.a12.toFixed(prec + 5);
+    result.m12 = t.m12.toFixed(prec);
+    result.M1221 = t.M12.toFixed(prec + 7) + " " + t.M21.toFixed(prec + 6);
+    result.S12 = t.S12.toFixed(Math.max(prec - 7, 0));
   }
   catch (e) {
     result.status = "ERROR: " + e.message;
     result.p1 = "";
     result.p2 = "";
     result.s12 = "";
+    result.a12 = "";
+    result.m12 = "";
+    result.M1221 = "";
+    result.S12 = "";
   }
   return result;
 }
@@ -81,17 +92,27 @@ function GeodesicDirect(input, dmsformat, prec) {
     var p1 = GeographicLib.DMS.DecodeLatLon(t[0], t[1]);
     var azi1 = GeographicLib.DMS.DecodeAzimuth(t[2]);
     var s12 = parseFloat(t[3]);
-    t = geod.Direct(p1.lat, p1.lon, azi1, s12);
+    t = geod.Direct(p1.lat, p1.lon, azi1, s12,
+		    GeographicLib.Geodesic.ALL |
+		    GeographicLib.Geodesic.LONG_UNROLL);
     result.status = "OK";
     result.p1 = formatpoint(t.lat1, t.lon1, t.azi1, dmsformat, prec);
     result.p2 = formatpoint(t.lat2, t.lon2, t.azi2, dmsformat, prec);
     result.s12 = t.s12.toFixed(prec);
+    result.a12 = t.a12.toFixed(prec + 5);
+    result.m12 = t.m12.toFixed(prec);
+    result.M1221 = t.M12.toFixed(prec + 7) + " " + t.M21.toFixed(prec + 6);
+    result.S12 = t.S12.toFixed(Math.max(prec - 7, 0));
   }
   catch (e) {
     result.status = "ERROR: " + e.message;
     result.p1 = "";
     result.p2 = "";
     result.s12 = "";
+    result.a12 = "";
+    result.m12 = "";
+    result.M1221 = "";
+    result.S12 = "";
   }
   return result;
 }
@@ -153,7 +174,6 @@ function GeodesicArea(input, polyline) {
   }
   return result;
 }
-//-->
     </script>
   </head>
   <body>
@@ -162,7 +182,7 @@ function GeodesicArea(input, polyline) {
     </div>
     <p>
       This page illustrates the geodesic routines available in
-      <a href="http://geographiclib.sourceforge.net">GeographicLib</a>.
+      <a href="http://geographiclib.sf.net">GeographicLib</a>.
       The C++ code has been converted to JavaScript so the calculations
       are carried out on the client.  The algorithms are considerably
       more accurate than Vincenty's method, and offer more functionality
@@ -189,7 +209,16 @@ function GeodesicArea(input, polyline) {
       -20:30:40.5.)  The results are accurate to about
       15 nanometers (or 0.1 m<sup>2</sup> per vertex for
       areas).  A slicker page where the geodesics are incorporated into
-      Google Maps is given <a href="geod-google.html">here</a>.
+      Google Maps is given <a href="geod-google.html">here</a>.  Basic
+      online tools which provide similar capabilities are
+      <a href="http://geographiclib.sf.net/cgi-bin/GeodSolve">GeodSolve</a>
+      and
+      <a href="http://geographiclib.sf.net/cgi-bin/Planimeter">Planimeter</a>;
+      these call a C++ backend.  This page uses version
+      <script type="text/javascript">
+	document.write(GeographicLib.Constants.version_string);
+      </script>
+      of the geodesic code.
     <p>
       Jump to:
       <ul>
@@ -207,14 +236,14 @@ function GeodesicArea(input, polyline) {
       <p>
 	Find the shortest path between two points on the earth.  The
 	path is characterized by its length <i>s12</i> and its azimuth
-	at the two ends <i>azi1</i> and <i>azi2</i>.  The sample
-	calculation finds the shortest path between Wellington, New
-	Zealand, and Salamanca, Spain.  (For this example, the
-	<a href="http://www.ngs.noaa.gov/">NGS</a>
-	<a href="http://www.ngs.noaa.gov/cgi-bin/Inv_Fwd/inverse2.prl">
-        inverse geodesic calculator</a> returns a result which is 1.2 km
-	too long with an azimuth which is off by 3 degrees.)  To perform
-	the calculation, press the “COMPUTE” button.
+	at the two ends <i>azi1</i> and <i>azi2</i>.  See
+	<a href="http://geographiclib.sf.net/html/GeodSolve.1.html">
+	  GeodSolve(1)</a>
+	for the definition of the
+	quantities <i>a12</i>, <i>m12</i>, <i>M12</i>, <i>M21</i>,
+	and <i>S12</i>.  The sample calculation finds the shortest path
+	between Wellington, New Zealand, and Salamanca, Spain.  To
+	perform the calculation, press the “COMPUTE” button.
       </p>
       <p>Enter <i>“lat1 lon1 lat2 lon2”</i>:</p>
       <p>input:
@@ -250,7 +279,11 @@ function GeodesicArea(input, polyline) {
 			document.inverse.status.value = t.status;
 			document.inverse.p1.value = t.p1;
 			document.inverse.p2.value = t.p2;
-			document.inverse.s12.value = t.s12;" />
+			document.inverse.s12.value = t.s12;
+			document.inverse.a12.value = t.a12;
+			document.inverse.m12.value = t.m12;
+			document.inverse.M1221.value = t.M1221;
+			document.inverse.S12.value = t.S12;" />
       </p>
       <p>
 	status:
@@ -268,6 +301,22 @@ function GeodesicArea(input, polyline) {
 	<font color='blue'>s12</font>:
         <input name="s12" size=25 readonly />
       </p>
+      <p>
+	<font color='blue'>a12</font>:
+        <input name="a12" size=25 readonly />
+      </p>
+      <p>
+	<font color='blue'>m12</font>:
+        <input name="m12" size=25 readonly />
+      </p>
+      <p>
+	<font color='blue'>M12 M21</font>:
+        <input name="M1221" size=50 readonly />
+      </p>
+      <p>
+	<font color='blue'>S12</font>:
+        <input name="S12" size=25 readonly />
+      </p>
     </form>
     <hr>
     <form name="direct">
@@ -276,9 +325,14 @@ function GeodesicArea(input, polyline) {
 	Find the destination traveling a given distance along a geodesic
 	with a given azimuth at the starting point.  The destination is
 	characterized by its position <i>lat2, lon2</i> and its azimuth
-	at the destination <i>azi2</i>.  The sample calculation shows
-	the result of travelling 10000 km NE from JFK airport.  To perform
-	the calculation, press the “COMPUTE” button.
+	at the destination <i>azi2</i>.  See
+	<a href="http://geographiclib.sf.net/html/GeodSolve.1.html">
+	  GeodSolve(1)</a>
+	for the definition of the
+	quantities <i>a12</i>, <i>m12</i>, <i>M12</i>, <i>M21</i>,
+	and <i>S12</i>.  The sample calculation shows the result of
+	travelling 10000 km NE from JFK airport.  To perform the
+	calculation, press the “COMPUTE” button.
       </p>
       <p>Enter <i>“lat1 lon1 azi1 s12”</i>:</p>
       <p>input:
@@ -314,7 +368,11 @@ function GeodesicArea(input, polyline) {
 			document.direct.status.value = t.status;
 			document.direct.p1.value = t.p1;
 			document.direct.p2.value = t.p2;
-			document.direct.s12.value = t.s12;" />
+			document.direct.s12.value = t.s12;
+			document.direct.a12.value = t.a12;
+			document.direct.m12.value = t.m12;
+			document.direct.M1221.value = t.M1221;
+			document.direct.S12.value = t.S12;" />
       </p>
       <p>
 	status:
@@ -332,6 +390,22 @@ function GeodesicArea(input, polyline) {
 	s12:
         <input name="s12" size=25 readonly />
       </p>
+      <p>
+	<font color='blue'>a12</font>:
+        <input name="a12" size=25 readonly />
+      </p>
+      <p>
+	<font color='blue'>m12</font>:
+        <input name="m12" size=25 readonly />
+      </p>
+      <p>
+	<font color='blue'>M12 M21</font>:
+        <input name="M1221" size=50 readonly />
+      </p>
+      <p>
+	<font color='blue'>S12</font>:
+        <input name="S12" size=25 readonly />
+      </p>
     </form>
     <hr>
     <form name="path">
@@ -460,8 +534,8 @@ function GeodesicArea(input, polyline) {
     <hr>
     <address>Charles Karney
       <a href="mailto:charles at karney.com"><charles at karney.com></a>
-      (2011-08-04)</address>
+      (2015-08-12)</address>
     <br>
-    <a href="http://geographiclib.sourceforge.net">Geographiclib Sourceforge</a>
+    <a href="http://geographiclib.sf.net">Geographiclib Sourceforge</a>
   </body>
 </html>
diff --git a/doc/scripts/geod-google-instructions.html b/doc/scripts/geod-google-instructions.html
index d967982..9046bb5 100644
--- a/doc/scripts/geod-google-instructions.html
+++ b/doc/scripts/geod-google-instructions.html
@@ -25,6 +25,8 @@
 		   Google Maps,
 		   WGS84 ellipsoid,
 		   GeographicLib" />
+    <meta http-equiv="Content-Type"
+	  content="text/html; charset=ISO-8859-1">
   </head>
   <body>
     <h2>
@@ -81,11 +83,17 @@
       intermediate points on a geodesic, and finds the area of a
       geodesic polygon; it allows you to specify the precision of the
       output and choose between decimal degrees and degress, minutes,
-      and seconds.
+      and seconds.  Basic online tools which provide similar capabilities
+      are
+      <a href="http://geographiclib.sf.net/cgi-bin/GeodSolve">GeodSolve</a>
+      and
+      <a href="http://geographiclib.sf.net/cgi-bin/Planimeter">Planimeter</a>;
+      these call a C++ backend.
+    </p>
     <p>
       The Javascipt code for computing the geodesic lines, circles, and
       envelopes is part of
-      <a href="http://geographiclib.sourceforge.net/">GeographicLib</a>.
+      <a href="http://geographiclib.sf.net/">GeographicLib</a>.
       The algorithms are derived in
       <blockquote>
 	Charles F. F. Karney,<br>
@@ -109,6 +117,6 @@
       <a href="mailto:charles at karney.com"><charles at karney.com></a>
       (2011-08-02)</address>
     <br>
-    <a href="http://geographiclib.sourceforge.net">Geographiclib Sourceforge</a>
+    <a href="http://geographiclib.sf.net">Geographiclib Sourceforge</a>
   </body>
 </html>
diff --git a/doc/scripts/geod-google.html b/doc/scripts/geod-google.html
index 5a48d7e..d6d4b67 100644
--- a/doc/scripts/geod-google.html
+++ b/doc/scripts/geod-google.html
@@ -24,6 +24,8 @@
 		   Google Maps,
 		   WGS84 ellipsoid,
 		   GeographicLib" />
+    <meta http-equiv="Content-Type"
+	  content="text/html; charset=ISO-8859-1">
     <style>
       html, body, #map-canvas {
         height: 100%;
@@ -219,8 +221,11 @@ function clearPaths() {
 	 s12: <input type="text" "readonly" id="s12" size=20>
 	   status: <input "readonly" id="status" size=30>
 	  
-	<a href="geod-google-instructions.html"><b>INSTRUCTIONS HERE</b></a>
-    </p>
+	<a href="geod-google-instructions.html"><b>INSTRUCTIONS</b></a>
+	(v<script type="text/javascript">
+	  document.write(GeographicLib.Constants.version_string);
+	</script>)
+      </p>
   </div>
   </body>
 </html>
diff --git a/doc/tmseries30.html b/doc/tmseries30.html
index 0ce8832..505020e 100644
--- a/doc/tmseries30.html
+++ b/doc/tmseries30.html
@@ -3,6 +3,8 @@
     <title>
       Krueger's series for the transverse Mercator projection
     </title>
+    <meta http-equiv="Content-Type"
+	  content="text/html; charset=ISO-8859-1">
   <body>
     <h2>
       Krueger's series for the transverse Mercator projection
diff --git a/dotnet/NETGeographicLib/AlbersEqualArea.h b/dotnet/NETGeographicLib/AlbersEqualArea.h
index c110517..15bb419 100644
--- a/dotnet/NETGeographicLib/AlbersEqualArea.h
+++ b/dotnet/NETGeographicLib/AlbersEqualArea.h
@@ -180,12 +180,11 @@ namespace NETGeographicLib
          * @param[out] k azimuthal scale of projection at point; the radial
          *   scale is the 1/\e k.
          *
-         * The latitude origin is given by AlbersEqualArea::LatitudeOrigin().  No
-         * false easting or northing is added and \e lat should be in the range
-         * [−90°, 90°]; \e lon and \e lon0 should be in the
-         * range [−540°, 540°).  The values of \e x and \e y
-         * returned for points which project to infinity (i.e., one or both of the
-         * poles) will be large but finite.
+         * The latitude origin is given by AlbersEqualArea::LatitudeOrigin().
+         * No false easting or northing is added and \e lat should be in the
+         * range [−90°, 90°].  The values of \e x and \e y
+         * returned for points which project to infinity (i.e., one or both of
+         * the poles) will be large but finite.
          **********************************************************************/
         void Forward(double lon0, double lat, double lon,
                      [System::Runtime::InteropServices::Out] double% x,
@@ -205,12 +204,11 @@ namespace NETGeographicLib
          * @param[out] k azimuthal scale of projection at point; the radial
          *   scale is the 1/\e k.
          *
-         * The latitude origin is given by AlbersEqualArea::LatitudeOrigin().  No
-         * false easting or northing is added.  \e lon0 should be in the range
-         * [−540°, 540°).  The value of \e lon returned is in
-         * the range [−180°, 180°).  The value of \e lat
-         * returned is in the range [−90°, 90°].  If the
-         * input point is outside the legal projected space the nearest pole is
+         * The latitude origin is given by AlbersEqualArea::LatitudeOrigin().
+         * No false easting or northing is added.  The value of \e lon returned
+         * is in the range [−180°, 180°).  The value of \e lat
+         * returned is in the range [−90°, 90°].  If the input
+         * point is outside the legal projected space the nearest pole is
          * returned.
          **********************************************************************/
         void Reverse(double lon0, double x, double y,
diff --git a/dotnet/NETGeographicLib/AzimuthalEquidistant.h b/dotnet/NETGeographicLib/AzimuthalEquidistant.h
index ab0643f..7fa27a5 100644
--- a/dotnet/NETGeographicLib/AzimuthalEquidistant.h
+++ b/dotnet/NETGeographicLib/AzimuthalEquidistant.h
@@ -86,13 +86,12 @@ namespace NETGeographicLib
          * @param[out] azi azimuth of geodesic at point (degrees).
          * @param[out] rk reciprocal of azimuthal scale at point.
          *
-         * \e lat0 and \e lat should be in the range [−90°,
-         * 90°] and \e lon0 and \e lon should be in the range
-         * [−540°, 540°).  The scale of the projection is 1
-         * in the "radial" direction, \e azi clockwise from true north, and is 1/\e
-         * rk in the direction perpendicular to this.  A call to Forward followed
-         * by a call to Reverse will return the original (\e lat, \e lon) (to
-         * within roundoff).
+         * \e lat0 and \e lat should be in the range [−90°, 90°].
+         * The scale of the projection is 1 in the "radial" direction, \e azi
+         * clockwise from true north, and is 1/\e rk in the direction
+         * perpendicular to this.  A call to Forward followed by a call to
+         * Reverse will return the original (\e lat, \e lon) (to within
+         * roundoff).
          **********************************************************************/
         void Forward(double lat0, double lon0, double lat, double lon,
                      [System::Runtime::InteropServices::Out] double% x,
@@ -112,15 +111,14 @@ namespace NETGeographicLib
          * @param[out] azi azimuth of geodesic at point (degrees).
          * @param[out] rk reciprocal of azimuthal scale at point.
          *
-         * \e lat0 should be in the range [−90°, 90°] and \e
-         * lon0 should be in the range [−540°, 540°).  \e lat
-         * will be in the range [−90°, 90°] and \e lon will
-         * be in the range [−180°, 180°).  The scale of the
-         * projection is 1 in the "radial" direction, \e azi clockwise from true
-         * north, and is 1/\e rk in the direction perpendicular to this.  A call to
-         * Reverse followed by a call to Forward will return the original (\e x, \e
-         * y) (to roundoff) only if the geodesic to (\e x, \e y) is a shortest
-         * path.
+         * \e lat0 should be in the range [−90°, 90°].  \e lat
+         * will be in the range [−90°, 90°] and \e lon will be in
+         * the range [−180°, 180°).  The scale of the projection
+         * is 1 in the "radial" direction, \e azi clockwise from true north,
+         * and is 1/\e rk in the direction perpendicular to this.  A call to
+         * Reverse followed by a call to Forward will return the original (\e
+         * x, \e y) (to roundoff) only if the geodesic to (\e x, \e y) is a
+         * shortest path.
          **********************************************************************/
         void Reverse(double lat0, double lon0, double x, double y,
                      [System::Runtime::InteropServices::Out] double% lat,
diff --git a/dotnet/NETGeographicLib/CassiniSoldner.h b/dotnet/NETGeographicLib/CassiniSoldner.h
index 7150da0..3e494dc 100644
--- a/dotnet/NETGeographicLib/CassiniSoldner.h
+++ b/dotnet/NETGeographicLib/CassiniSoldner.h
@@ -93,8 +93,7 @@ namespace NETGeographicLib
          * @param[in] earth the Geodesic object to use for geodesic calculations.
          *   By default this uses the WGS84 ellipsoid.
          *
-         * \e lat0 should be in the range [−90°, 90°] and \e
-         * lon0 should be in the range [−540°, 540°).
+         * \e lat0 should be in the range [−90°, 90°].
          **********************************************************************/
         CassiniSoldner(double lat0, double lon0, Geodesic^ earth );
 
@@ -110,8 +109,7 @@ namespace NETGeographicLib
          * @param[in] lat0 latitude of center point of projection (degrees).
          * @param[in] lon0 longitude of center point of projection (degrees).
          *
-         * \e lat0 should be in the range [−90°, 90°] and \e
-         * lon0 should be in the range [−540°, 540°).
+         * \e lat0 should be in the range [−90°, 90°].
          **********************************************************************/
         void Reset(double lat0, double lon0);
 
@@ -125,9 +123,8 @@ namespace NETGeographicLib
          * @param[out] azi azimuth of easting direction at point (degrees).
          * @param[out] rk reciprocal of azimuthal northing scale at point.
          *
-         * \e lat should be in the range [−90°, 90°] and \e
-         * lon should be in the range [−540°, 540°).  A call
-         * to Forward followed by a call to Reverse will return the original (\e
+         * \e lat should be in the range [−90°, 90°].  A call to
+         * Forward followed by a call to Reverse will return the original (\e
          * lat, \e lon) (to within roundoff).  The routine does nothing if the
          * origin has not been set.
          **********************************************************************/
diff --git a/dotnet/NETGeographicLib/DMS.cpp b/dotnet/NETGeographicLib/DMS.cpp
index 38bed3b..ef1a9da 100644
--- a/dotnet/NETGeographicLib/DMS.cpp
+++ b/dotnet/NETGeographicLib/DMS.cpp
@@ -36,13 +36,13 @@ double DMS::Decode( System::String^ dms,
 void DMS::DecodeLatLon(System::String^ dmsa, System::String^ dmsb,
                         [System::Runtime::InteropServices::Out] double% lat,
                         [System::Runtime::InteropServices::Out] double% lon,
-                        bool swaplatlong )
+                        bool longfirst )
 {
     try
     {
         double llat, llon;
         GeographicLib::DMS::DecodeLatLon( StringConvert::ManagedToUnmanaged( dmsa ),
-            StringConvert::ManagedToUnmanaged( dmsb ), llat, llon, swaplatlong );
+            StringConvert::ManagedToUnmanaged( dmsb ), llat, llon, longfirst );
         lat = llat;
         lon = llon;
     }
diff --git a/dotnet/NETGeographicLib/DMS.h b/dotnet/NETGeographicLib/DMS.h
index 878e712..8f778eb 100644
--- a/dotnet/NETGeographicLib/DMS.h
+++ b/dotnet/NETGeographicLib/DMS.h
@@ -105,23 +105,47 @@ public:
      * (colon) may be used to <i>separate</i> these components (numbers must
      * appear before and after each colon); thus 50d30'10.3" may be
      * written as 50:30:10.3, 5.5' may be written 0:5.5, and so on.  The
-     * integer parts of the minutes and seconds components must be less than
-     * 60.  A single leading sign is permitted.  A hemisphere designator (N, E,
-     * W, S) may be added to the beginning or end of the string.  The result is
-     * multiplied by the implied sign of the hemisphere designator (negative
-     * for S and W).  In addition \e ind is set to DMS::LATITUDE if N or S is
-     * present, to DMS::LONGITUDE if E or W is present, and to DMS::NONE
-     * otherwise.  Throws an error on a malformed string.  No check is
-     * performed on the range of the result.  Examples of legal and illegal
+     * integer parts of the minutes and seconds components must be less
+     * than 60.  A single leading sign is permitted.  A hemisphere designator
+     * (N, E, W, S) may be added to the beginning or end of the string.  The
+     * result is multiplied by the implied sign of the hemisphere designator
+     * (negative for S and W).  In addition \e ind is set to DMS::LATITUDE if N
+     * or S is present, to DMS::LONGITUDE if E or W is present, and to
+     * DMS::NONE otherwise.  Throws an error on a malformed string.  No check
+     * is performed on the range of the result.  Examples of legal and illegal
      * strings are
      * - <i>LEGAL</i> (all the entries on each line are equivalent)
      *   - -20.51125, 20d30'40.5"S, -20°30'40.5, -20d30.675,
      *     N-20d30'40.5", -20:30:40.5
      *   - 4d0'9, 4d9", 4d9'', 4:0:9, 004:00:09, 4.0025, 4.0025d, 4d0.15,
      *     04:.15
+     *   - 4:59.99999999999999, 4:60.0, 4:59:59.9999999999999, 4:59:60.0, 5
      * - <i>ILLEGAL</i> (the exception thrown explains the problem)
      *   - 4d5"4', 4::5, 4:5:, :4:5, 4d4.5'4", -N20.5, 1.8e2d, 4:60,
-     *     4d-5'
+     *     4:59:60
+     *
+     * The decoding operation can also perform addition and subtraction
+     * operations.  If the string includes <i>internal</i> signs (i.e., not at
+     * the beginning nor immediately after an initial hemisphere designator),
+     * then the string is split immediately before such signs and each piece is
+     * decoded according to the above rules and the results added; thus
+     * <code>S3-2.5+4.1N</code> is parsed as the sum of <code>S3</code>,
+     * <code>-2.5</code>, <code>+4.1N</code>.  Any piece can include a
+     * hemisphere designator; however, if multiple designators are given, they
+     * must compatible; e.g., you cannot mix N and E.  In addition, the
+     * designator can appear at the beginning or end of the first piece, but
+     * must be at the end of all subsequent pieces (a hemisphere designator is
+     * not allowed after the initial sign).  Examples of legal and illegal
+     * combinations are
+     * - <i>LEGAL</i> (these are all equivalent)
+     *   - 070:00:45, 70:01:15W+0:0.5, 70:01:15W-0:0:30W, W70:01:15+0:0:30E
+     * - <i>ILLEGAL</i> (the exception thrown explains the problem)
+     *   - 70:01:15W+0:0:15N, W70:01:15+W0:0:15
+     *
+     * <b>WARNING:</b> "Exponential" notation is not recognized.  Thus
+     * <code>7.0E1</code> is illegal, while <code>7.0E+1</code> is parsed as
+     * <code>(7.0E) + (+1)</code>, yielding the same result as
+     * <code>8.0E</code>.
      *
      * <b>NOTE:</b> At present, all the string handling in the C++
      * implementation %GeographicLib is with 8-bit characters.  The support for
@@ -177,7 +201,7 @@ public:
      * @param[in] dmsb second string.
      * @param[out] lat latitude (degrees).
      * @param[out] lon longitude (degrees).
-     * @param[in] swaplatlong if true assume longitude is given before latitude
+     * @param[in] longfirst if true assume longitude is given before latitude
      *   in the absence of hemisphere designators (default false).
      * @exception GeographicErr if \e dmsa or \e dmsb is malformed.
      * @exception GeographicErr if \e dmsa and \e dmsb are both interpreted as
@@ -186,8 +210,6 @@ public:
      *   longitudes.
      * @exception GeographicErr if decoded latitude is not in [−90°,
      *   90°].
-     * @exception GeographicErr if decoded longitude is not in
-     *   [−540°, 540°).
      *
      * By default, the \e lat (resp., \e lon) is assigned to the results of
      * decoding \e dmsa (resp., \e dmsb).  However this is overridden if either
@@ -198,7 +220,7 @@ public:
     static void DecodeLatLon(System::String^ dmsa, System::String^ dmsb,
                      [System::Runtime::InteropServices::Out] double% lat,
                      [System::Runtime::InteropServices::Out] double% lon,
-                     bool swaplatlong );
+                     bool longfirst );
 
     /**
      * Convert a string to an angle in degrees.
@@ -219,8 +241,6 @@ public:
      * @param[in] azistr input string.
      * @exception GeographicErr if \e azistr is malformed.
      * @exception GeographicErr if \e azistr includes a N/S designator.
-     * @exception GeographicErr if decoded azimuth is not in
-     *   [−540°, 540°).
      * @return azimuth (degrees) reduced to the range [−180°,
      *   180°).
      *
diff --git a/dotnet/NETGeographicLib/Ellipsoid.h b/dotnet/NETGeographicLib/Ellipsoid.h
index 29048ca..cae9107 100644
--- a/dotnet/NETGeographicLib/Ellipsoid.h
+++ b/dotnet/NETGeographicLib/Ellipsoid.h
@@ -402,9 +402,8 @@ namespace NETGeographicLib
          *   section at latitude φ inclined at an angle \e azi to the
          *   meridian (meters).
          *
-         * φ must lie in the range [−90°, 90°] and \e
-         * azi must lie in the range [−540°, 540°); the
-         * result is undefined if either of conditions does not hold.
+         * φ must lie in the range [−90°, 90°]; the
+         * result is undefined if this condition does not hold.
          **********************************************************************/
         double NormalCurvatureRadius(double phi, double azi);
         ///@}
diff --git a/dotnet/NETGeographicLib/GARS.cpp b/dotnet/NETGeographicLib/GARS.cpp
new file mode 100644
index 0000000..867944a
--- /dev/null
+++ b/dotnet/NETGeographicLib/GARS.cpp
@@ -0,0 +1,57 @@
+/**
+ * \file NETGeographicLib/GARS.cpp
+ * \brief Source for NETGeographicLib::GARS class
+ *
+ * NETGeographicLib is copyright (c) Scott Heiman (2013-2015)
+ * GeographicLib is Copyright (c) Charles Karney (2010-2012)
+ * <charles at karney.com> and licensed under the MIT/X11 License.
+ * For more information, see
+ * http://geographiclib.sourceforge.net/
+ **********************************************************************/
+#include "stdafx.h"
+#include "GeographicLib/GARS.hpp"
+#include "GARS.h"
+#include "NETGeographicLib.h"
+
+using namespace NETGeographicLib;
+
+//*****************************************************************************
+void GARS::Forward(double lat, double lon, int prec, System::String^% gars)
+{
+    try
+    {
+        std::string l;
+        GeographicLib::GARS::Forward( lat, lon, prec, l );
+        gars = gcnew System::String( l.c_str() );
+    }
+    catch ( const std::exception& xcpt )
+    {
+        throw gcnew GeographicErr( xcpt.what() );
+    }
+}
+
+//*****************************************************************************
+void GARS::Reverse( System::String^ gars,  double% lat,  double% lon,
+        int% prec, bool centerp)
+{
+    try
+    {
+        double llat, llon;
+        int lprec;
+        GeographicLib::GARS::Reverse( StringConvert::ManagedToUnmanaged( gars ),
+            llat, llon, lprec, centerp );
+        lat = llat;
+        lon = llon;
+        prec = lprec;
+    }
+    catch ( const std::exception& err )
+    {
+        throw gcnew GeographicErr( err.what() );
+    }
+}
+
+//*****************************************************************************
+double GARS::Resolution(int prec) { return GeographicLib::GARS::Resolution(prec); }
+
+//*****************************************************************************
+int GARS::Precision(double res) { return GeographicLib::GARS::Precision(res); }
diff --git a/dotnet/NETGeographicLib/GARS.h b/dotnet/NETGeographicLib/GARS.h
new file mode 100644
index 0000000..0e7c358
--- /dev/null
+++ b/dotnet/NETGeographicLib/GARS.h
@@ -0,0 +1,109 @@
+/**
+ * \file NETGeographicLib/GARS.h
+ * \brief Header for NETGeographicLib::GARS class
+ *
+ * NETGeographicLib is copyright (c) Scott Heiman (2013-2015)
+ * GeographicLib is Copyright (c) Charles Karney (2010-2012)
+ * <charles at karney.com> and licensed under the MIT/X11 License.
+ * For more information, see
+ * http://geographiclib.sourceforge.net/
+ **********************************************************************/
+#pragma once
+
+namespace NETGeographicLib
+{
+  /**
+   * \brief .NET Wrapper for GeographicLib::GARS
+   *
+   * This class allows .NET applications to access GeographicLib::GARS.
+   *
+   * The Global Area Reference System is described in
+   * - https://en.wikipedia.org/wiki/Global_Area_Reference_System
+   * - http://earth-info.nga.mil/GandG/coordsys/grids/gars.html
+   * .
+   * It provides a compact string representation of a geographic area
+   * (expressed as latitude and longitude).  The classes Georef and Geohash
+   * implement similar compact representations.
+   *
+   * C# Example:
+   * \include example-GARS.cs
+   * Managed C++ Example:
+   * \include example-GARS.cpp
+   * Visual Basic Example:
+   * \include example-GARS.vb
+   **********************************************************************/
+  public ref class GARS
+  {
+    // all memebers of this class are static so the constructor is hidden.
+      GARS() {}
+
+  public:
+
+    /**
+     * Convert from geographic coordinates to GARS.
+     *
+     * @param[in] lat latitude of point (degrees).
+     * @param[in] lon longitude of point (degrees).
+     * @param[in] prec the precision of the resulting GARS.
+     * @param[out] gars the GARS string.
+     * @exception GeographicErr if \e lat is not in [−90°,
+     *   90°] or if memory for \e gars can't be allocated.
+     *
+     * \e prec specifies the precision of \e gars as follows:
+     * - \e prec = 0 (min), 30' precision, e.g., 006AG;
+     * - \e prec = 1, 15' precision, e.g., 006AG3;
+     * - \e prec = 2 (max), 5' precision, e.g., 006AG39.
+     *
+     * If \e lat or \e lon is NaN, then \e gars is set to "INVALID".
+     **********************************************************************/
+    static void Forward(double lat, double lon, int prec,
+        [System::Runtime::InteropServices::Out] System::String^% gars);
+
+    /**
+     * Convert from GARS to geographic coordinates.
+     *
+     * @param[in] gars the GARS.
+     * @param[out] lat latitude of point (degrees).
+     * @param[out] lon longitude of point (degrees).
+     * @param[out] prec the precision of \e gars.
+     * @param[in] centerp if true (the default) return the center of the
+     *   \e gars, otherwise return the south-west corner.
+     * @exception GeographicErr if \e gars is illegal.
+     *
+     * The case of the letters in \e gars is ignored.  \e prec is in the range
+     * [0, 2] and gives the precision of \e gars as follows:
+     * - \e prec = 0 (min), 30' precision, e.g., 006AG;
+     * - \e prec = 1, 15' precision, e.g., 006AG3;
+     * - \e prec = 2 (max), 5' precision, e.g., 006AG39.
+     *
+     * If the first 3 characters of \e gars are "INV", then \e lat and \e lon
+     * are set to NaN and \e prec is unchanged.
+     **********************************************************************/
+    static void Reverse( System::String^ gars,
+        [System::Runtime::InteropServices::Out] double% lat,
+        [System::Runtime::InteropServices::Out] double% lon,
+        [System::Runtime::InteropServices::Out] int% prec,
+        bool centerp);
+
+    /**
+     * The angular resolution of a GARS.
+     *
+     * @param[in] prec the precision of the GARS.
+     * @return the latitude-longitude resolution (degrees).
+     *
+     * Internally, \e prec is first put in the range [0, 2].
+     **********************************************************************/
+    static double Resolution(int prec);
+
+    /**
+     * The GARS precision required to meet a given geographic resolution.
+     *
+     * @param[in] res the minimum of resolution in latitude and longitude
+     *   (degrees).
+     * @return GARS precision.
+     *
+     * The returned length is in the range [0, 2].
+     **********************************************************************/
+    static int Precision(double res);
+  };
+}  // namespace NETGeographicLib
diff --git a/dotnet/NETGeographicLib/GeoCoords.cpp b/dotnet/NETGeographicLib/GeoCoords.cpp
index 2786f86..40d43c9 100644
--- a/dotnet/NETGeographicLib/GeoCoords.cpp
+++ b/dotnet/NETGeographicLib/GeoCoords.cpp
@@ -42,11 +42,11 @@ GeoCoords::GeoCoords()
 }
 
 //*****************************************************************************
-GeoCoords::GeoCoords(System::String^ s, bool centerp, bool swaplatlong )
+GeoCoords::GeoCoords(System::String^ s, bool centerp, bool longfirst )
 {
     try
     {
-        m_pGeoCoords = new GeographicLib::GeoCoords(StringConvert::ManagedToUnmanaged(s), centerp, swaplatlong);
+        m_pGeoCoords = new GeographicLib::GeoCoords(StringConvert::ManagedToUnmanaged(s), centerp, longfirst);
     }
     catch ( std::bad_alloc )
     {
@@ -93,11 +93,11 @@ GeoCoords::GeoCoords(int zone, bool northp, double easting, double northing)
 }
 
 //*****************************************************************************
-void GeoCoords::Reset( System::String^ s, bool centerp, bool swaplatlong )
+void GeoCoords::Reset( System::String^ s, bool centerp, bool longfirst )
 {
     try
     {
-        m_pGeoCoords->Reset(StringConvert::ManagedToUnmanaged(s), centerp, swaplatlong);
+        m_pGeoCoords->Reset(StringConvert::ManagedToUnmanaged(s), centerp, longfirst);
     }
     catch ( const std::exception& err )
     {
@@ -194,16 +194,16 @@ double GeoCoords::MajorRadius::get() { return UTMUPS::MajorRadius(); }
 double GeoCoords::Flattening::get() { return UTMUPS::Flattening(); }
 
 //*****************************************************************************
-System::String^ GeoCoords::GeoRepresentation(int prec, bool swaplatlong )
+System::String^ GeoCoords::GeoRepresentation(int prec, bool longfirst )
 {
-    return gcnew System::String( m_pGeoCoords->GeoRepresentation(prec, swaplatlong).c_str() );
+    return gcnew System::String( m_pGeoCoords->GeoRepresentation(prec, longfirst).c_str() );
 }
 
 //*****************************************************************************
-System::String^ GeoCoords::DMSRepresentation(int prec, bool swaplatlong,
+System::String^ GeoCoords::DMSRepresentation(int prec, bool longfirst,
                                 char dmssep )
 {
-    return gcnew System::String( m_pGeoCoords->DMSRepresentation(prec, swaplatlong, dmssep).c_str() );
+    return gcnew System::String( m_pGeoCoords->DMSRepresentation(prec, longfirst, dmssep).c_str() );
 }
 
 //*****************************************************************************
diff --git a/dotnet/NETGeographicLib/GeoCoords.h b/dotnet/NETGeographicLib/GeoCoords.h
index 332d1c1..79cdfa6 100644
--- a/dotnet/NETGeographicLib/GeoCoords.h
+++ b/dotnet/NETGeographicLib/GeoCoords.h
@@ -76,7 +76,7 @@ namespace NETGeographicLib
          *   the position.
          * @param[in] centerp governs the interpretation of MGRS coordinates (see
          *   below).
-         * @param[in] swaplatlong governs the interpretation of geographic
+         * @param[in] longfirst governs the interpretation of geographic
          *   coordinates (see below).
          * @exception GeographicErr if the \e s is malformed (see below).
          *
@@ -104,9 +104,9 @@ namespace NETGeographicLib
          *
          * <b>Latitude and Longitude parsing</b>: Latitude precedes longitude,
          * unless a N, S, E, W hemisphere designator is used on one or both
-         * coordinates.  If \e swaplatlong = true (default is false), then
+         * coordinates.  If \e longfirst = true (default is false), then
          * longitude precedes latitude in the absence of a hemisphere designator.
-         * Thus (with \e swaplatlong = false)
+         * Thus (with \e longfirst = false)
          * - 40 -75
          * - N40 W75
          * - -75 N40
@@ -128,10 +128,9 @@ namespace NETGeographicLib
          * - 40:30.5
          * - 40.508333333
          * .
-         * all specify the same angle.  The leading sign applies to all components
-         * so -1d30 is -(1+30/60) = -1.5.  Latitudes must be in the range
-         * [−90°, 90°] and longitudes in the range
-         * [−540°, 540°).  Internally longitudes are reduced
+         * all specify the same angle.  The leading sign applies to all
+         * components so -1d30 is -(1+30/60) = -1.5.  Latitudes must be in the
+         * range [−90°, 90°].  Internally longitudes are reduced
          * to the range [−180°, 180°).
          *
          * <b>UTM/UPS parsing</b>: For UTM zones (−80° ≤ Lat <
@@ -155,7 +154,7 @@ namespace NETGeographicLib
          * - 38SMB4484       = 38N 444000 3684000
          * - 38SMB44148470   = 38N 444140 3684700
          **********************************************************************/
-        GeoCoords(System::String^ s, bool centerp, bool swaplatlong );
+        GeoCoords(System::String^ s, bool centerp, bool longfirst );
 
         /**
          * Construct from geographic coordinates.
@@ -166,8 +165,6 @@ namespace NETGeographicLib
          *   specified zone using the rules given in UTMUPS::zonespec.
          * @exception GeographicErr if \e latitude is not in [−90°,
          *   90°].
-         * @exception GeographicErr if \e longitude is not in [−540°,
-         *   540°).
          * @exception GeographicErr if \e zone cannot be used for this location.
          **********************************************************************/
         GeoCoords(double latitude, double longitude, int zone );
@@ -191,16 +188,16 @@ namespace NETGeographicLib
 
         /**
          * Reset the location from a string.  See
-         * GeoCoords(const std::string& s, bool centerp, bool swaplatlong).
+         * GeoCoords(const std::string& s, bool centerp, bool longfirst).
          *
          * @param[in] s 1-element, 2-element, or 3-element string representation of
          *   the position.
          * @param[in] centerp governs the interpretation of MGRS coordinates.
-         * @param[in] swaplatlong governs the interpretation of geographic
+         * @param[in] longfirst governs the interpretation of geographic
          *   coordinates.
          * @exception GeographicErr if the \e s is malformed.
          **********************************************************************/
-        void Reset( System::String^ s, bool centerp, bool swaplatlong);
+        void Reset( System::String^ s, bool centerp, bool longfirst);
 
         /**
          * Reset the location in terms of geographic coordinates.  See
@@ -212,8 +209,6 @@ namespace NETGeographicLib
          *   specified zone using the rules given in UTMUPS::zonespec.
          * @exception GeographicErr if \e latitude is not in [−90°,
          *   90°].
-         * @exception GeographicErr if \e longitude is not in [−540°,
-         *   540°).
          * @exception GeographicErr if \e zone cannot be used for this location.
          **********************************************************************/
         void Reset(double latitude, double longitude, int zone ) ;
@@ -326,7 +321,7 @@ namespace NETGeographicLib
          * degrees.
          *
          * @param[in] prec precision (relative to about 1m).
-         * @param[in] swaplatlong if true give longitude first (default = false)
+         * @param[in] longfirst if true give longitude first (default = false)
          * @exception std::bad_alloc if memory for the string can't be allocated.
          * @return decimal latitude/longitude string representation.
          *
@@ -336,14 +331,14 @@ namespace NETGeographicLib
          * - prec = 3, 10<sup>−8</sup>°
          * - prec = 9 (max), 10<sup>−14</sup>°
          **********************************************************************/
-        System::String^ GeoRepresentation(int prec, bool swaplatlong );
+        System::String^ GeoRepresentation(int prec, bool longfirst );
 
         /**
          * String representation with latitude and longitude as degrees, minutes,
          * seconds, and hemisphere.
          *
          * @param[in] prec precision (relative to about 1m)
-         * @param[in] swaplatlong if true give longitude first (default = false)
+         * @param[in] longfirst if true give longitude first (default = false)
          * @param[in] dmssep if non-null, use as the DMS separator character
          *   (instead of d, ', " delimiters).
          * @exception std::bad_alloc if memory for the string can't be allocated.
@@ -359,7 +354,7 @@ namespace NETGeographicLib
          * - prec = 1, 0.01"
          * - prec = 10 (max), 10<sup>−11</sup>"
          **********************************************************************/
-        System::String^ DMSRepresentation(int prec, bool swaplatlong,
+        System::String^ DMSRepresentation(int prec, bool longfirst,
                                       char dmssep );
 
         /**
diff --git a/dotnet/NETGeographicLib/Geocentric.h b/dotnet/NETGeographicLib/Geocentric.h
index a4912dc..404d3b3 100644
--- a/dotnet/NETGeographicLib/Geocentric.h
+++ b/dotnet/NETGeographicLib/Geocentric.h
@@ -114,8 +114,7 @@ namespace NETGeographicLib
          * @param[out] Y geocentric coordinate (meters).
          * @param[out] Z geocentric coordinate (meters).
          *
-         * \e lat should be in the range [−90°, 90°]; \e lon
-         * should be in the range [−540°, 540°).
+         * \e lat should be in the range [−90°, 90°].
          **********************************************************************/
         void Forward(double lat, double lon, double h,
             [System::Runtime::InteropServices::Out] double% X,
diff --git a/dotnet/NETGeographicLib/Geodesic.h b/dotnet/NETGeographicLib/Geodesic.h
index 584d350..886a78b 100644
--- a/dotnet/NETGeographicLib/Geodesic.h
+++ b/dotnet/NETGeographicLib/Geodesic.h
@@ -297,10 +297,9 @@ namespace NETGeographicLib
          * @param[out] S12 area under the geodesic (meters<sup>2</sup>).
          * @return \e a12 arc length of between point 1 and point 2 (degrees).
          *
-         * \e lat1 should be in the range [−90°, 90°]; \e lon1 and \e
-         * azi1 should be in the range [−540°, 540°).  The values of
-         * \e lon2 and \e azi2 returned are in the range [−180°,
-         * 180°).
+         * \e lat1 should be in the range [−90°, 90°].  The
+         * values of \e lon2 and \e azi2 returned are in the range
+         * [−180°, 180°).
          *
          * If either point is at a pole, the azimuth is defined by keeping the
          * longitude fixed, writing \e lat = ±(90° − ε),
@@ -391,10 +390,9 @@ namespace NETGeographicLib
          *   (dimensionless).
          * @param[out] S12 area under the geodesic (meters<sup>2</sup>).
          *
-         * \e lat1 should be in the range [−90°, 90°]; \e lon1 and \e
-         * azi1 should be in the range [−540°, 540°).  The values of
-         * \e lon2 and \e azi2 returned are in the range [−180°,
-         * 180°).
+         * \e lat1 should be in the range [−90°, 90°].  The
+         * values of \e lon2 and \e azi2 returned are in the range
+         * [−180°, 180°).
          *
          * If either point is at a pole, the azimuth is defined by keeping the
          * longitude fixed, writing \e lat = ±(90° − ε),
@@ -526,10 +524,7 @@ namespace NETGeographicLib
          *
          * With the LONG_UNROLL bit set, the quantity \e lon2 − \e lon1
          * indicates how many times and in what sense the geodesic encircles
-         * the ellipsoid.  Because \e lon2 might be outside the normal allowed
-         * range for longitudes, [−540°, 540°), be sure to
-         * normalize it with Math::AngNormalize2 before using it in other
-         * GeographicLib calls.
+         * the ellipsoid.
          **********************************************************************/
         double GenDirect(double lat1, double lon1, double azi1,
                         bool arcmode, double s12_a12,
@@ -565,10 +560,9 @@ namespace NETGeographicLib
          * @param[out] S12 area under the geodesic (meters<sup>2</sup>).
          * @return \e a12 arc length of between point 1 and point 2 (degrees).
          *
-         * \e lat1 and \e lat2 should be in the range [−90°, 90°]; \e
-         * lon1 and \e lon2 should be in the range [−540°, 540°).
-         * The values of \e azi1 and \e azi2 returned are in the range
-         * [−180°, 180°).
+         * \e lat1 and \e lat2 should be in the range [−90°,
+         * 90°].  The values of \e azi1 and \e azi2 returned are in the
+         * range [−180°, 180°).
          *
          * If either point is at a pole, the azimuth is defined by keeping the
          * longitude fixed, writing \e lat = ±(90° − ε),
@@ -707,8 +701,7 @@ namespace NETGeographicLib
          *   GeodesicLine::Position.
          * @return a GeodesicLine object.
          *
-         * \e lat1 should be in the range [−90°, 90°]; \e lon1 and \e
-         * azi1 should be in the range [−540°, 540°).
+         * \e lat1 should be in the range [−90°, 90°].
          *
          * The NETGeographicLib::Mask values are
          * - \e caps |= NETGeographicLib::Mask::LATITUDE for the latitude \e lat2; this is
diff --git a/dotnet/NETGeographicLib/GeodesicExact.h b/dotnet/NETGeographicLib/GeodesicExact.h
index cb506d8..640e696 100644
--- a/dotnet/NETGeographicLib/GeodesicExact.h
+++ b/dotnet/NETGeographicLib/GeodesicExact.h
@@ -228,10 +228,9 @@ namespace NETGeographicLib
          * @param[out] S12 area under the geodesic (meters<sup>2</sup>).
          * @return \e a12 arc length of between point 1 and point 2 (degrees).
          *
-         * \e lat1 should be in the range [−90°, 90°]; \e lon1 and \e
-         * azi1 should be in the range [−540°, 540°).  The values of
-         * \e lon2 and \e azi2 returned are in the range [−180°,
-         * 180°).
+         * \e lat1 should be in the range [−90°, 90°];.  The
+         * values of \e lon2 and \e azi2 returned are in the range
+         * [−180°, 180°).
          *
          * If either point is at a pole, the azimuth is defined by keeping the
          * longitude fixed, writing \e lat = ±(90° − ε),
@@ -322,10 +321,9 @@ namespace NETGeographicLib
          *   (dimensionless).
          * @param[out] S12 area under the geodesic (meters<sup>2</sup>).
          *
-         * \e lat1 should be in the range [−90°, 90°]; \e lon1 and \e
-         * azi1 should be in the range [−540°, 540°).  The values of
-         * \e lon2 and \e azi2 returned are in the range [−180°,
-         * 180°).
+         * \e lat1 should be in the range [−90°, 90°].  The
+         * values of \e lon2 and \e azi2 returned are in the range
+         * [−180°, 180°).
          *
          * If either point is at a pole, the azimuth is defined by keeping the
          * longitude fixed, writing \e lat = ±(90° − ε),
@@ -457,10 +455,7 @@ namespace NETGeographicLib
          *
          * With the LONG_UNROLL bit set, the quantity \e lon2 − \e lon1
          * indicates how many times and in what sense the geodesic encircles
-         * the ellipsoid.  Because \e lon2 might be outside the normal allowed
-         * range for longitudes, [−540°, 540°), be sure to
-         * normalize it with Math::AngNormalize2 before using it in other
-         * GeographicLib calls.
+         * the ellipsoid.
          **********************************************************************/
         double GenDirect(double lat1, double lon1, double azi1,
                         bool arcmode, double s12_a12, GeodesicExact::mask outmask,
@@ -495,10 +490,9 @@ namespace NETGeographicLib
          * @param[out] S12 area under the geodesic (meters<sup>2</sup>).
          * @return \e a12 arc length of between point 1 and point 2 (degrees).
          *
-         * \e lat1 and \e lat2 should be in the range [−90°, 90°]; \e
-         * lon1 and \e lon2 should be in the range [−540°, 540°).
-         * The values of \e azi1 and \e azi2 returned are in the range
-         * [−180°, 180°).
+         * \e lat1 and \e lat2 should be in the range [−90°,
+         * 90°].  The values of \e azi1 and \e azi2 returned are in the
+         * range [−180°, 180°).
          *
          * If either point is at a pole, the azimuth is defined by keeping the
          * longitude fixed, writing \e lat = ±(90° − ε),
@@ -632,8 +626,7 @@ namespace NETGeographicLib
          *   GeodesicLineExact::Position.
          * @return a GeodesicLineExact object.
          *
-         * \e lat1 should be in the range [−90°, 90°]; \e lon1 and \e
-         * azi1 should be in the range [−540°, 540°).
+         * \e lat1 should be in the range [−90°, 90°].
          *
          * The GeodesicExact::mask values are
          * - \e caps |= NETGeographicLib::Mask::LATITUDE for the latitude \e lat2; this is
diff --git a/dotnet/NETGeographicLib/GeodesicLine.h b/dotnet/NETGeographicLib/GeodesicLine.h
index 5f18855..525706d 100644
--- a/dotnet/NETGeographicLib/GeodesicLine.h
+++ b/dotnet/NETGeographicLib/GeodesicLine.h
@@ -166,8 +166,7 @@ namespace NETGeographicLib
          *   i.e., which quantities can be returned in calls to
          *   GeodesicLine::Position.
          *
-         * \e lat1 should be in the range [−90°, 90°]; \e lon1 and \e
-         * azi1 should be in the range [−540°, 540°).
+         * \e lat1 should be in the range [−90°, 90°].
          *
          * The NETGeographicLib::Mask values are
          * - \e caps |= GeodesicLine::LATITUDE for the latitude \e lat2; this is
@@ -474,10 +473,7 @@ namespace NETGeographicLib
          *
          * With the LONG_UNROLL bit set, the quantity \e lon2 − \e lon1
          * indicates how many times and in what sense the geodesic encircles
-         * the ellipsoid.  Because \e lon2 might be outside the normal allowed
-         * range for longitudes, [−540°, 540°), be sure to
-         * normalize it with Math::AngNormalize2 before using it in other
-         * GeographicLib calls.
+         * the ellipsoid.
          **********************************************************************/
         double GenPosition(bool arcmode, double s12_a12,
                     GeodesicLine::mask outmask,
diff --git a/dotnet/NETGeographicLib/GeodesicLineExact.h b/dotnet/NETGeographicLib/GeodesicLineExact.h
index 3b78998..bcbbd54 100644
--- a/dotnet/NETGeographicLib/GeodesicLineExact.h
+++ b/dotnet/NETGeographicLib/GeodesicLineExact.h
@@ -156,8 +156,7 @@ namespace NETGeographicLib
          *   possess, i.e., which quantities can be returned in calls to
          *   GeodesicLine::Position.
          *
-         * \e lat1 should be in the range [−90°, 90°]; \e lon1 and \e
-         * azi1 should be in the range [−540°, 540°).
+         * \e lat1 should be in the range [−90°, 90°].
          *
          * The NETGeographicLib::Mask values are
          * - \e caps |= GeodesicLineExact::LATITUDE for the latitude \e lat2; this
@@ -465,10 +464,7 @@ namespace NETGeographicLib
          *
          * With the LONG_UNROLL bit set, the quantity \e lon2 − \e lon1
          * indicates how many times and in what sense the geodesic encircles
-         * the ellipsoid.  Because \e lon2 might be outside the normal allowed
-         * range for longitudes, [−540°, 540°), be sure to
-         * normalize it with Math::AngNormalize2 before using it in other
-         * GeographicLib calls.
+         * the ellipsoid.
          **********************************************************************/
         double GenPosition(bool arcmode, double s12_a12,
                 GeodesicLineExact::mask outmask,
diff --git a/dotnet/NETGeographicLib/Geohash.h b/dotnet/NETGeographicLib/Geohash.h
index abedf89..b6b0864 100644
--- a/dotnet/NETGeographicLib/Geohash.h
+++ b/dotnet/NETGeographicLib/Geohash.h
@@ -45,10 +45,8 @@ namespace NETGeographicLib
          * @param[in] lon longitude of point (degrees).
          * @param[in] len the length of the resulting geohash.
          * @param[out] geohash the geohash.
-         * @exception GeographicErr if \e la is not in [−90°,
+         * @exception GeographicErr if \e lat is not in [−90°,
          *   90°].
-         * @exception GeographicErr if \e lon is not in [−540°,
-         *   540°).
          * @exception std::bad_alloc if memory for \e geohash can't be allocated.
          *
          * Internally, \e len is first put in the range [0, 18].
diff --git a/dotnet/NETGeographicLib/Geoid.h b/dotnet/NETGeographicLib/Geoid.h
index 864c392..f0e87c0 100644
--- a/dotnet/NETGeographicLib/Geoid.h
+++ b/dotnet/NETGeographicLib/Geoid.h
@@ -156,8 +156,7 @@ namespace NETGeographicLib
          * parallels \e south and \e north and the meridians \e west and \e east.
          * \e east is always interpreted as being east of \e west, if necessary by
          * adding 360° to its value.  \e south and \e north should be in
-         * the range [−90°, 90°]; \e west and \e east should
-         * be in the range [−540°, 540°).
+         * the range [−90°, 90°].
          **********************************************************************/
         void CacheArea(double south, double west, double north, double east);
 
@@ -196,8 +195,7 @@ namespace NETGeographicLib
          *   never happens if (\e lat, \e lon) is within a successfully cached area.
          * @return geoid height (meters).
          *
-         * The latitude should be in [−90°, 90°] and
-         * longitude should be in [−540°, 540°).
+         * The latitude should be in [−90°, 90°].
          **********************************************************************/
         double Height(double lat, double lon);
 
@@ -212,13 +210,12 @@ namespace NETGeographicLib
          *   never happens if (\e lat, \e lon) is within a successfully cached area.
          * @return geoid height (meters).
          *
-         * The latitude should be in [−90°, 90°] and
-         * longitude should be in [−540°, 540°).  As a result
-         * of the way that the geoid data is stored, the calculation of gradients
-         * can result in large quantization errors.  This is particularly acute for
-         * fine grids, at high latitudes, and for the easterly gradient.  If you
-         * need to compute the direction of the acceleration due to gravity
-         * accurately, you should use GravityModel::Gravity.
+         * The latitude should be in [−90°, 90°].  As a result of
+         * the way that the geoid data is stored, the calculation of gradients
+         * can result in large quantization errors.  This is particularly acute
+         * for fine grids, at high latitudes, and for the easterly gradient.
+         * If you need to compute the direction of the acceleration due to
+         * gravity accurately, you should use GravityModel::Gravity.
          **********************************************************************/
         double Height(double lat, double lon,
             [System::Runtime::InteropServices::Out] double% gradn,
diff --git a/dotnet/NETGeographicLib/Georef.cpp b/dotnet/NETGeographicLib/Georef.cpp
new file mode 100644
index 0000000..2939cf3
--- /dev/null
+++ b/dotnet/NETGeographicLib/Georef.cpp
@@ -0,0 +1,57 @@
+/**
+ * \file NETGeographicLib/Georef.cpp
+ * \brief Source for NETGeographicLib::Georef class
+ *
+ * NETGeographicLib is copyright (c) Scott Heiman (2013-2015)
+ * GeographicLib is Copyright (c) Charles Karney (2010-2012)
+ * <charles at karney.com> and licensed under the MIT/X11 License.
+ * For more information, see
+ * http://geographiclib.sourceforge.net/
+ **********************************************************************/
+#include "stdafx.h"
+#include "GeographicLib/Georef.hpp"
+#include "Georef.h"
+#include "NETGeographicLib.h"
+
+using namespace NETGeographicLib;
+
+//*****************************************************************************
+void Georef::Forward(double lat, double lon, int prec, System::String^% georef)
+{
+    try
+    {
+        std::string l;
+        GeographicLib::Georef::Forward( lat, lon, prec, l );
+        georef = gcnew System::String( l.c_str() );
+    }
+    catch ( const std::exception& xcpt )
+    {
+        throw gcnew GeographicErr( xcpt.what() );
+    }
+}
+
+//*****************************************************************************
+void Georef::Reverse( System::String^ georef,  double% lat,  double% lon,
+        int% prec, bool centerp)
+{
+    try
+    {
+        double llat, llon;
+        int lprec;
+        GeographicLib::Georef::Reverse( StringConvert::ManagedToUnmanaged( georef ),
+            llat, llon, lprec, centerp );
+        lat = llat;
+        lon = llon;
+        prec = lprec;
+    }
+    catch ( const std::exception& err )
+    {
+        throw gcnew GeographicErr( err.what() );
+    }
+}
+
+//*****************************************************************************
+double Georef::Resolution(int prec) { return GeographicLib::Georef::Resolution(prec); }
+
+//*****************************************************************************
+int Georef::Precision(double res) { return GeographicLib::Georef::Precision(res); }
diff --git a/dotnet/NETGeographicLib/Georef.h b/dotnet/NETGeographicLib/Georef.h
new file mode 100644
index 0000000..b27b4c4
--- /dev/null
+++ b/dotnet/NETGeographicLib/Georef.h
@@ -0,0 +1,119 @@
+/**
+ * \file NETGeographicLib/Georef.h
+ * \brief Header for NETGeographicLib::Georef class
+ *
+ * NETGeographicLib is copyright (c) Scott Heiman (2013-2015)
+ * GeographicLib is Copyright (c) Charles Karney (2010-2012)
+ * <charles at karney.com> and licensed under the MIT/X11 License.
+ * For more information, see
+ * http://geographiclib.sourceforge.net/
+ **********************************************************************/
+#pragma once
+
+namespace NETGeographicLib
+{
+  /**
+   * \brief .NET wrapper for GeographicLib::Georef.
+   *
+   * The World Geographic Reference System is described in
+   * - https://en.wikipedia.org/wiki/Georef
+   * - http://earth-info.nga.mil/GandG/coordsys/grids/georef.pdf
+   * .
+   * It provides a compact string representation of a geographic area
+   * (expressed as latitude and longitude).  The classes GARS and Geohash
+   * implement similar compact representations.
+   *
+   * C# Example:
+   * \include example-Georef.cs
+   * Managed C++ Example:
+   * \include example-Georef.cpp
+   * Visual Basic Example:
+   * \include example-Georef.vb
+   **********************************************************************/
+  public ref class Georef
+  {
+  private:
+      // hide the constructor since all members of this class are static.
+      Georef() {}
+
+  public:
+    /**
+     * Convert from geographic coordinates to georef.
+     *
+     * @param[in] lat latitude of point (degrees).
+     * @param[in] lon longitude of point (degrees).
+     * @param[in] prec the precision of the resulting georef.
+     * @param[out] georef the georef string.
+     * @exception GeographicErr if \e lat is not in [−90°,
+     *   90°] or if memory for \e georef can't be allocated.
+     *
+     * \e prec specifies the precision of \e georef as follows:
+     * - \e prec = −1 (min), 15°
+     * - \e prec = 0, 1°
+     * - \e prec = 1, converted to \e prec = 2
+     * - \e prec = 2, 1'
+     * - \e prec = 3, 0.1'
+     * - \e prec = 4, 0.01'
+     * - \e prec = 5, 0.001'
+     * - …
+     * - \e prec = 11 (max), 10<sup>−9</sup>'
+     *
+     * If \e lat or \e lon is NaN, then \e georef is set to "INVALID".
+     **********************************************************************/
+    static void Forward(double lat, double lon, int prec,
+        [System::Runtime::InteropServices::Out] System::String^% georef);
+
+    /**
+     * Convert from Georef to geographic coordinates.
+     *
+     * @param[in] georef the Georef.
+     * @param[out] lat latitude of point (degrees).
+     * @param[out] lon longitude of point (degrees).
+     * @param[out] prec the precision of \e georef.
+     * @param[in] centerp if true (the default) return the center
+     *   \e georef, otherwise return the south-west corner.
+     * @exception GeographicErr if \e georef is illegal.
+     *
+     * The case of the letters in \e georef is ignored.  \e prec is in the
+     * range [−1, 11] and gives the precision of \e georef as follows:
+     * - \e prec = −1 (min), 15°
+     * - \e prec = 0, 1°
+     * - \e prec = 1, not returned
+     * - \e prec = 2, 1'
+     * - \e prec = 3, 0.1'
+     * - \e prec = 4, 0.01'
+     * - \e prec = 5, 0.001'
+     * - …
+     * - \e prec = 11 (max), 10<sup>−9</sup>'
+     *
+     * If the first 3 characters of \e georef are "INV", then \e lat and \e lon
+     * are set to NaN and \e prec is unchanged.
+     **********************************************************************/
+    static void Reverse( System::String^ georef,
+        [System::Runtime::InteropServices::Out] double% lat,
+        [System::Runtime::InteropServices::Out] double% lon,
+        [System::Runtime::InteropServices::Out] int% prec,
+        bool centerp );
+
+    /**
+     * The angular resolution of a Georef.
+     *
+     * @param[in] prec the precision of the Georef.
+     * @return the latitude-longitude resolution (degrees).
+     *
+     * Internally, \e prec is first put in the range [−1, 11].
+     **********************************************************************/
+    static double Resolution(int prec);
+
+    /**
+     * The Georef precision required to meet a given geographic resolution.
+     *
+     * @param[in] res the minimum of resolution in latitude and longitude
+     *   (degrees).
+     * @return Georef precision.
+     *
+     * The returned length is in the range [0, 11].
+     **********************************************************************/
+    static int Precision(double res);
+  };
+}
diff --git a/dotnet/NETGeographicLib/Gnomonic.h b/dotnet/NETGeographicLib/Gnomonic.h
index d97e795..a5c9992 100644
--- a/dotnet/NETGeographicLib/Gnomonic.h
+++ b/dotnet/NETGeographicLib/Gnomonic.h
@@ -140,15 +140,15 @@ namespace NETGeographicLib
          * @param[out] azi azimuth of geodesic at point (degrees).
          * @param[out] rk reciprocal of azimuthal scale at point.
          *
-         * \e lat0 and \e lat should be in the range [−90°, 90°] and
-         * \e lon0 and \e lon should be in the range [−540°, 540°).
-         * The scale of the projection is 1/<i>rk</i><sup>2</sup> in the "radial"
-         * direction, \e azi clockwise from true north, and is 1/\e rk in the
-         * direction perpendicular to this.  If the point lies "over the horizon",
-         * i.e., if \e rk ≤ 0, then NaNs are returned for \e x and \e y (the
-         * correct values are returned for \e azi and \e rk).  A call to Forward
-         * followed by a call to Reverse will return the original (\e lat, \e lon)
-         * (to within roundoff) provided the point in not over the horizon.
+         * \e lat0 and \e lat should be in the range [−90°, 90°].
+         * The scale of the projection is 1/<i>rk</i><sup>2</sup> in the
+         * "radial" direction, \e azi clockwise from true north, and is 1/\e rk
+         * in the direction perpendicular to this.  If the point lies "over the
+         * horizon", i.e., if \e rk ≤ 0, then NaNs are returned for \e x and
+         * \e y (the correct values are returned for \e azi and \e rk).  A call
+         * to Forward followed by a call to Reverse will return the original
+         * (\e lat, \e lon) (to within roundoff) provided the point in not over
+         * the horizon.
          **********************************************************************/
         void Forward(double lat0, double lon0, double lat, double lon,
                      [System::Runtime::InteropServices::Out] double% x,
@@ -168,17 +168,16 @@ namespace NETGeographicLib
          * @param[out] azi azimuth of geodesic at point (degrees).
          * @param[out] rk reciprocal of azimuthal scale at point.
          *
-         * \e lat0 should be in the range [−90°, 90°] and \e
-         * lon0 should be in the range [−540°, 540°).  \e lat
-         * will be in the range [−90°, 90°] and \e lon will
-         * be in the range [−180°, 180°).  The scale of the
-         * projection is 1/\e rk<sup>2</sup> in the "radial" direction, \e azi
-         * clockwise from true north, and is 1/\e rk in the direction perpendicular
-         * to this.  Even though all inputs should return a valid \e lat and \e
-         * lon, it's possible that the procedure fails to converge for very large
-         * \e x or \e y; in this case NaNs are returned for all the output
-         * arguments.  A call to Reverse followed by a call to Forward will return
-         * the original (\e x, \e y) (to roundoff).
+         * \e lat0 should be in the range [−90°, 90°].  \e lat
+         * will be in the range [−90°, 90°] and \e lon will be in
+         * the range [−180°, 180°).  The scale of the projection
+         * is 1/\e rk<sup>2</sup> in the "radial" direction, \e azi clockwise
+         * from true north, and is 1/\e rk in the direction perpendicular to
+         * this.  Even though all inputs should return a valid \e lat and \e
+         * lon, it's possible that the procedure fails to converge for very
+         * large \e x or \e y; in this case NaNs are returned for all the
+         * output arguments.  A call to Reverse followed by a call to Forward
+         * will return the original (\e x, \e y) (to roundoff).
          **********************************************************************/
         void Reverse(double lat0, double lon0, double x, double y,
                      [System::Runtime::InteropServices::Out] double% lat,
diff --git a/dotnet/NETGeographicLib/LambertConformalConic.h b/dotnet/NETGeographicLib/LambertConformalConic.h
index 63fa877..a23f135 100644
--- a/dotnet/NETGeographicLib/LambertConformalConic.h
+++ b/dotnet/NETGeographicLib/LambertConformalConic.h
@@ -173,14 +173,14 @@ namespace NETGeographicLib
          * @param[out] gamma meridian convergence at point (degrees).
          * @param[out] k scale of projection at point.
          *
-         * The latitude origin is given by LambertConformalConic::LatitudeOrigin().
-         * No false easting or northing is added and \e lat should be in the range
-         * [−90°, 90°]; \e lon and \e lon0 should be in the
-         * range [−540°, 540°).  The error in the projection
-         * is less than about 10 nm (10 nanometers), true distance, and the errors
-         * in the meridian convergence and scale are consistent with this.  The
-         * values of \e x and \e y returned for points which project to infinity
-         * (i.e., one or both of the poles) will be large but finite.
+         * The latitude origin is given by
+         * LambertConformalConic::LatitudeOrigin().  No false easting or
+         * northing is added and \e lat should be in the range [−90°,
+         * 90°].  The error in the projection is less than about 10 nm (10
+         * nanometers), true distance, and the errors in the meridian
+         * convergence and scale are consistent with this.  The values of \e x
+         * and \e y returned for points which project to infinity (i.e., one or
+         * both of the poles) will be large but finite.
          **********************************************************************/
         void Forward(double lon0, double lat, double lon,
                      [System::Runtime::InteropServices::Out] double% x,
@@ -199,13 +199,12 @@ namespace NETGeographicLib
          * @param[out] gamma meridian convergence at point (degrees).
          * @param[out] k scale of projection at point.
          *
-         * The latitude origin is given by LambertConformalConic::LatitudeOrigin().
-         * No false easting or northing is added.  \e lon0 should be in the range
-         * [−540°, 540°).  The value of \e lon returned is in
-         * the range [−180°, 180°).  The error in the
-         * projection is less than about 10 nm (10 nanometers), true distance, and
-         * the errors in the meridian convergence and scale are consistent with
-         * this.
+         * The latitude origin is given by
+         * LambertConformalConic::LatitudeOrigin().  No false easting or
+         * northing is added.  The value of \e lon returned is in the range
+         * [−180°, 180°).  The error in the projection is less
+         * than about 10 nm (10 nanometers), true distance, and the errors in
+         * the meridian convergence and scale are consistent with this.
          **********************************************************************/
         void Reverse(double lon0, double x, double y,
                      [System::Runtime::InteropServices::Out] double% lat,
diff --git a/dotnet/NETGeographicLib/LocalCartesian.h b/dotnet/NETGeographicLib/LocalCartesian.h
index 6f7c313..8ede9ea 100644
--- a/dotnet/NETGeographicLib/LocalCartesian.h
+++ b/dotnet/NETGeographicLib/LocalCartesian.h
@@ -64,8 +64,7 @@ namespace NETGeographicLib
          * @param[in] earth Geocentric object for the transformation; default
          *   Geocentric::WGS84.
          *
-         * \e lat0 should be in the range [−90°, 90°]; \e
-         * lon0 should be in the range [−540°, 540°).
+         * \e lat0 should be in the range [−90°, 90°].
          **********************************************************************/
         LocalCartesian(double lat0, double lon0, double h0,
                        Geocentric^ earth );
@@ -77,8 +76,7 @@ namespace NETGeographicLib
          * @param[in] lon0 longitude at origin (degrees).
          * @param[in] h0 height above ellipsoid at origin (meters); default 0.
          *
-         * \e lat0 should be in the range [−90°, 90°]; \e
-         * lon0 should be in the range [−540°, 540°).
+         * \e lat0 should be in the range [−90°, 90°].
          **********************************************************************/
         LocalCartesian(double lat0, double lon0, double h0 );
 
@@ -112,8 +110,7 @@ namespace NETGeographicLib
          * @param[in] lon0 longitude at origin (degrees).
          * @param[in] h0 height above ellipsoid at origin (meters); default 0.
          *
-         * \e lat0 should be in the range [−90°, 90°]; \e
-         * lon0 should be in the range [−540°, 540°).
+         * \e lat0 should be in the range [−90°, 90°].
          **********************************************************************/
         void Reset(double lat0, double lon0, double h0 );
 
@@ -127,8 +124,7 @@ namespace NETGeographicLib
          * @param[out] y local cartesian coordinate (meters).
          * @param[out] z local cartesian coordinate (meters).
          *
-         * \e lat should be in the range [−90°, 90°]; \e lon
-         * should be in the range [−540°, 540°).
+         * \e lat should be in the range [−90°, 90°].
          **********************************************************************/
         void Forward(double lat, double lon, double h,
             [System::Runtime::InteropServices::Out] double% x,
@@ -147,8 +143,7 @@ namespace NETGeographicLib
          * @param[out] z local cartesian coordinate (meters).
          * @param[out] M a 3 × 3 rotation matrix.
          *
-         * \e lat should be in the range [−90°, 90°]; \e lon
-         * should be in the range [−540°, 540°).
+         * \e lat should be in the range [−90°, 90°].
          *
          * Let \e v be a unit vector located at (\e lat, \e lon, \e h).  We can
          * express \e v as \e column vectors in one of two ways
diff --git a/dotnet/NETGeographicLib/NETGeographicLib.cpp b/dotnet/NETGeographicLib/NETGeographicLib.cpp
index 001109a..601b069 100644
--- a/dotnet/NETGeographicLib/NETGeographicLib.cpp
+++ b/dotnet/NETGeographicLib/NETGeographicLib.cpp
@@ -10,6 +10,7 @@
  **********************************************************************/
 #include "stdafx.h"
 #include "GeographicLib/Config.h"
+#include "GeographicLib/Utility.hpp"
 #include "NETGeographicLib.h"
 
 using namespace System::Runtime::InteropServices;
@@ -47,3 +48,10 @@ int VersionInfo::Patch()
 {
     return GEOGRAPHICLIB_VERSION_PATCH;
 }
+
+//*****************************************************************************
+double Utility::FractionalYear( System::String^ s )
+{
+    return GeographicLib::Utility::fractionalyear<double>(
+        StringConvert::ManagedToUnmanaged( s ) );
+}
diff --git a/dotnet/NETGeographicLib/NETGeographicLib.h b/dotnet/NETGeographicLib/NETGeographicLib.h
index d3c4aee..7cb0dcb 100644
--- a/dotnet/NETGeographicLib/NETGeographicLib.h
+++ b/dotnet/NETGeographicLib/NETGeographicLib.h
@@ -260,4 +260,31 @@ namespace NETGeographicLib
             static property double J2 { double get() { return m_J2; } }
         };
     };
+
+    /**
+     * @brief Utility library.
+     *
+     * This class only exposes the GeographicLib::Utility::fractionalyear
+     * function.
+     **********************************************************************/
+    public ref class Utility
+    {
+    private:
+        // hide the constructor since all members of this class are static
+        Utility() {}
+    public:
+    /**
+     * Convert a string representing a date to a fractional year.
+     *
+     * @param[in] s the string to be converted.
+     * @exception GeographicErr if \e s can't be interpreted as a date.
+     * @return the fractional year.
+     *
+     * The string is first read as an ordinary number (e.g., 2010 or 2012.5);
+     * if this is successful, the value is returned.  Otherwise the string
+     * should be of the form yyyy-mm or yyyy-mm-dd and this is converted to a
+     * number with 2010-01-01 giving 2010.0 and 2012-07-03 giving 2012.5.
+     **********************************************************************/
+        static double FractionalYear( System::String^ s );
+    };
 }  // namespace NETGeographicLib
diff --git a/dotnet/NETGeographicLib/OSGB.h b/dotnet/NETGeographicLib/OSGB.h
index 7819396..73ecf05 100644
--- a/dotnet/NETGeographicLib/OSGB.h
+++ b/dotnet/NETGeographicLib/OSGB.h
@@ -55,8 +55,7 @@ namespace NETGeographicLib
          * @param[out] gamma meridian convergence at point (degrees).
          * @param[out] k scale of projection at point.
          *
-         * \e lat should be in the range [−90°, 90°]; \e lon
-         * should be in the range [−540°, 540°).
+         * \e lat should be in the range [−90°, 90°].
          **********************************************************************/
         static void Forward(double lat, double lon,
                     [System::Runtime::InteropServices::Out] double% x,
diff --git a/dotnet/NETGeographicLib/PolarStereographic.h b/dotnet/NETGeographicLib/PolarStereographic.h
index 2dba46c..2240fac 100644
--- a/dotnet/NETGeographicLib/PolarStereographic.h
+++ b/dotnet/NETGeographicLib/PolarStereographic.h
@@ -105,8 +105,7 @@ namespace NETGeographicLib
          *
          * No false easting or northing is added.  \e lat should be in the range
          * (−90°, 90°] for \e northp = true and in the range
-         * [−90°, 90°) for \e northp = false; \e lon should
-         * be in the range [−540°, 540°).
+         * [−90°, 90°) for \e northp = false.
          **********************************************************************/
         void Forward(bool northp, double lat, double lon,
                      [System::Runtime::InteropServices::Out] double% x,
diff --git a/dotnet/NETGeographicLib/PolygonArea.h b/dotnet/NETGeographicLib/PolygonArea.h
index a055680..ab4a299 100644
--- a/dotnet/NETGeographicLib/PolygonArea.h
+++ b/dotnet/NETGeographicLib/PolygonArea.h
@@ -90,8 +90,7 @@ namespace NETGeographicLib
          * @param[in] lat the latitude of the point (degrees).
          * @param[in] lon the longitude of the point (degrees).
          *
-         * \e lat should be in the range [−90°, 90°] and \e
-         * lon should be in the range [−540°, 540°).
+         * \e lat should be in the range [−90°, 90°].
          **********************************************************************/
         void AddPoint(double lat, double lon);
 
@@ -101,9 +100,9 @@ namespace NETGeographicLib
          * @param[in] azi azimuth at current point (degrees).
          * @param[in] s distance from current point to next point (meters).
          *
-         * \e azi should be in the range [−540°, 540°).  This does
-         * nothing if no points have been added yet.  Use PolygonArea::CurrentPoint
-         * to determine the position of the new vertex.
+         * This does nothing if no points have been added yet.  Use
+         * PolygonArea::CurrentPoint to determine the position of the new
+         * vertex.
          **********************************************************************/
         void AddEdge(double azi, double s);
 
@@ -148,8 +147,7 @@ namespace NETGeographicLib
          *   constructor.
          * @return the number of points.
          *
-         * \e lat should be in the range [−90°, 90°] and \e
-         * lon should be in the range [−540°, 540°).
+         * \e lat should be in the range [−90°, 90°].
          **********************************************************************/
         unsigned TestPoint(double lat, double lon, bool reverse, bool sign,
                 [System::Runtime::InteropServices::Out] double% perimeter,
@@ -177,8 +175,6 @@ namespace NETGeographicLib
          *   (meters<sup>2</sup>); only set if polyline is false in the
          *   constructor.
          * @return the number of points.
-         *
-         * \e azi should be in the range [−540°, 540°).
          **********************************************************************/
         unsigned TestEdge(double azi, double s, bool reverse, bool sign,
                 [System::Runtime::InteropServices::Out] double% perimeter,
@@ -262,8 +258,7 @@ namespace NETGeographicLib
          * @param[in] lat the latitude of the point (degrees).
          * @param[in] lon the longitude of the point (degrees).
          *
-         * \e lat should be in the range [−90°, 90°] and \e
-         * lon should be in the range [−540°, 540°).
+         * \e lat should be in the range [−90°, 90°].
          **********************************************************************/
         void AddPoint(double lat, double lon);
 
@@ -273,9 +268,9 @@ namespace NETGeographicLib
          * @param[in] azi azimuth at current point (degrees).
          * @param[in] s distance from current point to next point (meters).
          *
-         * \e azi should be in the range [−540°, 540°).  This does
-         * nothing if no points have been added yet.  Use PolygonArea::CurrentPoint
-         * to determine the position of the new vertex.
+         * This does nothing if no points have been added yet.  Use
+         * PolygonArea::CurrentPoint to determine the position of the new
+         * vertex.
          **********************************************************************/
         void AddEdge(double azi, double s);
 
@@ -320,8 +315,7 @@ namespace NETGeographicLib
          *   constructor.
          * @return the number of points.
          *
-         * \e lat should be in the range [−90°, 90°] and \e
-         * lon should be in the range [−540°, 540°).
+         * \e lat should be in the range [−90°, 90°].
          **********************************************************************/
         unsigned TestPoint(double lat, double lon, bool reverse, bool sign,
                 [System::Runtime::InteropServices::Out] double% perimeter,
@@ -349,8 +343,6 @@ namespace NETGeographicLib
          *   (meters<sup>2</sup>); only set if polyline is false in the
          *   constructor.
          * @return the number of points.
-         *
-         * \e azi should be in the range [−540°, 540°).
          **********************************************************************/
         unsigned TestEdge(double azi, double s, bool reverse, bool sign,
                 [System::Runtime::InteropServices::Out] double% perimeter,
@@ -434,8 +426,7 @@ namespace NETGeographicLib
          * @param[in] lat the latitude of the point (degrees).
          * @param[in] lon the longitude of the point (degrees).
          *
-         * \e lat should be in the range [−90°, 90°] and \e
-         * lon should be in the range [−540°, 540°).
+         * \e lat should be in the range [−90°, 90°].
          **********************************************************************/
         void AddPoint(double lat, double lon);
 
@@ -445,9 +436,9 @@ namespace NETGeographicLib
          * @param[in] azi azimuth at current point (degrees).
          * @param[in] s distance from current point to next point (meters).
          *
-         * \e azi should be in the range [−540°, 540°).  This does
-         * nothing if no points have been added yet.  Use PolygonArea::CurrentPoint
-         * to determine the position of the new vertex.
+         * This does nothing if no points have been added yet.  Use
+         * PolygonArea::CurrentPoint to determine the position of the new
+         * vertex.
          **********************************************************************/
         void AddEdge(double azi, double s);
 
@@ -492,8 +483,7 @@ namespace NETGeographicLib
          *   constructor.
          * @return the number of points.
          *
-         * \e lat should be in the range [−90°, 90°] and \e
-         * lon should be in the range [−540°, 540°).
+         * \e lat should be in the range [−90°, 90°].
          **********************************************************************/
         unsigned TestPoint(double lat, double lon, bool reverse, bool sign,
                 [System::Runtime::InteropServices::Out] double% perimeter,
@@ -521,8 +511,6 @@ namespace NETGeographicLib
          *   (meters<sup>2</sup>); only set if polyline is false in the
          *   constructor.
          * @return the number of points.
-         *
-         * \e azi should be in the range [−540°, 540°).
          **********************************************************************/
         unsigned TestEdge(double azi, double s, bool reverse, bool sign,
                 [System::Runtime::InteropServices::Out] double% perimeter,
diff --git a/dotnet/NETGeographicLib/Rhumb.h b/dotnet/NETGeographicLib/Rhumb.h
index abdecf5..06fdd66 100644
--- a/dotnet/NETGeographicLib/Rhumb.h
+++ b/dotnet/NETGeographicLib/Rhumb.h
@@ -154,8 +154,7 @@ namespace NETGeographicLib {
      * @param[out] lon2 longitude of point 2 (degrees).
      * @param[out] S12 area under the rhumb line (meters<sup>2</sup>).
      *
-     * \e lat1 should be in the range [−90°, 90°]; \e lon1 and \e
-     * azi12 should be in the range [−540°, 540°).  The value of
+     * \e lat1 should be in the range [−90°, 90°].  The value of
      * \e lon2 returned is in the range [−180°, 180°).
      *
      * If point 1 is a pole, the cosine of its latitude is taken to be
@@ -181,8 +180,7 @@ namespace NETGeographicLib {
      * @param[out] lat2 latitude of point 2 (degrees).
      * @param[out] lon2 longitude of point 2 (degrees).
      *
-     * \e lat1 should be in the range [−90°, 90°]; \e lon1 and \e
-     * azi1 should be in the range [−540°, 540°).  The values of
+     * \e lat1 should be in the range [−90°, 90°].  The values of
      * \e lon2 and \e azi2 returned are in the range [−180°,
      * 180°).
      *
@@ -222,9 +220,6 @@ namespace NETGeographicLib {
      * .
      * With the LONG_UNROLL bit set, the quantity \e lon2 − \e lon1
      * indicates how many times the rhumb line wrapped around the ellipsoid.
-     * Because \e lon2 might be outside the normal allowed range for
-     * longitudes, [−540°, 540°), be sure to normalize it with
-     * Math::AngNormalize2 before using it in other GeographicLib calls.
      **********************************************************************/
     void GenDirect(double lat1, double lon1, double azi12, double s12,
                    Rhumb::mask outmask,
@@ -246,8 +241,7 @@ namespace NETGeographicLib {
      * The shortest rhumb line is found.  If the end points are on opposite
      * meridians, there are two shortest rhumb lines and the east-going one is
      * chosen.  \e lat1 and \e lat2 should be in the range [−90°,
-     * 90°]; \e lon1 and \e lon2 should be in the range [−540°,
-     * 540°).  The value of \e azi12 returned is in the range
+     * 90°].  The value of \e azi12 returned is in the range
      * [−180°, 180°).
      *
      * If either point is a pole, the cosine of its latitude is taken to be
@@ -271,8 +265,7 @@ namespace NETGeographicLib {
      * @param[out] azi12 azimuth of the rhumb line (degrees).
      *
      * The shortest rhumb line is found.  \e lat1 and \e lat2 should be in the
-     * range [−90°, 90°]; \e lon1 and \e lon2 should be in the
-     * range [−540°, 540°).  The value of \e azi12 returned is in
+     * range [−90°, 90°].  The value of \e azi12 returned is in
      * the range [−180°, 180°).
      *
      * If either point is a pole, the cosine of its latitude is taken to be
@@ -318,8 +311,7 @@ namespace NETGeographicLib {
      * @param[in] azi12 azimuth of the rhumb line (degrees).
      * @return a RhumbLine object.
      *
-     * \e lat1 should be in the range [−90°, 90°]; \e lon1 and \e
-     * azi12 should be in the range [−540°, 540°).
+     * \e lat1 should be in the range [−90°, 90°].
      *
      * If point 1 is a pole, the cosine of its latitude is taken to be
      * 1/ε<sup>2</sup> (where ε is 2<sup>-52</sup>).  This
@@ -510,9 +502,7 @@ namespace NETGeographicLib {
      * .
      * With the LONG_UNROLL bit set, the quantity \e lon2 − \e lon1
      * indicates how many times and in what sense the rhumb line encircles the
-     * ellipsoid.  Because \e lon2 might be outside the normal allowed range
-     * for longitudes, [−540°, 540°), be sure to normalize it
-     * with Math::AngNormalize2 before using it in other GeographicLib calls.
+     * ellipsoid.
      *
      * If \e s12 is large enough that the rhumb line crosses a pole, the
      * longitude of point 2 is indeterminate (a NaN is returned for \e lon2 and
diff --git a/dotnet/NETGeographicLib/TransverseMercator.h b/dotnet/NETGeographicLib/TransverseMercator.h
index 69c6ac2..0ebbff4 100644
--- a/dotnet/NETGeographicLib/TransverseMercator.h
+++ b/dotnet/NETGeographicLib/TransverseMercator.h
@@ -119,8 +119,7 @@ namespace NETGeographicLib
          * @param[out] k scale of projection at point.
          *
          * No false easting or northing is added. \e lat should be in the range
-         * [−90°, 90°]; \e lon and \e lon0 should be in the
-         * range [−540°, 540°).
+         * [−90°, 90°].
          **********************************************************************/
         void Forward(double lon0, double lat, double lon,
                      [System::Runtime::InteropServices::Out] double% x,
@@ -139,9 +138,8 @@ namespace NETGeographicLib
          * @param[out] gamma meridian convergence at point (degrees).
          * @param[out] k scale of projection at point.
          *
-         * No false easting or northing is added.  \e lon0 should be in the range
-         * [−540°, 540°).  The value of \e lon returned is in
-         * the range [−180°, 180°).
+         * No false easting or northing is added.  The value of \e lon returned
+         * is in the range [−180°, 180°).
          **********************************************************************/
         void Reverse(double lon0, double x, double y,
                      [System::Runtime::InteropServices::Out] double% lat,
diff --git a/dotnet/NETGeographicLib/TransverseMercatorExact.h b/dotnet/NETGeographicLib/TransverseMercatorExact.h
index 7322675..5175948 100644
--- a/dotnet/NETGeographicLib/TransverseMercatorExact.h
+++ b/dotnet/NETGeographicLib/TransverseMercatorExact.h
@@ -165,8 +165,7 @@ namespace NETGeographicLib
          * @param[out] k scale of projection at point.
          *
          * No false easting or northing is added. \e lat should be in the range
-         * [−90°, 90°]; \e lon and \e lon0 should be in the
-         * range [−540°, 540°).
+         * [−90°, 90°].
          **********************************************************************/
         void Forward(double lon0, double lat, double lon,
                      [System::Runtime::InteropServices::Out] double% x,
@@ -185,9 +184,8 @@ namespace NETGeographicLib
          * @param[out] gamma meridian convergence at point (degrees).
          * @param[out] k scale of projection at point.
          *
-         * No false easting or northing is added.  \e lon0 should be in the range
-         * [−540°, 540°).  The value of \e lon returned is in
-         * the range [−180°, 180°).
+         * No false easting or northing is added.  The value of \e lon returned
+         * is in the range [−180°, 180°).
          **********************************************************************/
         void Reverse(double lon0, double x, double y,
                      [System::Runtime::InteropServices::Out] double% lat,
diff --git a/dotnet/NETGeographicLib/UTMUPS.h b/dotnet/NETGeographicLib/UTMUPS.h
index 8a0f6fa..c8af9dc 100644
--- a/dotnet/NETGeographicLib/UTMUPS.h
+++ b/dotnet/NETGeographicLib/UTMUPS.h
@@ -166,8 +166,6 @@ namespace NETGeographicLib
          *   coordinates (default = false).
          * @exception GeographicErr if \e lat is not in [−90°,
          *   90°].
-         * @exception GeographicErr if \e lon is not in [−540°,
-         *   540°).
          * @exception GeographicErr if the resulting \e x or \e y is out of allowed
          *   range (see Reverse); in this case, these arguments are unchanged.
          *
diff --git a/dotnet/Projections/Form1.Designer.cs b/dotnet/Projections/Form1.Designer.cs
index fac84e9..f658b2a 100644
--- a/dotnet/Projections/Form1.Designer.cs
+++ b/dotnet/Projections/Form1.Designer.cs
@@ -276,4 +276,3 @@ namespace Projections
 
     }
 }
-
diff --git a/dotnet/Projections/MagneticPanel.cs b/dotnet/Projections/MagneticPanel.cs
index 6531265..c51e836 100644
--- a/dotnet/Projections/MagneticPanel.cs
+++ b/dotnet/Projections/MagneticPanel.cs
@@ -134,6 +134,9 @@ namespace Projections
                 if (bx != x || by != y || bz != z )
                     throw new Exception("Error in MagneticCircle.Field (2)");
 
+                double dtest = Utility.FractionalYear("2015.34");
+                dtest = Utility.FractionalYear("2015-07-31");
+
                 MessageBox.Show("No errors detected", "OK", MessageBoxButtons.OK, MessageBoxIcon.Information);
             }
             catch (Exception xcpt)
diff --git a/dotnet/Projections/MiscPanel.Designer.cs b/dotnet/Projections/MiscPanel.Designer.cs
index fda7666..4ee9fa5 100644
--- a/dotnet/Projections/MiscPanel.Designer.cs
+++ b/dotnet/Projections/MiscPanel.Designer.cs
@@ -39,11 +39,11 @@ namespace Projections
             this.m_LongitudeTextBox = new System.Windows.Forms.TextBox();
             this.m_latitudeTextBox = new System.Windows.Forms.TextBox();
             this.m_geohashTextBox = new System.Windows.Forms.TextBox();
-            this.label5 = new System.Windows.Forms.Label();
             this.button1 = new System.Windows.Forms.Button();
             this.button2 = new System.Windows.Forms.Button();
             this.button3 = new System.Windows.Forms.Button();
             this.button4 = new System.Windows.Forms.Button();
+            this.m_comboBox = new System.Windows.Forms.ComboBox();
             this.SuspendLayout();
             //
             // label1
@@ -117,15 +117,6 @@ namespace Projections
             this.m_geohashTextBox.Size = new System.Drawing.Size(155, 20);
             this.m_geohashTextBox.TabIndex = 8;
             //
-            // label5
-            //
-            this.label5.AutoSize = true;
-            this.label5.Location = new System.Drawing.Point(409, 4);
-            this.label5.Name = "label5";
-            this.label5.Size = new System.Drawing.Size(50, 13);
-            this.label5.TabIndex = 9;
-            this.label5.Text = "Geohash";
-            //
             // button1
             //
             this.button1.Location = new System.Drawing.Point(96, 83);
@@ -166,15 +157,29 @@ namespace Projections
             this.button4.UseVisualStyleBackColor = true;
             this.button4.Click += new System.EventHandler(this.OnValidate);
             //
+            // m_comboBox
+            //
+            this.m_comboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.m_comboBox.FormattingEnabled = true;
+            this.m_comboBox.Items.AddRange(new object[] {
+            "Geohash",
+            "GARS",
+            "Georef"});
+            this.m_comboBox.Location = new System.Drawing.Point(376, 4);
+            this.m_comboBox.Name = "m_comboBox";
+            this.m_comboBox.Size = new System.Drawing.Size(121, 21);
+            this.m_comboBox.TabIndex = 14;
+            this.m_toolTip.SetToolTip(this.m_comboBox, "Select the reference system");
+            //
             // MiscPanel
             //
             this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.Controls.Add(this.m_comboBox);
             this.Controls.Add(this.button4);
             this.Controls.Add(this.button3);
             this.Controls.Add(this.button2);
             this.Controls.Add(this.button1);
-            this.Controls.Add(this.label5);
             this.Controls.Add(this.m_geohashTextBox);
             this.Controls.Add(this.m_latitudeTextBox);
             this.Controls.Add(this.m_LongitudeTextBox);
@@ -203,10 +208,10 @@ namespace Projections
         private System.Windows.Forms.TextBox m_LongitudeTextBox;
         private System.Windows.Forms.TextBox m_latitudeTextBox;
         private System.Windows.Forms.TextBox m_geohashTextBox;
-        private System.Windows.Forms.Label label5;
         private System.Windows.Forms.Button button1;
         private System.Windows.Forms.Button button2;
         private System.Windows.Forms.Button button3;
         private System.Windows.Forms.Button button4;
+        private System.Windows.Forms.ComboBox m_comboBox;
     }
 }
diff --git a/dotnet/Projections/MiscPanel.cs b/dotnet/Projections/MiscPanel.cs
index 1a5385d..2b66bd1 100644
--- a/dotnet/Projections/MiscPanel.cs
+++ b/dotnet/Projections/MiscPanel.cs
@@ -25,6 +25,7 @@ namespace Projections
         public MiscPanel()
         {
             InitializeComponent();
+            m_comboBox.SelectedIndex = 0;
         }
 
         private void OnConvertDMS(object sender, EventArgs e)
@@ -55,7 +56,18 @@ namespace Projections
                 m_longitudeDMSTextBox.Text = DMS.Encode(lon, 5, DMS.Flag.LONGITUDE, 0);
                 m_latitudeDMSTextBox.Text = DMS.Encode(lat, 5, DMS.Flag.LATITUDE, 0);
                 string tmp = "";
-                Geohash.Forward(lat, lon, 12, out tmp);
+                switch (m_comboBox.SelectedIndex)
+                {
+                    case 0: // Geohash
+                        Geohash.Forward(lat, lon, 12, out tmp);
+                        break;
+                    case 1: // GARS
+                        GARS.Forward(lat, lon, 2, out tmp);
+                        break;
+                    case 2: // Georef
+                        Georef.Forward(lat, lon, 2, out tmp);
+                        break;
+                }
                 m_geohashTextBox.Text = tmp;
             }
             catch (Exception xcpt)
@@ -68,9 +80,20 @@ namespace Projections
         {
             try
             {
-                double lat, lon;
+                double lat = 0.0, lon = 0.0;
                 int len;
-                Geohash.Reverse(m_geohashTextBox.Text, out lat, out lon, out len, true);
+                switch (m_comboBox.SelectedIndex)
+                {
+                    case 0: // Geohash
+                        Geohash.Reverse(m_geohashTextBox.Text, out lat, out lon, out len, true);
+                        break;
+                    case 1: // GARS
+                        GARS.Reverse(m_geohashTextBox.Text, out lat, out lon, out len, true);
+                        break;
+                    case 2: // Georef
+                        Georef.Reverse(m_geohashTextBox.Text, out lat, out lon, out len, true);
+                        break;
+                }
                 m_LongitudeTextBox.Text = lon.ToString();
                 m_latitudeTextBox.Text = lat.ToString();
                 m_longitudeDMSTextBox.Text = DMS.Encode(lon, 5, DMS.Flag.LONGITUDE, 0);
@@ -106,6 +129,10 @@ namespace Projections
                 Geohash.LatitudeResolution(12);
                 Geohash.LongitudeResolution(12);
                 Geohash.Reverse("djds54mrfc0g", out lat, out lon, out len, true);
+                GARS.Forward(32.0, -86.0, 2, out tmp);
+                GARS.Reverse("189LE37", out lat, out lon, out len, true);
+                Georef.Forward(32.0, -86.0, 2, out tmp);
+                Georef.Reverse("GJEC0000", out lat, out lon, out len, true);
                 MessageBox.Show("No errors detected", "OK", MessageBoxButtons.OK, MessageBoxIcon.Information);
             }
             catch (Exception xcpt)
diff --git a/dotnet/Projections/Projections-vs13.csproj b/dotnet/Projections/Projections-vs13.csproj
index 2f6f330..5c2fa7f 100644
--- a/dotnet/Projections/Projections-vs13.csproj
+++ b/dotnet/Projections/Projections-vs13.csproj
@@ -256,7 +256,6 @@
     </ProjectReference>
   </ItemGroup>
   <ItemGroup>
-    <None Include="app.config" />
     <None Include="Properties\Settings.settings">
       <Generator>SettingsSingleFileGenerator</Generator>
       <LastGenOutput>Settings.Designer.cs</LastGenOutput>
diff --git a/dotnet/examples/CS/example-GARS.cs b/dotnet/examples/CS/example-GARS.cs
new file mode 100644
index 0000000..ac1783d
--- /dev/null
+++ b/dotnet/examples/CS/example-GARS.cs
@@ -0,0 +1,36 @@
+using System;
+using NETGeographicLib;
+
+namespace example_GARS
+{
+    class Program
+    {
+        static void Main(string[] args)
+        {
+            try {
+              {
+                // Sample forward calculation
+                double lat = 57.64911, lon = 10.40744; // Jutland
+                string gars;
+                for (int prec = 0; prec <= 2; ++prec) {
+                  GARS.Forward(lat, lon, prec, out gars);
+                  Console.WriteLine(String.Format("Precision: {0} GARS: {1}", prec, gars));
+                }
+              }
+              {
+                // Sample reverse calculation
+                string gars = "381NH45";
+                double lat, lon;
+                for (int len = 5; len <= gars.Length; ++len) {
+                  int prec;
+                  GARS.Reverse(gars.Substring(0, len), out lat, out lon, out prec, true);
+                  Console.WriteLine(String.Format("Precision: {0} Latitude: {1} Longitude {2}", prec, lat, lon));
+                }
+              }
+            }
+            catch (GeographicErr e) {
+              Console.WriteLine(String.Format("Caught Exception {0}", e.Message));
+            }
+        }
+    }
+}
diff --git a/dotnet/examples/CS/example-Georef.cs b/dotnet/examples/CS/example-Georef.cs
new file mode 100644
index 0000000..e730473
--- /dev/null
+++ b/dotnet/examples/CS/example-Georef.cs
@@ -0,0 +1,38 @@
+using System;
+using NETGeographicLib;
+
+namespace example_Georef
+{
+  class Program
+  {
+    static void Main(string[] args)
+    {
+      try {
+        {
+          // Sample forward calculation
+          double lat = 57.64911, lon = 10.40744; // Jutland
+          string georef;
+          for (int prec = -1; prec <= 11; ++prec) {
+            Georef.Forward(lat, lon, prec, out georef);
+            Console.WriteLine(String.Format("Precision: {0} Georef: {1}", prec, georef));
+          }
+        }
+        {
+          // Sample reverse calculation
+          string georef = "NKLN2444638946";
+          double lat, lon;
+          int prec;
+          Georef.Reverse(georef.Substring(0, 2), out lat, out lon, out prec, true);
+          Console.WriteLine(String.Format("Precision: {0} Latitude: {1} Longitude: {2}", prec, lat, lon));
+          Georef.Reverse(georef.Substring(0, 4), out lat, out lon, out prec, true);
+          Console.WriteLine(String.Format("Precision: {0} Latitude: {1} Longitude: {2}", prec, lat, lon));
+          Georef.Reverse(georef, out lat, out lon, out prec, true);
+          Console.WriteLine(String.Format("Precision: {0} Latitude: {1} Longitude: {2}", prec, lat, lon));
+        }
+      }
+      catch (GeographicErr e) {
+        Console.WriteLine(String.Format("Caught Exception {0}", e.Message));
+      }
+    }
+  }
+}
diff --git a/dotnet/examples/ManagedCPP/example-GARS.cpp b/dotnet/examples/ManagedCPP/example-GARS.cpp
new file mode 100644
index 0000000..5c08e57
--- /dev/null
+++ b/dotnet/examples/ManagedCPP/example-GARS.cpp
@@ -0,0 +1,32 @@
+using namespace System;
+using namespace NETGeographicLib;
+
+int main(array<System::String ^> ^/*args*/)
+{
+  try {
+    {
+      // Sample forward calculation
+      double lat = 57.64911, lon = 10.40744; // Jutland
+      String^ gars;
+      for (int prec = 0; prec <= 2; ++prec) {
+        GARS::Forward(lat, lon, prec, gars);
+        Console::WriteLine(String::Format("Precision: {0} GARS: {1}", prec, gars));
+      }
+    }
+    {
+      // Sample reverse calculation
+      String^ gars = gcnew String("381NH45");
+      double lat, lon;
+      for (int len = 5; len <= gars->Length; ++len) {
+        int prec;
+        GARS::Reverse(gars->Substring(0, len), lat, lon, prec, true);
+        Console::WriteLine(String::Format("Precision: {0} Latitude: {1} Longitude {2}", prec, lat, lon));
+      }
+    }
+  }
+  catch (GeographicErr^ e) {
+    Console::WriteLine(String::Format("Caught Exception {0}", e->Message));
+    return 1;
+  }
+  return 0;
+}
diff --git a/dotnet/examples/ManagedCPP/example-Georef.cpp b/dotnet/examples/ManagedCPP/example-Georef.cpp
new file mode 100644
index 0000000..ede3272
--- /dev/null
+++ b/dotnet/examples/ManagedCPP/example-Georef.cpp
@@ -0,0 +1,34 @@
+using namespace System;
+using namespace NETGeographicLib;
+
+int main(array<System::String ^> ^/*args*/)
+{
+  try {
+    {
+      // Sample forward calculation
+      double lat = 57.64911, lon = 10.40744; // Jutland
+      String^ georef;
+      for (int prec = -1; prec <= 11; ++prec) {
+        Georef::Forward(lat, lon, prec, georef);
+        Console::WriteLine(String::Format("Precision: {0} Georef: {1}", prec, georef));
+      }
+    }
+    {
+      // Sample reverse calculation
+      String^ georef = gcnew String("NKLN2444638946");
+      double lat, lon;
+      int prec;
+      Georef::Reverse(georef->Substring(0, 2), lat, lon, prec, true);
+      Console::WriteLine(String::Format("Precision: {0} Latitude: {1} Longitude: {2}", prec, lat, lon));
+      Georef::Reverse(georef->Substring(0, 4), lat, lon, prec, true);
+      Console::WriteLine(String::Format("Precision: {0} Latitude: {1} Longitude: {2}", prec, lat, lon));
+      Georef::Reverse(georef, lat, lon, prec, true);
+      Console::WriteLine(String::Format("Precision: {0} Latitude: {1} Longitude: {2}", prec, lat, lon));
+    }
+  }
+  catch (GeographicErr^ e) {
+    Console::WriteLine(String::Format("Caught Exception {0}", e->Message));
+    return 1;
+  }
+  return 0;
+}
diff --git a/dotnet/examples/VB/example-GARS.vb b/dotnet/examples/VB/example-GARS.vb
new file mode 100644
index 0000000..88da552
--- /dev/null
+++ b/dotnet/examples/VB/example-GARS.vb
@@ -0,0 +1,23 @@
+Imports NETGeographicLib
+Module example_GARS
+    Sub Main()
+        Try
+            ' Sample forward calculation
+            Dim lat As Double = 57.64911, lon = 10.40744
+            Dim garstring As String
+            For prec As Integer = 0 To 2
+                GARS.Forward(lat, lon, prec, garstring)
+                Console.WriteLine(String.Format("Precision: {0} GARS: {1}", prec, garstring))
+            Next
+            ' Sample reverse calculation
+            garstring = "381NH45"
+            For len As Integer = 5 To garstring.Length
+                Dim prec As Integer
+                GARS.Reverse(garstring.Substring(0, len), lat, lon, prec, True)
+                Console.WriteLine(String.Format("Precision: {0} Latitude: {1} Longitude {2}", prec, lat, lon))
+            Next
+        Catch ex As GeographicErr
+            Console.WriteLine(String.Format("Caught Exception {0}", ex.Message))
+        End Try
+    End Sub
+End Module
diff --git a/dotnet/examples/VB/example-Georef.vb b/dotnet/examples/VB/example-Georef.vb
new file mode 100644
index 0000000..d6f7454
--- /dev/null
+++ b/dotnet/examples/VB/example-Georef.vb
@@ -0,0 +1,25 @@
+Imports NETGeographicLib
+Module example_Georef
+    Sub Main()
+        Try
+            ' Sample forward calculation
+            Dim lat As Double = 57.64911, lon = 10.40744 ' Jutland
+            Dim georefstring As String
+            For prec1 As Integer = -1 To 11
+                Georef.Forward(lat, lon, prec1, georefstring)
+                Console.WriteLine(String.Format("Precision: {0} Georef: {1}", prec1, georefstring))
+            Next
+            ' Sample reverse calculation
+            georefstring = "NKLN2444638946"
+            Dim prec As Integer
+            Georef.Reverse(georefstring.Substring(0, 2), lat, lon, prec, True)
+            Console.WriteLine(String.Format("Precision: {0} Latitude: {1} Longitude: {2}", prec, lat, lon))
+            Georef.Reverse(georefstring.Substring(0, 4), lat, lon, prec, True)
+            Console.WriteLine(String.Format("Precision: {0} Latitude: {1} Longitude: {2}", prec, lat, lon))
+            Georef.Reverse(georefstring, lat, lon, prec, True)
+            Console.WriteLine(String.Format("Precision: {0} Latitude: {1} Longitude: {2}", prec, lat, lon))
+        Catch ex As GeographicErr
+            Console.WriteLine(String.Format("Caught Exception {0}", ex.Message))
+        End Try
+    End Sub
+End Module
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index 4676cad..df97f27 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -29,13 +29,10 @@ find_package (OpenMP QUIET)
 
 if (OPENMP_FOUND)
   set_target_properties (GeoidToGTX PROPERTIES
-    COMPILE_FLAGS ${OpenMP_CXX_FLAGS} COMPILE_DEFINITIONS HAVE_OPENMP=1)
+    COMPILE_FLAGS ${OpenMP_CXX_FLAGS})
   if (NOT WIN32)
     set_target_properties (GeoidToGTX PROPERTIES LINK_FLAGS ${OpenMP_CXX_FLAGS})
   endif ()
-  message (STATUS "Example program GeoidToGTX will use OpenMP")
-else ()
-  message (STATUS "Example program GeoidToGTX will not use OpenMP")
 endif ()
 
 add_custom_target (exampleprograms DEPENDS ${EXAMPLES})
diff --git a/examples/GeoidToGTX.cpp b/examples/GeoidToGTX.cpp
index 5d168eb..d9ca6bf 100644
--- a/examples/GeoidToGTX.cpp
+++ b/examples/GeoidToGTX.cpp
@@ -1,6 +1,6 @@
 // Write out a gtx file of geoid heights above the ellipsoid.  For egm2008 at
 // 1' resolution this takes about 40 mins on a 8-processor Intel 2.66 GHz
-// machine using OpenMP (-DHAVE_OPENMP=1).
+// machine using OpenMP.
 //
 // For the format of gtx files, see
 // http://vdatum.noaa.gov/dev/gtx_info.html#dev_gtx_binary
@@ -20,6 +20,12 @@
 #include <string>
 #include <algorithm>
 
+#if defined(_OPENMP)
+#define HAVE_OPENMP 1
+#else
+#define HAVE_OPENMP 0
+#endif
+
 #if HAVE_OPENMP
 #  include <omp.h>
 #endif
diff --git a/examples/JacobiConformal.hpp b/examples/JacobiConformal.hpp
index 90e4809..7c83b22 100644
--- a/examples/JacobiConformal.hpp
+++ b/examples/JacobiConformal.hpp
@@ -127,11 +127,8 @@ namespace GeographicLib {
      * ω must be in (−180°, 180°].
      **********************************************************************/
     Math::real x(real omg) const {
-      using std::abs; using std::sin; using std::cos;
-      real
-        a = omg * Math::degree(),
-        somg = abs(omg) == 180 ? 0 : sin(a),
-        comg = abs(omg) ==  90 ? 0 : cos(a);
+      real somg, comg;
+      Math::sincosd(omg, somg, comg);
       return x(somg, comg) / Math::degree();
     }
     /**
@@ -159,11 +156,8 @@ namespace GeographicLib {
      * β must be in (−180°, 180°].
      **********************************************************************/
     Math::real y(real bet) const {
-      using std::abs; using std::sin; using std::cos;
-      real
-        a = bet * Math::degree(),
-        sbet = abs(bet) == 180 ? 0 : sin(a),
-        cbet = abs(bet) ==  90 ? 0 : cos(a);
+      real sbet, cbet;
+      Math::sincosd(bet, sbet, cbet);
       return y(sbet, cbet) / Math::degree();
     }
   };
diff --git a/examples/Makefile.am b/examples/Makefile.am
index 331dad6..2009c06 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -13,6 +13,7 @@ EXAMPLE_FILES = \
 	example-DMS.cpp \
 	example-Ellipsoid.cpp \
 	example-EllipticFunction.cpp \
+	example-GARS.cpp \
 	example-GeoCoords.cpp \
 	example-Geocentric.cpp \
 	example-Geodesic.cpp \
@@ -23,6 +24,7 @@ EXAMPLE_FILES = \
 	example-GeographicErr.cpp \
 	example-Geohash.cpp \
 	example-Geoid.cpp \
+	example-Georef.cpp \
 	example-Gnomonic.cpp \
 	example-GravityCircle.cpp \
 	example-GravityModel.cpp \
diff --git a/examples/Makefile.in b/examples/Makefile.in
index eb83649..7a15158 100644
--- a/examples/Makefile.in
+++ b/examples/Makefile.in
@@ -261,6 +261,7 @@ EXAMPLE_FILES = \
 	example-DMS.cpp \
 	example-Ellipsoid.cpp \
 	example-EllipticFunction.cpp \
+	example-GARS.cpp \
 	example-GeoCoords.cpp \
 	example-Geocentric.cpp \
 	example-Geodesic.cpp \
@@ -271,6 +272,7 @@ EXAMPLE_FILES = \
 	example-GeographicErr.cpp \
 	example-Geohash.cpp \
 	example-Geoid.cpp \
+	example-Georef.cpp \
 	example-Gnomonic.cpp \
 	example-GravityCircle.cpp \
 	example-GravityModel.cpp \
diff --git a/examples/example-GARS.cpp b/examples/example-GARS.cpp
new file mode 100644
index 0000000..4fd7dd9
--- /dev/null
+++ b/examples/example-GARS.cpp
@@ -0,0 +1,40 @@
+// Example of using the GeographicLib::GARS class
+
+#include <iostream>
+#include <iomanip>
+#include <exception>
+#include <string>
+#include <GeographicLib/GARS.hpp>
+
+using namespace std;
+using namespace GeographicLib;
+
+int main() {
+  try {
+    {
+      // Sample forward calculation
+      double lat = 57.64911, lon = 10.40744; // Jutland
+      string gars;
+      for (int prec = 0; prec <= 2; ++prec) {
+        GARS::Forward(lat, lon, prec, gars);
+        cout << prec << " " << gars << "\n";
+      }
+    }
+    {
+      // Sample reverse calculation
+      string gars = "381NH45";
+      double lat, lon;
+      cout << fixed;
+      for (int len = 5; len <= int(gars.size()); ++len) {
+        int prec;
+        GARS::Reverse(gars.substr(0, len), lat, lon, prec);
+        cout << prec << " " << lat << " " << lon << "\n";
+      }
+    }
+  }
+  catch (const exception& e) {
+    cerr << "Caught exception: " << e.what() << "\n";
+    return 1;
+  }
+  return 0;
+}
diff --git a/examples/example-Georef.cpp b/examples/example-Georef.cpp
new file mode 100644
index 0000000..4c050f8
--- /dev/null
+++ b/examples/example-Georef.cpp
@@ -0,0 +1,42 @@
+// Example of using the GeographicLib::GARS class
+
+#include <iostream>
+#include <iomanip>
+#include <exception>
+#include <string>
+#include <GeographicLib/Georef.hpp>
+
+using namespace std;
+using namespace GeographicLib;
+
+int main() {
+  try {
+    {
+      // Sample forward calculation
+      double lat = 57.64911, lon = 10.40744; // Jutland
+      string georef;
+      for (int prec = -1; prec <= 11; ++prec) {
+        Georef::Forward(lat, lon, prec, georef);
+        cout << prec << " " << georef << "\n";
+      }
+    }
+    {
+      // Sample reverse calculation
+      string georef = "NKLN2444638946";
+      double lat, lon;
+      int prec;
+      cout << fixed;
+      Georef::Reverse(georef.substr(0, 2), lat, lon, prec);
+      cout << prec << " " << lat << " " << lon << "\n";
+      Georef::Reverse(georef.substr(0, 4), lat, lon, prec);
+      cout << prec << " " << lat << " " << lon << "\n";
+      Georef::Reverse(georef, lat, lon, prec);
+      cout << prec << " " << lat << " " << lon << "\n";
+    }
+  }
+  catch (const exception& e) {
+    cerr << "Caught exception: " << e.what() << "\n";
+    return 1;
+  }
+  return 0;
+}
diff --git a/include/GeographicLib/Accumulator.hpp b/include/GeographicLib/Accumulator.hpp
index 492dc4f..b90f410 100644
--- a/include/GeographicLib/Accumulator.hpp
+++ b/include/GeographicLib/Accumulator.hpp
@@ -2,7 +2,7 @@
  * \file Accumulator.hpp
  * \brief Header for GeographicLib::Accumulator class
  *
- * Copyright (c) Charles Karney (2010-2011) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2010-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -142,6 +142,18 @@ namespace GeographicLib {
      **********************************************************************/
     Accumulator& operator*=(int n) { _s *= n; _t *= n; return *this; }
     /**
+     * Multiply accumulator by a number.  The fma (fused multiply and add)
+     * instruction is used (if available) in order to maintain accuracy.
+     *
+     * @param[in] y set \e sum *= \e y.
+     **********************************************************************/
+    Accumulator& operator*=(T y) {
+      T d = _s; _s *= y;
+      d = Math::fma(y, d, -_s); // the error in the first multiplication
+      _t = Math::fma(y, _t, d); // add error to the second term
+      return *this;
+    }
+    /**
      * Test equality of an Accumulator with a number.
      **********************************************************************/
     bool operator==(T y) const { return _s == y; }
diff --git a/include/GeographicLib/AlbersEqualArea.hpp b/include/GeographicLib/AlbersEqualArea.hpp
index db12abc..b4ca0fb 100644
--- a/include/GeographicLib/AlbersEqualArea.hpp
+++ b/include/GeographicLib/AlbersEqualArea.hpp
@@ -2,7 +2,7 @@
  * \file AlbersEqualArea.hpp
  * \brief Header for GeographicLib::AlbersEqualArea class
  *
- * Copyright (c) Charles Karney (2010-2014) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2010-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -209,10 +209,9 @@ namespace GeographicLib {
      *
      * The latitude origin is given by AlbersEqualArea::LatitudeOrigin().  No
      * false easting or northing is added and \e lat should be in the range
-     * [−90°, 90°]; \e lon and \e lon0 should be in the
-     * range [−540°, 540°).  The values of \e x and \e y
-     * returned for points which project to infinity (i.e., one or both of the
-     * poles) will be large but finite.
+     * [−90°, 90°].  The values of \e x and \e y returned for
+     * points which project to infinity (i.e., one or both of the poles) will
+     * be large but finite.
      **********************************************************************/
     void Forward(real lon0, real lat, real lon,
                  real& x, real& y, real& gamma, real& k) const;
@@ -230,12 +229,10 @@ namespace GeographicLib {
      *   scale is the 1/\e k.
      *
      * The latitude origin is given by AlbersEqualArea::LatitudeOrigin().  No
-     * false easting or northing is added.  \e lon0 should be in the range
-     * [−540°, 540°).  The value of \e lon returned is in
-     * the range [−180°, 180°).  The value of \e lat
-     * returned is in the range [−90°, 90°].  If the
-     * input point is outside the legal projected space the nearest pole is
-     * returned.
+     * false easting or northing is added.  The value of \e lon returned is in
+     * the range [−180°, 180°).  The value of \e lat returned is
+     * in the range [−90°, 90°].  If the input point is outside
+     * the legal projected space the nearest pole is returned.
      **********************************************************************/
     void Reverse(real lon0, real x, real y,
                  real& lat, real& lon, real& gamma, real& k) const;
diff --git a/include/GeographicLib/AzimuthalEquidistant.hpp b/include/GeographicLib/AzimuthalEquidistant.hpp
index 7929050..8f42900 100644
--- a/include/GeographicLib/AzimuthalEquidistant.hpp
+++ b/include/GeographicLib/AzimuthalEquidistant.hpp
@@ -2,7 +2,7 @@
  * \file AzimuthalEquidistant.hpp
  * \brief Header for GeographicLib::AzimuthalEquidistant class
  *
- * Copyright (c) Charles Karney (2009-2011) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2009-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -66,13 +66,11 @@ namespace GeographicLib {
      * @param[out] azi azimuth of geodesic at point (degrees).
      * @param[out] rk reciprocal of azimuthal scale at point.
      *
-     * \e lat0 and \e lat should be in the range [−90°,
-     * 90°] and \e lon0 and \e lon should be in the range
-     * [−540°, 540°).  The scale of the projection is 1
-     * in the "radial" direction, \e azi clockwise from true north, and is 1/\e
-     * rk in the direction perpendicular to this.  A call to Forward followed
-     * by a call to Reverse will return the original (\e lat, \e lon) (to
-     * within roundoff).
+     * \e lat0 and \e lat should be in the range [−90°, 90°].
+     * The scale of the projection is 1 in the "radial" direction, \e azi
+     * clockwise from true north, and is 1/\e rk in the direction perpendicular
+     * to this.  A call to Forward followed by a call to Reverse will return
+     * the original (\e lat, \e lon) (to within roundoff).
      **********************************************************************/
     void Forward(real lat0, real lon0, real lat, real lon,
                  real& x, real& y, real& azi, real& rk) const;
@@ -89,15 +87,13 @@ namespace GeographicLib {
      * @param[out] azi azimuth of geodesic at point (degrees).
      * @param[out] rk reciprocal of azimuthal scale at point.
      *
-     * \e lat0 should be in the range [−90°, 90°] and \e
-     * lon0 should be in the range [−540°, 540°).  \e lat
-     * will be in the range [−90°, 90°] and \e lon will
-     * be in the range [−180°, 180°).  The scale of the
-     * projection is 1 in the "radial" direction, \e azi clockwise from true
-     * north, and is 1/\e rk in the direction perpendicular to this.  A call to
-     * Reverse followed by a call to Forward will return the original (\e x, \e
-     * y) (to roundoff) only if the geodesic to (\e x, \e y) is a shortest
-     * path.
+     * \e lat0 should be in the range [−90°, 90°].  \e lat will
+     * be in the range [−90°, 90°] and \e lon will be in the
+     * range [−180°, 180°).  The scale of the projection is 1 in
+     * the "radial" direction, \e azi clockwise from true north, and is 1/\e rk
+     * in the direction perpendicular to this.  A call to Reverse followed by a
+     * call to Forward will return the original (\e x, \e y) (to roundoff) only
+     * if the geodesic to (\e x, \e y) is a shortest path.
      **********************************************************************/
     void Reverse(real lat0, real lon0, real x, real y,
                  real& lat, real& lon, real& azi, real& rk) const;
diff --git a/include/GeographicLib/CassiniSoldner.hpp b/include/GeographicLib/CassiniSoldner.hpp
index fe25740..011bc21 100644
--- a/include/GeographicLib/CassiniSoldner.hpp
+++ b/include/GeographicLib/CassiniSoldner.hpp
@@ -69,7 +69,6 @@ namespace GeographicLib {
   class GEOGRAPHICLIB_EXPORT CassiniSoldner {
   private:
     typedef Math::real real;
-    real eps1_, tiny_;
     Geodesic _earth;
     GeodesicLine _meridian;
     real _sbet0, _cbet0;
@@ -96,8 +95,7 @@ namespace GeographicLib {
      * @param[in] earth the Geodesic object to use for geodesic calculations.
      *   By default this uses the WGS84 ellipsoid.
      *
-     * \e lat0 should be in the range [−90°, 90°] and \e
-     * lon0 should be in the range [−540°, 540°).
+     * \e lat0 should be in the range [−90°, 90°].
      **********************************************************************/
     CassiniSoldner(real lat0, real lon0,
                    const Geodesic& earth = Geodesic::WGS84());
@@ -108,8 +106,7 @@ namespace GeographicLib {
      * @param[in] lat0 latitude of center point of projection (degrees).
      * @param[in] lon0 longitude of center point of projection (degrees).
      *
-     * \e lat0 should be in the range [−90°, 90°] and \e
-     * lon0 should be in the range [−540°, 540°).
+     * \e lat0 should be in the range [−90°, 90°].
      **********************************************************************/
     void Reset(real lat0, real lon0);
 
@@ -123,11 +120,10 @@ namespace GeographicLib {
      * @param[out] azi azimuth of easting direction at point (degrees).
      * @param[out] rk reciprocal of azimuthal northing scale at point.
      *
-     * \e lat should be in the range [−90°, 90°] and \e
-     * lon should be in the range [−540°, 540°).  A call
-     * to Forward followed by a call to Reverse will return the original (\e
-     * lat, \e lon) (to within roundoff).  The routine does nothing if the
-     * origin has not been set.
+     * \e lat should be in the range [−90°, 90°].  A call to
+     * Forward followed by a call to Reverse will return the original (\e lat,
+     * \e lon) (to within roundoff).  The routine does nothing if the origin
+     * has not been set.
      **********************************************************************/
     void Forward(real lat, real lon,
                  real& x, real& y, real& azi, real& rk) const;
diff --git a/include/GeographicLib/CircularEngine.hpp b/include/GeographicLib/CircularEngine.hpp
index 060ebe6..b3e0ea9 100644
--- a/include/GeographicLib/CircularEngine.hpp
+++ b/include/GeographicLib/CircularEngine.hpp
@@ -2,8 +2,8 @@
  * \file CircularEngine.hpp
  * \brief Header for GeographicLib::CircularEngine class
  *
- * Copyright (c) Charles Karney (2011) <charles at karney.com> and licensed under
- * the MIT/X11 License.  For more information, see
+ * Copyright (c) Charles Karney (2011-2015) <charles at karney.com> and licensed
+ * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
 
@@ -66,17 +66,7 @@ namespace GeographicLib {
     Math::real Value(bool gradp, real cl, real sl,
                      real& gradx, real& grady, real& gradz) const;
 
-    static inline void cossin(real x, real& cosx, real& sinx) {
-      using std::abs; using std::cos; using std::sin;
-      x = x >= 180 ? x - 360 : (x < -180 ? x + 360 : x);
-      real xi = x * Math::degree();
-      cosx = abs(x) ==   90 ? 0 : cos(xi);
-      sinx =     x  == -180 ? 0 : sin(xi);
-    }
-
     friend class SphericalEngine;
-    friend class GravityCircle;  // Access to cossin
-    friend class MagneticCircle; // Access to cossin
     CircularEngine(int M, bool gradp, unsigned norm,
                    real a, real r, real u, real t)
       : _M(M)
@@ -148,7 +138,7 @@ namespace GeographicLib {
      **********************************************************************/
     Math::real operator()(real lon) const {
       real coslon, sinlon;
-      cossin(lon, coslon, sinlon);
+      Math::sincosd(lon, sinlon, coslon);
       return (*this)(coslon, sinlon);
     }
 
@@ -191,7 +181,7 @@ namespace GeographicLib {
     Math::real operator()(real lon,
                           real& gradx, real& grady, real& gradz) const {
       real coslon, sinlon;
-      cossin(lon, coslon, sinlon);
+      Math::sincosd(lon, sinlon, coslon);
       return (*this)(coslon, sinlon, gradx, grady, gradz);
     }
   };
diff --git a/include/GeographicLib/Config.h b/include/GeographicLib/Config.h
index 7a6dfc7..ca5f29c 100644
--- a/include/GeographicLib/Config.h
+++ b/include/GeographicLib/Config.h
@@ -1,8 +1,8 @@
 // This will be overwritten by ./configure
 
-#define GEOGRAPHICLIB_VERSION_STRING "1.43"
+#define GEOGRAPHICLIB_VERSION_STRING "1.44"
 #define GEOGRAPHICLIB_VERSION_MAJOR 1
-#define GEOGRAPHICLIB_VERSION_MINOR 43
+#define GEOGRAPHICLIB_VERSION_MINOR 44
 #define GEOGRAPHICLIB_VERSION_PATCH 0
 
 // Undefine HAVE_LONG_DOUBLE if this type is unknown to the compiler
diff --git a/include/GeographicLib/Constants.hpp b/include/GeographicLib/Constants.hpp
index 1db512e..e515858 100644
--- a/include/GeographicLib/Constants.hpp
+++ b/include/GeographicLib/Constants.hpp
@@ -2,7 +2,7 @@
  * \file Constants.hpp
  * \brief Header for GeographicLib::Constants class
  *
- * Copyright (c) Charles Karney (2008-2011) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2008-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -150,8 +150,12 @@ namespace GeographicLib {
      * @tparam T the type of the returned value.
      * @return the flattening of WGS84 ellipsoid (1/298.257223563).
      **********************************************************************/
-    template<typename T> static inline T WGS84_f()
-    { return 1 / ( T(298257223563LL) / 1000000000 ); }
+    template<typename T> static inline T WGS84_f() {
+      // Evaluating this as 1000000000 / T(298257223563LL) reduces the
+      // round-off error by about 10%.  However, expressing the flattening as
+      // 1/298.257223563 is well ingrained.
+      return 1 / ( T(298257223563LL) / 1000000000 );
+    }
     /**
      * A synonym for WGS84_f<real>().
      **********************************************************************/
diff --git a/include/GeographicLib/DMS.hpp b/include/GeographicLib/DMS.hpp
index 72ef801..0043cbd 100644
--- a/include/GeographicLib/DMS.hpp
+++ b/include/GeographicLib/DMS.hpp
@@ -147,24 +147,34 @@ namespace GeographicLib {
      *     N-20d30'40.5", -20:30:40.5
      *   - 4d0'9, 4d9", 4d9'', 4:0:9, 004:00:09, 4.0025, 4.0025d, 4d0.15,
      *     04:.15
+     *   - 4:59.99999999999999, 4:60.0, 4:59:59.9999999999999, 4:59:60.0, 5
      * - <i>ILLEGAL</i> (the exception thrown explains the problem)
      *   - 4d5"4', 4::5, 4:5:, :4:5, 4d4.5'4", -N20.5, 1.8e2d, 4:60,
-     *     4d-5'
+     *     4:59:60
      *
-     * The decoding operation can also perform a single addition or subtraction
-     * operation.  If the string includes an <i>internal</i> sign (i.e., not at
+     * The decoding operation can also perform addition and subtraction
+     * operations.  If the string includes <i>internal</i> signs (i.e., not at
      * the beginning nor immediately after an initial hemisphere designator),
-     * then the string is split immediately before that sign and each half is
-     * decoded according to the above rules and the results added.  The second
-     * half can include a hemisphere designator, but it must come at the end (a
-     * hemisphere designator is not allowed after the initial sign).  If both
-     * halves include hemisphere designators then these must compatible; e.g.,
-     * you cannot mix N and E.  Examples of legal and illegal combinations are
+     * then the string is split immediately before such signs and each piece is
+     * decoded according to the above rules and the results added; thus
+     * <code>S3-2.5+4.1N</code> is parsed as the sum of <code>S3</code>,
+     * <code>-2.5</code>, <code>+4.1N</code>.  Any piece can include a
+     * hemisphere designator; however, if multiple designators are given, they
+     * must compatible; e.g., you cannot mix N and E.  In addition, the
+     * designator can appear at the beginning or end of the first piece, but
+     * must be at the end of all subsequent pieces (a hemisphere designator is
+     * not allowed after the initial sign).  Examples of legal and illegal
+     * combinations are
      * - <i>LEGAL</i> (these are all equivalent)
      *   - 070:00:45, 70:01:15W+0:0.5, 70:01:15W-0:0:30W, W70:01:15+0:0:30E
      * - <i>ILLEGAL</i> (the exception thrown explains the problem)
      *   - 70:01:15W+0:0:15N, W70:01:15+W0:0:15
      *
+     * <b>WARNING:</b> "Exponential" notation is not recognized.  Thus
+     * <code>7.0E1</code> is illegal, while <code>7.0E+1</code> is parsed as
+     * <code>(7.0E) + (+1)</code>, yielding the same result as
+     * <code>8.0E</code>.
+     *
      * <b>NOTE:</b> At present, all the string handling in the C++
      * implementation %GeographicLib is with 8-bit characters.  The support for
      * unicode symbols for degrees, minutes, and seconds is therefore via the
@@ -245,7 +255,7 @@ namespace GeographicLib {
      * @param[in] dmsb second string.
      * @param[out] lat latitude (degrees).
      * @param[out] lon longitude (degrees).
-     * @param[in] swaplatlong if true assume longitude is given before latitude
+     * @param[in] longfirst if true assume longitude is given before latitude
      *   in the absence of hemisphere designators (default false).
      * @exception GeographicErr if \e dmsa or \e dmsb is malformed.
      * @exception GeographicErr if \e dmsa and \e dmsb are both interpreted as
@@ -254,8 +264,6 @@ namespace GeographicLib {
      *   longitudes.
      * @exception GeographicErr if decoded latitude is not in [−90°,
      *   90°].
-     * @exception GeographicErr if decoded longitude is not in
-     *   [−540°, 540°).
      *
      * By default, the \e lat (resp., \e lon) is assigned to the results of
      * decoding \e dmsa (resp., \e dmsb).  However this is overridden if either
@@ -265,7 +273,7 @@ namespace GeographicLib {
      **********************************************************************/
     static void DecodeLatLon(const std::string& dmsa, const std::string& dmsb,
                              real& lat, real& lon,
-                             bool swaplatlong = false);
+                             bool longfirst = false);
 
     /**
      * Convert a string to an angle in degrees.
@@ -286,8 +294,6 @@ namespace GeographicLib {
      * @param[in] azistr input string.
      * @exception GeographicErr if \e azistr is malformed.
      * @exception GeographicErr if \e azistr includes a N/S designator.
-     * @exception GeographicErr if decoded azimuth is not in
-     *   [−540°, 540°).
      * @return azimuth (degrees) reduced to the range [−180°,
      *   180°).
      *
diff --git a/include/GeographicLib/Ellipsoid.hpp b/include/GeographicLib/Ellipsoid.hpp
index 3e103c0..9b16d49 100644
--- a/include/GeographicLib/Ellipsoid.hpp
+++ b/include/GeographicLib/Ellipsoid.hpp
@@ -396,9 +396,8 @@ namespace GeographicLib {
      *   section at latitude φ inclined at an angle \e azi to the
      *   meridian (meters).
      *
-     * φ must lie in the range [−90°, 90°] and \e
-     * azi must lie in the range [−540°, 540°); the
-     * result is undefined if either of conditions does not hold.
+     * φ must lie in the range [−90°, 90°]; the result is
+     * undefined this condition does not hold.
      **********************************************************************/
     Math::real NormalCurvatureRadius(real phi, real azi) const;
     ///@}
diff --git a/include/GeographicLib/GARS.hpp b/include/GeographicLib/GARS.hpp
new file mode 100644
index 0000000..a63420e
--- /dev/null
+++ b/include/GeographicLib/GARS.hpp
@@ -0,0 +1,143 @@
+/**
+ * \file GARS.hpp
+ * \brief Header for GeographicLib::GARS class
+ *
+ * Copyright (c) Charles Karney (2015) <charles at karney.com> and licensed under
+ * the MIT/X11 License.  For more information, see
+ * http://geographiclib.sourceforge.net/
+ **********************************************************************/
+
+#if !defined(GEOGRAPHICLIB_GARS_HPP)
+#define GEOGRAPHICLIB_GARS_HPP 1
+
+#include <GeographicLib/Constants.hpp>
+
+#if defined(_MSC_VER)
+// Squelch warnings about dll vs string
+#  pragma warning (push)
+#  pragma warning (disable: 4251)
+#endif
+
+namespace GeographicLib {
+
+  /**
+   * \brief Conversions for the Global Area Reference System (GARS)
+   *
+   * The Global Area Reference System is described in
+   * - https://en.wikipedia.org/wiki/Global_Area_Reference_System
+   * - http://earth-info.nga.mil/GandG/coordsys/grids/gars.html
+   * .
+   * It provides a compact string representation of a geographic area
+   * (expressed as latitude and longitude).  The classes Georef and Geohash
+   * implement similar compact representations.
+   *
+   * Example of use:
+   * \include example-GARS.cpp
+   **********************************************************************/
+
+  class GEOGRAPHICLIB_EXPORT GARS {
+  private:
+    typedef Math::real real;
+    static const std::string digits_;
+    static const std::string letters_;
+    enum {
+      lonorig_ = -180,          // Origin for longitude
+      latorig_ = -90,           // Origin for latitude
+      baselon_ = 10,            // Base for longitude tiles
+      baselat_ = 24,            // Base for latitude tiles
+      lonlen_ = 3,
+      latlen_ = 2,
+      baselen_ = lonlen_ + latlen_,
+      mult1_ = 2,               // base precision = 1/2 degree
+      mult2_ = 2,               // 6th char gives 2x more precision
+      mult3_ = 3,               // 7th char gives 3x more precision
+      m_ = mult1_ * mult2_ * mult3_,
+      maxprec_ = 2,
+      maxlen_ = baselen_ + maxprec_,
+    };
+    GARS();                     // Disable constructor
+
+  public:
+
+    /**
+     * Convert from geographic coordinates to GARS.
+     *
+     * @param[in] lat latitude of point (degrees).
+     * @param[in] lon longitude of point (degrees).
+     * @param[in] prec the precision of the resulting GARS.
+     * @param[out] gars the GARS string.
+     * @exception GeographicErr if \e lat is not in [−90°,
+     *   90°].
+     * @exception std::bad_alloc if memory for \e gars can't be allocated.
+     *
+     * \e prec specifies the precision of \e gars as follows:
+     * - \e prec = 0 (min), 30' precision, e.g., 006AG;
+     * - \e prec = 1, 15' precision, e.g., 006AG3;
+     * - \e prec = 2 (max), 5' precision, e.g., 006AG39.
+     *
+     * If \e lat or \e lon is NaN, then \e gars is set to "INVALID".
+     **********************************************************************/
+    static void Forward(real lat, real lon, int prec, std::string& gars);
+
+    /**
+     * Convert from GARS to geographic coordinates.
+     *
+     * @param[in] gars the GARS.
+     * @param[out] lat latitude of point (degrees).
+     * @param[out] lon longitude of point (degrees).
+     * @param[out] prec the precision of \e gars.
+     * @param[in] centerp if true (the default) return the center of the
+     *   \e gars, otherwise return the south-west corner.
+     * @exception GeographicErr if \e gars is illegal.
+     *
+     * The case of the letters in \e gars is ignored.  \e prec is in the range
+     * [0, 2] and gives the precision of \e gars as follows:
+     * - \e prec = 0 (min), 30' precision, e.g., 006AG;
+     * - \e prec = 1, 15' precision, e.g., 006AG3;
+     * - \e prec = 2 (max), 5' precision, e.g., 006AG39.
+     *
+     * If the first 3 characters of \e gars are "INV", then \e lat and \e lon
+     * are set to NaN and \e prec is unchanged.
+     **********************************************************************/
+    static void Reverse(const std::string& gars, real& lat, real& lon,
+                        int& prec, bool centerp = true);
+
+    /**
+     * The angular resolution of a GARS.
+     *
+     * @param[in] prec the precision of the GARS.
+     * @return the latitude-longitude resolution (degrees).
+     *
+     * Internally, \e prec is first put in the range [0, 2].
+     **********************************************************************/
+    static Math::real Resolution(int prec) {
+      return 1/real(prec <= 0 ? mult1_ : (prec == 1 ? mult1_ * mult2_ :
+                                          mult1_ * mult2_ * mult3_));
+    }
+
+    /**
+     * The GARS precision required to meet a given geographic resolution.
+     *
+     * @param[in] res the minimum of resolution in latitude and longitude
+     *   (degrees).
+     * @return GARS precision.
+     *
+     * The returned length is in the range [0, 2].
+     **********************************************************************/
+    static int Precision(real res) {
+      using std::abs; res = abs(res);
+      for (int prec = 0; prec < maxprec_; ++prec)
+        if (Resolution(prec) <= res)
+          return prec;
+      return maxprec_;
+    }
+
+  };
+
+} // namespace GeographicLib
+
+#if defined(_MSC_VER)
+#  pragma warning (pop)
+#endif
+
+#endif  // GEOGRAPHICLIB_GARS_HPP
diff --git a/include/GeographicLib/GeoCoords.hpp b/include/GeographicLib/GeoCoords.hpp
index 70106cc..720e2ab 100644
--- a/include/GeographicLib/GeoCoords.hpp
+++ b/include/GeographicLib/GeoCoords.hpp
@@ -2,7 +2,7 @@
  * \file GeoCoords.hpp
  * \brief Header for GeographicLib::GeoCoords class
  *
- * Copyright (c) Charles Karney (2008-2011) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2008-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -91,7 +91,7 @@ namespace GeographicLib {
      *   the position.
      * @param[in] centerp governs the interpretation of MGRS coordinates (see
      *   below).
-     * @param[in] swaplatlong governs the interpretation of geographic
+     * @param[in] longfirst governs the interpretation of geographic
      *   coordinates (see below).
      * @exception GeographicErr if the \e s is malformed (see below).
      *
@@ -119,9 +119,9 @@ namespace GeographicLib {
      *
      * <b>Latitude and Longitude parsing</b>: Latitude precedes longitude,
      * unless a N, S, E, W hemisphere designator is used on one or both
-     * coordinates.  If \e swaplatlong = true (default is false), then
+     * coordinates.  If \e longfirst = true (default is false), then
      * longitude precedes latitude in the absence of a hemisphere designator.
-     * Thus (with \e swaplatlong = false)
+     * Thus (with \e longfirst = false)
      * - 40 -75
      * - N40 W75
      * - -75 N40
@@ -150,9 +150,8 @@ namespace GeographicLib {
      * components so -1d30 is -(1+30/60) = −1.5.  However, note
      * that -1:30-0:0:15 is parsed as (-1:30) + (-0:0:15) = −(1+30/60)
      * − (15/3600).  Latitudes must be in the range [−90°,
-     * 90°] and longitudes in the range [−540°, 540°).
-     * Internally longitudes are reduced to the range [−180°,
-     * 180°).
+     * 90°].  Internally longitudes are reduced to the range
+     * [−180°, 180°).
      *
      * <b>UTM/UPS parsing</b>: For UTM zones (−80° ≤ Lat <
      * 84°), the zone designator is made up of a zone number (for 1 to 60)
@@ -177,8 +176,8 @@ namespace GeographicLib {
      * - 38SMB44148470   = 38n 444140 3684700
      **********************************************************************/
     explicit GeoCoords(const std::string& s,
-                       bool centerp = true, bool swaplatlong = false)
-    { Reset(s, centerp, swaplatlong); }
+                       bool centerp = true, bool longfirst = false)
+    { Reset(s, centerp, longfirst); }
 
     /**
      * Construct from geographic coordinates.
@@ -189,8 +188,6 @@ namespace GeographicLib {
      *   specified zone using the rules given in UTMUPS::zonespec.
      * @exception GeographicErr if \e latitude is not in [−90°,
      *   90°].
-     * @exception GeographicErr if \e longitude is not in [−540°,
-     *   540°).
      * @exception GeographicErr if \e zone cannot be used for this location.
      **********************************************************************/
     GeoCoords(real latitude, real longitude, int zone = UTMUPS::STANDARD) {
@@ -213,17 +210,17 @@ namespace GeographicLib {
 
     /**
      * Reset the location from a string.  See
-     * GeoCoords(const std::string& s, bool centerp, bool swaplatlong).
+     * GeoCoords(const std::string& s, bool centerp, bool longfirst).
      *
      * @param[in] s 1-element, 2-element, or 3-element string representation of
      *   the position.
      * @param[in] centerp governs the interpretation of MGRS coordinates.
-     * @param[in] swaplatlong governs the interpretation of geographic
+     * @param[in] longfirst governs the interpretation of geographic
      *   coordinates.
      * @exception GeographicErr if the \e s is malformed.
      **********************************************************************/
     void Reset(const std::string& s,
-               bool centerp = true, bool swaplatlong = false);
+               bool centerp = true, bool longfirst = false);
 
     /**
      * Reset the location in terms of geographic coordinates.  See
@@ -235,8 +232,6 @@ namespace GeographicLib {
      *   specified zone using the rules given in UTMUPS::zonespec.
      * @exception GeographicErr if \e latitude is not in [−90°,
      *   90°].
-     * @exception GeographicErr if \e longitude is not in [−540°,
-     *   540°).
      * @exception GeographicErr if \e zone cannot be used for this location.
      **********************************************************************/
     void Reset(real latitude, real longitude, int zone = UTMUPS::STANDARD) {
@@ -387,7 +382,7 @@ namespace GeographicLib {
      * degrees.
      *
      * @param[in] prec precision (relative to about 1m).
-     * @param[in] swaplatlong if true give longitude first (default = false)
+     * @param[in] longfirst if true give longitude first (default = false)
      * @exception std::bad_alloc if memory for the string can't be allocated.
      * @return decimal latitude/longitude string representation.
      *
@@ -397,14 +392,14 @@ namespace GeographicLib {
      * - prec = 3, 10<sup>−8</sup>°
      * - prec = 9 (max), 10<sup>−14</sup>°
      **********************************************************************/
-    std::string GeoRepresentation(int prec = 0, bool swaplatlong = false) const;
+    std::string GeoRepresentation(int prec = 0, bool longfirst = false) const;
 
     /**
      * String representation with latitude and longitude as degrees, minutes,
      * seconds, and hemisphere.
      *
      * @param[in] prec precision (relative to about 1m)
-     * @param[in] swaplatlong if true give longitude first (default = false)
+     * @param[in] longfirst if true give longitude first (default = false)
      * @param[in] dmssep if non-null, use as the DMS separator character
      *   (instead of d, ', " delimiters).
      * @exception std::bad_alloc if memory for the string can't be allocated.
@@ -420,7 +415,7 @@ namespace GeographicLib {
      * - prec = 1, 0.01"
      * - prec = 10 (max), 10<sup>−11</sup>"
      **********************************************************************/
-    std::string DMSRepresentation(int prec = 0, bool swaplatlong = false,
+    std::string DMSRepresentation(int prec = 0, bool longfirst = false,
                                   char dmssep = char(0))
       const;
 
diff --git a/include/GeographicLib/Geocentric.hpp b/include/GeographicLib/Geocentric.hpp
index a56e313..d2bbd6a 100644
--- a/include/GeographicLib/Geocentric.hpp
+++ b/include/GeographicLib/Geocentric.hpp
@@ -2,7 +2,7 @@
  * \file Geocentric.hpp
  * \brief Header for GeographicLib::Geocentric class
  *
- * Copyright (c) Charles Karney (2008-2014) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2008-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -128,8 +128,7 @@ namespace GeographicLib {
      * @param[out] Y geocentric coordinate (meters).
      * @param[out] Z geocentric coordinate (meters).
      *
-     * \e lat should be in the range [−90°, 90°]; \e lon
-     * should be in the range [−540°, 540°).
+     * \e lat should be in the range [−90°, 90°].
      **********************************************************************/
     void Forward(real lat, real lon, real h, real& X, real& Y, real& Z)
       const {
diff --git a/include/GeographicLib/Geodesic.hpp b/include/GeographicLib/Geodesic.hpp
index 41eaa57..ee312f3 100644
--- a/include/GeographicLib/Geodesic.hpp
+++ b/include/GeographicLib/Geodesic.hpp
@@ -183,6 +183,9 @@ namespace GeographicLib {
     static const int nC3x_ = (nC3_ * (nC3_ - 1)) / 2;
     static const int nC4_ = GEOGRAPHICLIB_GEODESIC_ORDER;
     static const int nC4x_ = (nC4_ * (nC4_ + 1)) / 2;
+    // Size for temporary array
+    // nC = max(max(nC1_, nC1p_, nC2_) + 1, max(nC3_, nC4_))
+    static const int nC_ = GEOGRAPHICLIB_GEODESIC_ORDER + 1;
     static const unsigned maxit1_ = 20;
     unsigned maxit2_;
     real tiny_, tol0_, tol1_, tol2_, tolb_, xthresh_;
@@ -210,23 +213,22 @@ namespace GeographicLib {
     void Lengths(real eps, real sig12,
                  real ssig1, real csig1, real dn1,
                  real ssig2, real csig2, real dn2,
-                 real cbet1, real cbet2,
+                 real cbet1, real cbet2, unsigned outmask,
                  real& s12s, real& m12a, real& m0,
-                 bool scalep, real& M12, real& M21,
-                 real C1a[], real C2a[]) const;
+                 real& M12, real& M21, real Ca[]) const;
     real InverseStart(real sbet1, real cbet1, real dn1,
                       real sbet2, real cbet2, real dn2,
                       real lam12,
                       real& salp1, real& calp1,
                       real& salp2, real& calp2, real& dnm,
-                      real C1a[], real C2a[]) const;
+                      real Ca[]) const;
     real Lambda12(real sbet1, real cbet1, real dn1,
                   real sbet2, real cbet2, real dn2,
                   real salp1, real calp1,
                   real& salp2, real& calp2, real& sig12,
                   real& ssig1, real& csig1, real& ssig2, real& csig2,
                   real& eps, real& domg12, bool diffp, real& dlam12,
-                  real C1a[], real C2a[], real C3a[])
+                  real Ca[])
       const;
 
     // These are Maxima generated functions to provide series approximations to
@@ -360,8 +362,7 @@ namespace GeographicLib {
      * @param[out] S12 area under the geodesic (meters<sup>2</sup>).
      * @return \e a12 arc length of between point 1 and point 2 (degrees).
      *
-     * \e lat1 should be in the range [−90°, 90°]; \e lon1 and \e
-     * azi1 should be in the range [−540°, 540°).  The values of
+     * \e lat1 should be in the range [−90°, 90°].  The values of
      * \e lon2 and \e azi2 returned are in the range [−180°,
      * 180°).
      *
@@ -474,8 +475,7 @@ namespace GeographicLib {
      *   (dimensionless).
      * @param[out] S12 area under the geodesic (meters<sup>2</sup>).
      *
-     * \e lat1 should be in the range [−90°, 90°]; \e lon1 and \e
-     * azi1 should be in the range [−540°, 540°).  The values of
+     * \e lat1 should be in the range [−90°, 90°].  The values of
      * \e lon2 and \e azi2 returned are in the range [−180°,
      * 180°).
      *
@@ -625,10 +625,7 @@ namespace GeographicLib {
      *
      * With the Geodesic::LONG_UNROLL bit set, the quantity \e lon2 − \e
      * lon1 indicates how many times and in what sense the geodesic encircles
-     * the ellipsoid.  Because \e lon2 might be outside the normal allowed
-     * range for longitudes, [−540°, 540°), be sure to normalize
-     * it with Math::AngNormalize2 before using it in other GeographicLib
-     * calls.
+     * the ellipsoid.
      **********************************************************************/
     Math::real GenDirect(real lat1, real lon1, real azi1,
                          bool arcmode, real s12_a12, unsigned outmask,
@@ -658,8 +655,7 @@ namespace GeographicLib {
      * @param[out] S12 area under the geodesic (meters<sup>2</sup>).
      * @return \e a12 arc length of between point 1 and point 2 (degrees).
      *
-     * \e lat1 and \e lat2 should be in the range [−90°, 90°]; \e
-     * lon1 and \e lon2 should be in the range [−540°, 540°).
+     * \e lat1 and \e lat2 should be in the range [−90°, 90°].
      * The values of \e azi1 and \e azi2 returned are in the range
      * [−180°, 180°).
      *
@@ -816,8 +812,7 @@ namespace GeographicLib {
      *   GeodesicLine::Position.
      * @return a GeodesicLine object.
      *
-     * \e lat1 should be in the range [−90°, 90°]; \e lon1 and \e
-     * azi1 should be in the range [−540°, 540°).
+     * \e lat1 should be in the range [−90°, 90°].
      *
      * The Geodesic::mask values are
      * - \e caps |= Geodesic::LATITUDE for the latitude \e lat2; this is
diff --git a/include/GeographicLib/GeodesicExact.hpp b/include/GeographicLib/GeodesicExact.hpp
index 420bd18..3472ebe 100644
--- a/include/GeographicLib/GeodesicExact.hpp
+++ b/include/GeographicLib/GeodesicExact.hpp
@@ -110,9 +110,9 @@ namespace GeographicLib {
                  real sig12,
                  real ssig1, real csig1, real dn1,
                  real ssig2, real csig2, real dn2,
-                 real cbet1, real cbet2,
+                 real cbet1, real cbet2, unsigned outmask,
                  real& s12s, real& m12a, real& m0,
-                 bool scalep, real& M12, real& M21) const;
+                 real& M12, real& M21) const;
     real InverseStart(EllipticFunction& E,
                       real sbet1, real cbet1, real dn1,
                       real sbet2, real cbet2, real dn2,
@@ -257,8 +257,7 @@ namespace GeographicLib {
      * @param[out] S12 area under the geodesic (meters<sup>2</sup>).
      * @return \e a12 arc length of between point 1 and point 2 (degrees).
      *
-     * \e lat1 should be in the range [−90°, 90°]; \e lon1 and \e
-     * azi1 should be in the range [−540°, 540°).  The values of
+     * \e lat1 should be in the range [−90°, 90°].  The values of
      * \e lon2 and \e azi2 returned are in the range [−180°,
      * 180°).
      *
@@ -371,8 +370,7 @@ namespace GeographicLib {
      *   (dimensionless).
      * @param[out] S12 area under the geodesic (meters<sup>2</sup>).
      *
-     * \e lat1 should be in the range [−90°, 90°]; \e lon1 and \e
-     * azi1 should be in the range [−540°, 540°).  The values of
+     * \e lat1 should be in the range [−90°, 90°].  The values of
      * \e lon2 and \e azi2 returned are in the range [−180°,
      * 180°).
      *
@@ -522,10 +520,7 @@ namespace GeographicLib {
      *
      * With the GeodesicExact::LONG_UNROLL bit set, the quantity \e lon2
      * − \e lon1 indicates how many times and in what sense the geodesic
-     * encircles the ellipsoid.  Because \e lon2 might be outside the normal
-     * allowed range for longitudes, [−540°, 540°), be sure to
-     * normalize it with Math::AngNormalize2 before using it in other
-     * GeographicLib calls.
+     * encircles the ellipsoid.
      **********************************************************************/
     Math::real GenDirect(real lat1, real lon1, real azi1,
                          bool arcmode, real s12_a12, unsigned outmask,
@@ -555,8 +550,7 @@ namespace GeographicLib {
      * @param[out] S12 area under the geodesic (meters<sup>2</sup>).
      * @return \e a12 arc length of between point 1 and point 2 (degrees).
      *
-     * \e lat1 and \e lat2 should be in the range [−90°, 90°]; \e
-     * lon1 and \e lon2 should be in the range [−540°, 540°).
+     * \e lat1 and \e lat2 should be in the range [−90°, 90°].
      * The values of \e azi1 and \e azi2 returned are in the range
      * [−180°, 180°).
      *
@@ -708,8 +702,7 @@ namespace GeographicLib {
      *   GeodesicLineExact::Position.
      * @return a GeodesicLineExact object.
      *
-     * \e lat1 should be in the range [−90°, 90°]; \e lon1 and \e
-     * azi1 should be in the range [−540°, 540°).
+     * \e lat1 should be in the range [−90°, 90°].
      *
      * The GeodesicExact::mask values are
      * - \e caps |= GeodesicExact::LATITUDE for the latitude \e lat2; this is
diff --git a/include/GeographicLib/GeodesicLine.hpp b/include/GeographicLib/GeodesicLine.hpp
index 7607fb6..5e19fee 100644
--- a/include/GeographicLib/GeodesicLine.hpp
+++ b/include/GeographicLib/GeodesicLine.hpp
@@ -2,7 +2,7 @@
  * \file GeodesicLine.hpp
  * \brief Header for GeographicLib::GeodesicLine class
  *
- * Copyright (c) Charles Karney (2009-2014) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2009-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -181,8 +181,7 @@ namespace GeographicLib {
      *   i.e., which quantities can be returned in calls to
      *   GeodesicLine::Position.
      *
-     * \e lat1 should be in the range [−90°, 90°]; \e lon1 and \e
-     * azi1 should be in the range [−540°, 540°).
+     * \e lat1 should be in the range [−90°, 90°].
      *
      * The GeodesicLine::mask values are
      * - \e caps |= GeodesicLine::LATITUDE for the latitude \e lat2; this is
@@ -516,10 +515,7 @@ namespace GeographicLib {
      *
      * With the GeodesicLine::LONG_UNROLL bit set, the quantity \e lon2 −
      * \e lon1 indicates how many times and in what sense the geodesic
-     * encircles the ellipsoid.  Because \e lon2 might be outside the normal
-     * allowed range for longitudes, [−540°, 540°), be sure to
-     * normalize it with Math::AngNormalize2 before using it in other
-     * GeographicLib calls.
+     * encircles the ellipsoid.
      **********************************************************************/
     Math::real GenPosition(bool arcmode, real s12_a12, unsigned outmask,
                            real& lat2, real& lon2, real& azi2,
@@ -558,21 +554,21 @@ namespace GeographicLib {
     /**
      * @return \e azi0 the azimuth (degrees) of the geodesic line as it crosses
      *   the equator in a northward direction.
+     *
+     * The result lies in [−90°, 90°].
      **********************************************************************/
     Math::real EquatorialAzimuth() const {
-      using std::atan2;
-      return Init() ?
-        atan2(_salp0, _calp0) / Math::degree() : Math::NaN();
+      return Init() ? Math::atan2d(_salp0, _calp0) : Math::NaN();
     }
 
     /**
      * @return \e a1 the arc length (degrees) between the northward equatorial
      *   crossing and point 1.
+     *
+     * The result lies in (−180°, 180°].
      **********************************************************************/
     Math::real EquatorialArc() const {
-      using std::atan2;
-      return Init() ?
-        atan2(_ssig1, _csig1) / Math::degree() : Math::NaN();
+      return Init() ? Math::atan2d(_ssig1, _csig1) : Math::NaN();
     }
 
     /**
diff --git a/include/GeographicLib/GeodesicLineExact.hpp b/include/GeographicLib/GeodesicLineExact.hpp
index f65f592..548b790 100644
--- a/include/GeographicLib/GeodesicLineExact.hpp
+++ b/include/GeographicLib/GeodesicLineExact.hpp
@@ -2,7 +2,7 @@
  * \file GeodesicLineExact.hpp
  * \brief Header for GeographicLib::GeodesicLineExact class
  *
- * Copyright (c) Charles Karney (2012-2014) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2012-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -153,8 +153,7 @@ namespace GeographicLib {
      *   possess, i.e., which quantities can be returned in calls to
      *   GeodesicLine::Position.
      *
-     * \e lat1 should be in the range [−90°, 90°]; \e lon1 and \e
-     * azi1 should be in the range [−540°, 540°).
+     * \e lat1 should be in the range [−90°, 90°].
      *
      * The GeodesicLineExact::mask values are
      * - \e caps |= GeodesicLineExact::LATITUDE for the latitude \e lat2; this
@@ -490,10 +489,7 @@ namespace GeographicLib {
      *
      * With the GeodesicLineExact::LONG_UNROLL bit set, the quantity \e lon2
      * − \e lon1 indicates how many times and in what sense the geodesic
-     * encircles the ellipsoid.  Because \e lon2 might be outside the normal
-     * allowed range for longitudes, [−540°, 540°), be sure to
-     * normalize it with Math::AngNormalize2 before using it in other
-     * GeographicLib calls.
+     * encircles the ellipsoid.
      **********************************************************************/
     Math::real GenPosition(bool arcmode, real s12_a12, unsigned outmask,
                            real& lat2, real& lon2, real& azi2,
@@ -531,22 +527,24 @@ namespace GeographicLib {
 
     /**
      * @return \e azi0 the azimuth (degrees) of the geodesic line as it crosses
-     * the equator in a northward direction.
+     *   the equator in a northward direction.
+     *
+     * The result lies in [−90°, 90°].
      **********************************************************************/
     Math::real EquatorialAzimuth() const {
       using std::atan2;
-      return Init() ?
-        atan2(_salp0, _calp0) / Math::degree() : Math::NaN();
+      return Init() ? Math::atan2d(_salp0, _calp0) : Math::NaN();
     }
 
     /**
      * @return \e a1 the arc length (degrees) between the northward equatorial
-     * crossing and point 1.
+     *   crossing and point 1.
+     *
+     * The result lies in (−180°, 180°].
      **********************************************************************/
     Math::real EquatorialArc() const {
       using std::atan2;
-      return Init() ?
-        atan2(_ssig1, _csig1) / Math::degree() : Math::NaN();
+      return Init() ? atan2(_ssig1, _csig1) / Math::degree() : Math::NaN();
     }
 
     /**
diff --git a/include/GeographicLib/Geohash.hpp b/include/GeographicLib/Geohash.hpp
index c182f9b..38b5a04 100644
--- a/include/GeographicLib/Geohash.hpp
+++ b/include/GeographicLib/Geohash.hpp
@@ -2,8 +2,8 @@
  * \file Geohash.hpp
  * \brief Header for GeographicLib::Geohash class
  *
- * Copyright (c) Charles Karney (2012) <charles at karney.com> and licensed under
- * the MIT/X11 License.  For more information, see
+ * Copyright (c) Charles Karney (2012-2015) <charles at karney.com> and licensed
+ * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
 
@@ -25,12 +25,13 @@ namespace GeographicLib {
    *
    * Geohashes are described in
    * - https://en.wikipedia.org/wiki/Geohash
-   * - http://geohash.org/ (this link is broken as of 2012-12-11)
+   * - http://geohash.org/
    * .
    * They provide a compact string representation of a particular geographic
    * location (expressed as latitude and longitude), with the property that if
    * trailing characters are dropped from the string the geographic location
-   * remains nearby.
+   * remains nearby.  The classes Georef and GARS implement similar compact
+   * representations.
    *
    * Example of use:
    * \include example-Geohash.cpp
@@ -41,20 +42,6 @@ namespace GeographicLib {
     typedef Math::real real;
     static const int maxlen_ = 18;
     static const unsigned long long mask_ = 1ULL << 45;
-    static const int decprec_[];
-    static inline real shift() {
-      using std::pow; static const real shift = pow(real(2), 45);
-      return shift;
-    }
-    static inline real loneps() {
-      static const real loneps = 180 / shift();
-      return loneps;
-    }
-    static inline real lateps() {
-      static const real lateps = 90 / shift();
-      return lateps;
-    }
-    static const real lateps_;
     static const std::string lcdigits_;
     static const std::string ucdigits_;
     Geohash();                     // Disable constructor
@@ -68,15 +55,14 @@ namespace GeographicLib {
      * @param[in] lon longitude of point (degrees).
      * @param[in] len the length of the resulting geohash.
      * @param[out] geohash the geohash.
-     * @exception GeographicErr if \e la is not in [−90°,
+     * @exception GeographicErr if \e lat is not in [−90°,
      *   90°].
-     * @exception GeographicErr if \e lon is not in [−540°,
-     *   540°).
      * @exception std::bad_alloc if memory for \e geohash can't be allocated.
      *
-     * Internally, \e len is first put in the range [0, 18].
+     * Internally, \e len is first put in the range [0, 18].  (\e len = 18
+     * provides approximately 1μm precision.)
      *
-     * If \e lat or \e lon is NaN, the returned geohash is "nan".
+     * If \e lat or \e lon is NaN, the returned geohash is "invalid".
      **********************************************************************/
     static void Forward(real lat, real lon, int len, std::string& geohash);
 
@@ -91,11 +77,13 @@ namespace GeographicLib {
      *   geohash location, otherwise return the south-west corner.
      * @exception GeographicErr if \e geohash contains illegal characters.
      *
-     * Only the first 18 characters for \e geohash are considered.  The case of
-     * the letters in \e geohash is ignored.
+     * Only the first 18 characters for \e geohash are considered.  (18
+     * characters provides approximately 1μm precision.)  The case of the
+     * letters in \e geohash is ignored.
      *
-     * If the first three characters in \e geohash are "nan", then \e lat and
-     * \e lon are set to NaN.
+     * If the first 3 characters of \e geohash are "inv", then \e lat and \e
+     * lon are set to NaN and \e len is unchanged.  ("nan" is treated
+     * similarly.)
      **********************************************************************/
     static void Reverse(const std::string& geohash, real& lat, real& lon,
                         int& len, bool centerp = true);
@@ -109,8 +97,9 @@ namespace GeographicLib {
      * Internally, \e len is first put in the range [0, 18].
      **********************************************************************/
     static Math::real LatitudeResolution(int len) {
+      using std::pow;
       len = (std::max)(0, (std::min)(int(maxlen_), len));
-      return 180 * std::pow(0.5, 5 * len / 2);
+      return 180 * pow(real(0.5), 5 * len / 2);
     }
 
     /**
@@ -122,8 +111,9 @@ namespace GeographicLib {
      * Internally, \e len is first put in the range [0, 18].
      **********************************************************************/
     static Math::real LongitudeResolution(int len) {
+      using std::pow;
       len = (std::max)(0, (std::min)(int(maxlen_), len));
-      return 360 * std::pow(0.5, 5 * len - 5 * len / 2);
+      return 360 * pow(real(0.5), 5 * len - 5 * len / 2);
     }
 
     /**
@@ -136,8 +126,7 @@ namespace GeographicLib {
      * The returned length is in the range [0, 18].
      **********************************************************************/
     static int GeohashLength(real res) {
-      using std::abs;
-      res = abs(res);
+      using std::abs; res = abs(res);
       for (int len = 0; len < maxlen_; ++len)
         if (LongitudeResolution(len) <= res)
           return len;
diff --git a/include/GeographicLib/Geoid.hpp b/include/GeographicLib/Geoid.hpp
index 40e8eff..9f2e388 100644
--- a/include/GeographicLib/Geoid.hpp
+++ b/include/GeographicLib/Geoid.hpp
@@ -62,16 +62,6 @@ namespace GeographicLib {
    * See \ref geoid for details of how to install the data sets, the data
    * format, estimates of the interpolation errors, and how to use caching.
    *
-   * In addition to returning the geoid height, the gradient of the geoid can
-   * be calculated.  The gradient is defined as the rate of change of the geoid
-   * as a function of position on the ellipsoid.  This uses the parameters for
-   * the WGS84 ellipsoid.  The gradient defined in terms of the interpolated
-   * heights.  As a result of the way that the geoid data is stored, the
-   * calculation of gradients can result in large quantization errors.  This is
-   * particularly acute for fine grids, at high latitudes, and for the easterly
-   * gradient.  For this reason, the use of this facility is <b>DEPRECATED</b>.
-   * Instead, use the GravityModel class to evaluate the gravity vector.
-   *
    * This class is typically \e not thread safe in that a single instantiation
    * cannot be safely used by multiple threads because of the way the object
    * reads the data set and because it maintains a single-cell cache.  If
@@ -251,8 +241,7 @@ namespace GeographicLib {
      * parallels \e south and \e north and the meridians \e west and \e east.
      * \e east is always interpreted as being east of \e west, if necessary by
      * adding 360° to its value.  \e south and \e north should be in
-     * the range [−90°, 90°]; \e west and \e east should
-     * be in the range [−540°, 540°).
+     * the range [−90°, 90°].
      **********************************************************************/
     void CacheArea(real south, real west, real north, real east) const;
 
@@ -292,14 +281,14 @@ namespace GeographicLib {
      *   never happens if (\e lat, \e lon) is within a successfully cached area.
      * @return the height of the geoid above the ellipsoid (meters).
      *
-     * The latitude should be in [−90°, 90°] and
-     * longitude should be in [−540°, 540°).
+     * The latitude should be in [−90°, 90°].
      **********************************************************************/
     Math::real operator()(real lat, real lon) const {
       real gradn, grade;
       return height(lat, lon, false, gradn, grade);
     }
 
+    /// \cond SKIP
     /**
      * Compute the geoid height and gradient at a point
      *
@@ -311,18 +300,18 @@ namespace GeographicLib {
      *   never happens if (\e lat, \e lon) is within a successfully cached area.
      * @return geoid height (meters).
      *
-     * The latitude should be in [−90°, 90°] and longitude should
-     * be in [−540°, 540°).  As a result of the way that the
-     * geoid data is stored, the calculation of gradients can result in large
-     * quantization errors.  This is particularly acute for fine grids, at high
-     * latitudes, and for the easterly gradient.  For this reason, the
-     * computation of the gradient is <b>DEPRECATED</b>.  If you need to
-     * compute the direction of the acceleration due to gravity accurately, you
-     * should use GravityModel::Gravity.
+     * The latitude should be in [−90°, 90°].  As a result of the
+     * way that the geoid data is stored, the calculation of gradients can
+     * result in large quantization errors.  This is particularly acute for
+     * fine grids, at high latitudes, and for the easterly gradient.  For this
+     * reason, the computation of the gradient is <b>DEPRECATED</b>.  If you
+     * need to compute the direction of the acceleration due to gravity
+     * accurately, you should use GravityModel::Gravity.
      **********************************************************************/
     Math::real operator()(real lat, real lon, real& gradn, real& grade) const {
       return height(lat, lon, true, gradn, grade);
     }
+    /// \endcond
 
     /**
      * Convert a height above the geoid to a height above the ellipsoid and
@@ -342,7 +331,7 @@ namespace GeographicLib {
     Math::real ConvertHeight(real lat, real lon, real h,
                              convertflag d) const {
       real gradn, grade;
-      return h + real(d) * height(lat, lon, true, gradn, grade);
+      return h + real(d) * height(lat, lon, false, gradn, grade);
     }
 
     ///@}
diff --git a/include/GeographicLib/Georef.hpp b/include/GeographicLib/Georef.hpp
new file mode 100644
index 0000000..d1ed366
--- /dev/null
+++ b/include/GeographicLib/Georef.hpp
@@ -0,0 +1,160 @@
+/**
+ * \file Georef.hpp
+ * \brief Header for GeographicLib::Georef class
+ *
+ * Copyright (c) Charles Karney (2015) <charles at karney.com> and licensed under
+ * the MIT/X11 License.  For more information, see
+ * http://geographiclib.sourceforge.net/
+ **********************************************************************/
+
+#if !defined(GEOGRAPHICLIB_GEOREF_HPP)
+#define GEOGRAPHICLIB_GEOREF_HPP 1
+
+#include <GeographicLib/Constants.hpp>
+
+#if defined(_MSC_VER)
+// Squelch warnings about dll vs string
+#  pragma warning (push)
+#  pragma warning (disable: 4251)
+#endif
+
+namespace GeographicLib {
+
+  /**
+   * \brief Conversions for the World Geographic Reference System (georef)
+   *
+   * The World Geographic Reference System is described in
+   * - https://en.wikipedia.org/wiki/Georef
+   * - http://earth-info.nga.mil/GandG/coordsys/grids/georef.pdf
+   * .
+   * It provides a compact string representation of a geographic area
+   * (expressed as latitude and longitude).  The classes GARS and Geohash
+   * implement similar compact representations.
+   *
+   * Example of use:
+   * \include example-Georef.cpp
+   **********************************************************************/
+
+  class GEOGRAPHICLIB_EXPORT Georef {
+  private:
+    typedef Math::real real;
+    static const std::string digits_;
+    static const std::string lontile_;
+    static const std::string lattile_;
+    static const std::string degrees_;
+    enum {
+      tile_ = 15,               // The size of tile in degrees
+      lonorig_ = -180,          // Origin for longitude
+      latorig_ = -90,           // Origin for latitude
+      base_ = 10,               // Base for minutes
+      baselen_ = 4,
+      maxprec_ = 11,            // approximately equivalent to MGRS class
+      maxlen_ = baselen_ + 2 * maxprec_,
+    };
+    Georef();                     // Disable constructor
+
+  public:
+
+    /**
+     * Convert from geographic coordinates to georef.
+     *
+     * @param[in] lat latitude of point (degrees).
+     * @param[in] lon longitude of point (degrees).
+     * @param[in] prec the precision of the resulting georef.
+     * @param[out] georef the georef string.
+     * @exception GeographicErr if \e lat is not in [−90°,
+     *   90°].
+     * @exception std::bad_alloc if memory for \e georef can't be allocated.
+     *
+     * \e prec specifies the precision of \e georef as follows:
+     * - \e prec = −1 (min), 15°
+     * - \e prec = 0, 1°
+     * - \e prec = 1, converted to \e prec = 2
+     * - \e prec = 2, 1'
+     * - \e prec = 3, 0.1'
+     * - \e prec = 4, 0.01'
+     * - \e prec = 5, 0.001'
+     * - …
+     * - \e prec = 11 (max), 10<sup>−9</sup>'
+     *
+     * If \e lat or \e lon is NaN, then \e georef is set to "INVALID".
+     **********************************************************************/
+    static void Forward(real lat, real lon, int prec, std::string& georef);
+
+    /**
+     * Convert from Georef to geographic coordinates.
+     *
+     * @param[in] georef the Georef.
+     * @param[out] lat latitude of point (degrees).
+     * @param[out] lon longitude of point (degrees).
+     * @param[out] prec the precision of \e georef.
+     * @param[in] centerp if true (the default) return the center
+     *   \e georef, otherwise return the south-west corner.
+     * @exception GeographicErr if \e georef is illegal.
+     *
+     * The case of the letters in \e georef is ignored.  \e prec is in the
+     * range [−1, 11] and gives the precision of \e georef as follows:
+     * - \e prec = −1 (min), 15°
+     * - \e prec = 0, 1°
+     * - \e prec = 1, not returned
+     * - \e prec = 2, 1'
+     * - \e prec = 3, 0.1'
+     * - \e prec = 4, 0.01'
+     * - \e prec = 5, 0.001'
+     * - …
+     * - \e prec = 11 (max), 10<sup>−9</sup>'
+     *
+     * If the first 3 characters of \e georef are "INV", then \e lat and \e lon
+     * are set to NaN and \e prec is unchanged.
+     **********************************************************************/
+    static void Reverse(const std::string& georef, real& lat, real& lon,
+                        int& prec, bool centerp = true);
+
+    /**
+     * The angular resolution of a Georef.
+     *
+     * @param[in] prec the precision of the Georef.
+     * @return the latitude-longitude resolution (degrees).
+     *
+     * Internally, \e prec is first put in the range [−1, 11].
+     **********************************************************************/
+    static Math::real Resolution(int prec) {
+      if (prec < 1)
+        return real(prec < 0 ? 15 : 1);
+      else {
+        using std::pow;
+        // Treat prec = 1 as 2.
+        prec = (std::max)(2, (std::min)(int(maxprec_), prec));
+        return 1/(60 * pow(real(base_), prec - 2));
+      }
+    }
+
+    /**
+     * The Georef precision required to meet a given geographic resolution.
+     *
+     * @param[in] res the minimum of resolution in latitude and longitude
+     *   (degrees).
+     * @return Georef precision.
+     *
+     * The returned length is in the range [0, 11].
+     **********************************************************************/
+    static int Precision(real res) {
+      using std::abs; res = abs(res);
+      for (int prec = 0; prec < maxprec_; ++prec) {
+        if (prec == 1)
+          continue;
+        if (Resolution(prec) <= res)
+          return prec;
+      }
+      return maxprec_;
+    }
+
+  };
+
+} // namespace GeographicLib
+
+#if defined(_MSC_VER)
+#  pragma warning (pop)
+#endif
+
+#endif  // GEOGRAPHICLIB_GEOREF_HPP
diff --git a/include/GeographicLib/Gnomonic.hpp b/include/GeographicLib/Gnomonic.hpp
index 97b03c4..5b4596e 100644
--- a/include/GeographicLib/Gnomonic.hpp
+++ b/include/GeographicLib/Gnomonic.hpp
@@ -2,7 +2,7 @@
  * \file Gnomonic.hpp
  * \brief Header for GeographicLib::Gnomonic class
  *
- * Copyright (c) Charles Karney (2010-2011) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2010-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -127,8 +127,7 @@ namespace GeographicLib {
      * @param[out] azi azimuth of geodesic at point (degrees).
      * @param[out] rk reciprocal of azimuthal scale at point.
      *
-     * \e lat0 and \e lat should be in the range [−90°, 90°] and
-     * \e lon0 and \e lon should be in the range [−540°, 540°).
+     * \e lat0 and \e lat should be in the range [−90°, 90°].
      * The scale of the projection is 1/<i>rk</i><sup>2</sup> in the "radial"
      * direction, \e azi clockwise from true north, and is 1/\e rk in the
      * direction perpendicular to this.  If the point lies "over the horizon",
@@ -152,17 +151,16 @@ namespace GeographicLib {
      * @param[out] azi azimuth of geodesic at point (degrees).
      * @param[out] rk reciprocal of azimuthal scale at point.
      *
-     * \e lat0 should be in the range [−90°, 90°] and \e
-     * lon0 should be in the range [−540°, 540°).  \e lat
-     * will be in the range [−90°, 90°] and \e lon will
-     * be in the range [−180°, 180°).  The scale of the
-     * projection is 1/<i>rk</i><sup>2</sup> in the "radial" direction, \e azi
-     * clockwise from true north, and is 1/\e rk in the direction perpendicular
-     * to this.  Even though all inputs should return a valid \e lat and \e
-     * lon, it's possible that the procedure fails to converge for very large
-     * \e x or \e y; in this case NaNs are returned for all the output
-     * arguments.  A call to Reverse followed by a call to Forward will return
-     * the original (\e x, \e y) (to roundoff).
+     * \e lat0 should be in the range [−90°, 90°].  \e lat will
+     * be in the range [−90°, 90°] and \e lon will be in the
+     * range [−180°, 180°).  The scale of the projection is
+     * 1/<i>rk</i><sup>2</sup> in the "radial" direction, \e azi clockwise from
+     * true north, and is 1/\e rk in the direction perpendicular to this.  Even
+     * though all inputs should return a valid \e lat and \e lon, it's possible
+     * that the procedure fails to converge for very large \e x or \e y; in
+     * this case NaNs are returned for all the output arguments.  A call to
+     * Reverse followed by a call to Forward will return the original (\e x, \e
+     * y) (to roundoff).
      **********************************************************************/
     void Reverse(real lat0, real lon0, real x, real y,
                  real& lat, real& lon, real& azi, real& rk) const;
diff --git a/include/GeographicLib/GravityCircle.hpp b/include/GeographicLib/GravityCircle.hpp
index 6f9986e..335b23b 100644
--- a/include/GeographicLib/GravityCircle.hpp
+++ b/include/GeographicLib/GravityCircle.hpp
@@ -2,8 +2,8 @@
  * \file GravityCircle.hpp
  * \brief Header for GeographicLib::GravityCircle class
  *
- * Copyright (c) Charles Karney (2011) <charles at karney.com> and licensed under
- * the MIT/X11 License.  For more information, see
+ * Copyright (c) Charles Karney (2011-2015) <charles at karney.com> and licensed
+ * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
 
@@ -67,7 +67,7 @@ namespace GeographicLib {
       : _caps(caps)
       , _a(a)
       , _f(f)
-      , _lat(lat)
+      , _lat(Math::LatFix(lat))
       , _h(h)
       , _Z(Z)
       , _Px(P)
@@ -185,7 +185,7 @@ namespace GeographicLib {
      **********************************************************************/
     Math::real W(real lon, real& gX, real& gY, real& gZ) const {
       real clam, slam;
-      CircularEngine::cossin(lon, clam, slam);
+      Math::sincosd(lon, slam, clam);
       return W(clam, slam, gX, gY, gZ);
     }
 
@@ -205,7 +205,7 @@ namespace GeographicLib {
      **********************************************************************/
     Math::real V(real lon, real& GX, real& GY, real& GZ) const {
       real clam, slam;
-      CircularEngine::cossin(lon, clam, slam);
+      Math::sincosd(lon, slam, clam);
       return V(clam, slam, GX, GY, GZ);
     }
 
@@ -226,7 +226,7 @@ namespace GeographicLib {
     Math::real T(real lon, real& deltaX, real& deltaY, real& deltaZ)
       const {
       real clam, slam;
-      CircularEngine::cossin(lon, clam, slam);
+      Math::sincosd(lon, slam, clam);
       return InternalT(clam, slam, deltaX, deltaY, deltaZ, true, true);
     }
 
@@ -239,7 +239,7 @@ namespace GeographicLib {
      **********************************************************************/
     Math::real T(real lon) const {
       real clam, slam, dummy;
-      CircularEngine::cossin(lon, clam, slam);
+      Math::sincosd(lon, slam, clam);
       return InternalT(clam, slam, dummy, dummy, dummy, false, true);
     }
 
diff --git a/include/GeographicLib/LambertConformalConic.hpp b/include/GeographicLib/LambertConformalConic.hpp
index 6cbc4e9..06f3d7d 100644
--- a/include/GeographicLib/LambertConformalConic.hpp
+++ b/include/GeographicLib/LambertConformalConic.hpp
@@ -223,12 +223,11 @@ namespace GeographicLib {
      *
      * The latitude origin is given by LambertConformalConic::LatitudeOrigin().
      * No false easting or northing is added and \e lat should be in the range
-     * [−90°, 90°]; \e lon and \e lon0 should be in the
-     * range [−540°, 540°).  The error in the projection
-     * is less than about 10 nm (10 nanometers), true distance, and the errors
-     * in the meridian convergence and scale are consistent with this.  The
-     * values of \e x and \e y returned for points which project to infinity
-     * (i.e., one or both of the poles) will be large but finite.
+     * [−90°, 90°].  The error in the projection is less than
+     * about 10 nm (10 nanometers), true distance, and the errors in the
+     * meridian convergence and scale are consistent with this.  The values of
+     * \e x and \e y returned for points which project to infinity (i.e., one
+     * or both of the poles) will be large but finite.
      **********************************************************************/
     void Forward(real lon0, real lat, real lon,
                  real& x, real& y, real& gamma, real& k) const;
@@ -245,12 +244,10 @@ namespace GeographicLib {
      * @param[out] k scale of projection at point.
      *
      * The latitude origin is given by LambertConformalConic::LatitudeOrigin().
-     * No false easting or northing is added.  \e lon0 should be in the range
-     * [−540°, 540°).  The value of \e lon returned is in
-     * the range [−180°, 180°).  The error in the
-     * projection is less than about 10 nm (10 nanometers), true distance, and
-     * the errors in the meridian convergence and scale are consistent with
-     * this.
+     * No false easting or northing is added.  The value of \e lon returned is
+     * in the range [−180°, 180°).  The error in the projection
+     * is less than about 10 nm (10 nanometers), true distance, and the errors
+     * in the meridian convergence and scale are consistent with this.
      **********************************************************************/
     void Reverse(real lon0, real x, real y,
                  real& lat, real& lon, real& gamma, real& k) const;
diff --git a/include/GeographicLib/LocalCartesian.hpp b/include/GeographicLib/LocalCartesian.hpp
index 9a7b3f0..110cb30 100644
--- a/include/GeographicLib/LocalCartesian.hpp
+++ b/include/GeographicLib/LocalCartesian.hpp
@@ -2,7 +2,7 @@
  * \file LocalCartesian.hpp
  * \brief Header for GeographicLib::LocalCartesian class
  *
- * Copyright (c) Charles Karney (2008-2011) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2008-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -59,8 +59,7 @@ namespace GeographicLib {
      * @param[in] earth Geocentric object for the transformation; default
      *   Geocentric::WGS84().
      *
-     * \e lat0 should be in the range [−90°, 90°]; \e
-     * lon0 should be in the range [−540°, 540°).
+     * \e lat0 should be in the range [−90°, 90°].
      **********************************************************************/
     LocalCartesian(real lat0, real lon0, real h0 = 0,
                    const Geocentric& earth = Geocentric::WGS84())
@@ -86,8 +85,7 @@ namespace GeographicLib {
      * @param[in] lon0 longitude at origin (degrees).
      * @param[in] h0 height above ellipsoid at origin (meters); default 0.
      *
-     * \e lat0 should be in the range [−90°, 90°]; \e
-     * lon0 should be in the range [−540°, 540°).
+     * \e lat0 should be in the range [−90°, 90°].
      **********************************************************************/
     void Reset(real lat0, real lon0, real h0 = 0);
 
@@ -101,8 +99,7 @@ namespace GeographicLib {
      * @param[out] y local cartesian coordinate (meters).
      * @param[out] z local cartesian coordinate (meters).
      *
-     * \e lat should be in the range [−90°, 90°]; \e lon
-     * should be in the range [−540°, 540°).
+     * \e lat should be in the range [−90°, 90°].
      **********************************************************************/
     void Forward(real lat, real lon, real h, real& x, real& y, real& z)
       const {
@@ -122,8 +119,7 @@ namespace GeographicLib {
      * @param[out] M if the length of the vector is 9, fill with the rotation
      *   matrix in row-major order.
      *
-     * \e lat should be in the range [−90°, 90°]; \e lon
-     * should be in the range [−540°, 540°).
+     * \e lat should be in the range [−90°, 90°].
      *
      * Let \e v be a unit vector located at (\e lat, \e lon, \e h).  We can
      * express \e v as \e column vectors in one of two ways
diff --git a/include/GeographicLib/MGRS.hpp b/include/GeographicLib/MGRS.hpp
index fc78992..9d48729 100644
--- a/include/GeographicLib/MGRS.hpp
+++ b/include/GeographicLib/MGRS.hpp
@@ -46,6 +46,11 @@ namespace GeographicLib {
    *   identity.  (This is affected in predictable ways by errors in
    *   determining the latitude band and by loss of precision in the MGRS
    *   coordinates.)
+   * - The trailing digits produced by Forward are consistent as the precision
+   *   is varied.  Specifically, the digits are obtained by operating on the
+   *   easting with ⌊10<sup>6</sup> <i>x</i>⌋ and extracting the
+   *   required digits from the resulting number (and similarly for the
+   *   northing).
    * - All MGRS coordinates truncate to legal 100 km blocks.  All MGRS
    *   coordinates with a legal 100 km block prefix are legal (even though the
    *   latitude band letter may now belong to a neighboring band).
@@ -69,21 +74,6 @@ namespace GeographicLib {
   class GEOGRAPHICLIB_EXPORT MGRS {
   private:
     typedef Math::real real;
-    // The smallest length s.t., 1.0e7 - eps() < 1.0e7 (approx 1.9 nm)
-    static inline real eps() {
-      using std::pow;
-      // 25 = ceil(log_2(2e7)) -- use half circumference here because
-      // northing 195e5 is a legal in the "southern" hemisphere.
-      static const real eps = pow(real(0.5), Math::digits() - 25);
-      return eps;
-    }
-    // The smallest angle s.t., 90 - angeps() < 90 (approx 50e-12 arcsec)
-    static inline real angeps() {
-      using std::pow;
-      // 7 = ceil(log_2(90))
-      static const real angeps = pow(real(0.5), Math::digits() - 7);
-      return angeps;
-    }
     static const std::string hemispheres_;
     static const std::string utmcols_[3];
     static const std::string utmrow_;
@@ -107,6 +97,8 @@ namespace GeographicLib {
       utmevenrowshift_ = 5,
       // Maximum precision is um
       maxprec_ = 5 + 6,
+      // For generating digits at maxprec
+      mult_ = 1000000,
     };
     static void CheckCoords(bool utmp, bool& northp, real& x, real& y);
     static int UTMRow(int iband, int icol, int irow);
@@ -182,15 +174,16 @@ namespace GeographicLib {
      *   allocated.
      *
      * \e prec specifies the precision of the MGRS string as follows:
-     * - prec = −1 (min), only the grid zone is returned
-     * - prec = 0 (min), 100 km
-     * - prec = 1, 10 km
-     * - prec = 2, 1 km
-     * - prec = 3, 100 m
-     * - prec = 4, 10 m
-     * - prec = 5, 1 m
-     * - prec = 6, 0.1 m
-     * - prec = 11 (max), 1 μm
+     * - \e prec = −1 (min), only the grid zone is returned
+     * - \e prec = 0, 100 km
+     * - \e prec = 1, 10 km
+     * - \e prec = 2, 1 km
+     * - \e prec = 3, 100 m
+     * - \e prec = 4, 10 m
+     * - \e prec = 5, 1 m
+     * - \e prec = 6, 0.1 m
+     * - …
+     * - \e prec = 11 (max), 1 μm
      *
      * UTM eastings are allowed to be in the range [100 km, 900 km], northings
      * are allowed to be in in [0 km, 9500 km] for the northern hemisphere and
diff --git a/include/GeographicLib/MagneticCircle.hpp b/include/GeographicLib/MagneticCircle.hpp
index dae5cb4..085d419 100644
--- a/include/GeographicLib/MagneticCircle.hpp
+++ b/include/GeographicLib/MagneticCircle.hpp
@@ -48,7 +48,7 @@ namespace GeographicLib {
                    const CircularEngine& circ0, const CircularEngine& circ1)
       : _a(a)
       , _f(f)
-      , _lat(lat)
+      , _lat(Math::LatFix(lat))
       , _h(h)
       , _t(t)
       , _cphi(cphi)
diff --git a/include/GeographicLib/Math.hpp b/include/GeographicLib/Math.hpp
index cbe3f54..e1cb0f4 100644
--- a/include/GeographicLib/Math.hpp
+++ b/include/GeographicLib/Math.hpp
@@ -156,7 +156,9 @@ namespace GeographicLib {
      * @param[in] ndigits the number of bits of precision.
      * @return the resulting number of bits of precision.
      *
-     * This only has an effect when GEOGRAPHICLIB_PRECISION == 5.
+     * This only has an effect when GEOGRAPHICLIB_PRECISION == 5.  See also
+     * Utility::set_digits for caveats about when this routine should be
+     * called.
      **********************************************************************/
     static inline int set_digits(int ndigits) {
 #if GEOGRAPHICLIB_PRECISION != 5
@@ -373,6 +375,10 @@ namespace GeographicLib {
      * @param[in] z
      * @return <i>xy</i> + <i>z</i>, correctly rounded (on those platforms with
      *   support for the <code>fma</code> instruction).
+     *
+     * On platforms without the <code>fma</code> instruction, no attempt is
+     * made to improve on the result of a rounded multiplication followed by a
+     * rounded addition.
      **********************************************************************/
     template<typename T> static inline T fma(T x, T y, T z) {
 #if GEOGRAPHICLIB_CXX11_MATH
@@ -434,16 +440,24 @@ namespace GeographicLib {
     { T y = N < 0 ? 0 : *p++; while (--N >= 0) y = y * x + *p++; return y; }
 
     /**
-     * Normalize an angle (restricted input range).
+     * Normalize an angle.
      *
      * @tparam T the type of the argument and returned value.
      * @param[in] x the angle in degrees.
      * @return the angle reduced to the range [−180°, 180°).
      *
-     * \e x must lie in [−540°, 540°).
+     * The range of \e x is unrestricted.
      **********************************************************************/
-    template<typename T> static inline T AngNormalize(T x)
-    { return x >= 180 ? x - 360 : (x < -180 ? x + 360 : x); }
+    template<typename T> static inline T AngNormalize(T x) {
+#if GEOGRAPHICLIB_CXX11_MATH && GEOGRAPHICLIB_PRECISION != 4
+      using std::remainder;
+      x = remainder(x, T(360)); return x != 180 ? x : -180;
+#else
+      using std::fmod;
+      x = fmod(x, T(360));
+      return x < -180 ? x + 360 : (x < 180 ? x : x - 360);
+#endif
+    }
 
     /**
      * Normalize an arbitrary angle.
@@ -452,10 +466,21 @@ namespace GeographicLib {
      * @param[in] x the angle in degrees.
      * @return the angle reduced to the range [−180°, 180°).
      *
-     * The range of \e x is unrestricted.
+     * <b>DEPRECATED</b>: use AngNormalize instead.
      **********************************************************************/
     template<typename T> static inline T AngNormalize2(T x)
-    { using std::fmod; return AngNormalize<T>(fmod(x, T(360))); }
+    { return AngNormalize<T>(x); }
+
+    /**
+     * Normalize a latitude.
+     *
+     * @tparam T the type of the argument and returned value.
+     * @param[in] x the angle in degrees.
+     * @return x if it is in the range [−90°, 90°], otherwise
+     *   return NaN.
+     **********************************************************************/
+    template<typename T> static inline T LatFix(T x)
+    { using std::abs; return abs(x) > 90 ? NaN<T>() : x; }
 
     /**
      * Difference of two angles reduced to [−180°, 180°]
@@ -466,19 +491,26 @@ namespace GeographicLib {
      * @return \e y − \e x, reduced to the range [−180°,
      *   180°].
      *
-     * \e x and \e y must both lie in [−180°, 180°].  The result
-     * is equivalent to computing the difference exactly, reducing it to
-     * (−180°, 180°] and rounding the result.  Note that this
-     * prescription allows −180° to be returned (e.g., if \e x is
-     * tiny and negative and \e y = 180°).
+     * The result is equivalent to computing the difference exactly, reducing
+     * it to (−180°, 180°] and rounding the result.  Note that
+     * this prescription allows −180° to be returned (e.g., if \e x
+     * is tiny and negative and \e y = 180°).
      **********************************************************************/
     template<typename T> static inline T AngDiff(T x, T y) {
-      T t, d = sum(-x, y, t);
-      if ((d - T(180)) + t > T(0)) // y - x > 180
-        d -= T(360);            // exact
-      else if ((d + T(180)) + t <= T(0)) // y - x <= -180
-        d += T(360);            // exact
-      return d + t;
+#if GEOGRAPHICLIB_CXX11_MATH && GEOGRAPHICLIB_PRECISION != 4
+      using std::remainder;
+      T t, d = - AngNormalize(sum(remainder( x, T(360)),
+                                  remainder(-y, T(360)), t));
+#else
+      T t, d = - AngNormalize(sum(AngNormalize(x), AngNormalize(-y), t));
+#endif
+      // Here y - x = d - t (mod 360), exactly, where d is in (-180,180] and
+      // abs(t) <= eps (eps = 2^-45 for doubles).  The only case where the
+      // addition of t takes the result outside the range (-180,180] is d = 180
+      // and t < 0.  The case, d = -180 + eps, t = eps, can't happen, since
+      // sum would have returned the exact result in such a case (i.e., given t
+      // = 0).
+      return (d == 180 && t < 0 ? -180 : d) - t;
     }
 
     /**
@@ -501,41 +533,131 @@ namespace GeographicLib {
       GEOGRAPHICLIB_VOLATILE T y = abs(x);
       // The compiler mustn't "simplify" z - (z - y) to y
       y = y < z ? z - (z - y) : y;
+#if GEOGRAPHICLIB_PRECISION == 4
+      // With quad precision and x = +/-0, this gives y = -0.  So change test
+      // to x <= 0 here to force +0 to be returned.
+      return x <= 0 ? 0 - y : y;
+#elif GEOGRAPHICLIB_PRECISION == 5
+      // With mpfr, 0 - y is a call to +=(int) which doesn't fix the sign of -0
+      return x < 0 ? T(0) - y : y;
+#else
       return x < 0 ? 0 - y : y;
+#endif
     }
 
     /**
-     * Evaluate the tangent function with the argument in degrees
+     * Evaluate the sine and cosine function with the argument in degrees
+     *
+     * @tparam T the type of the arguments.
+     * @param[in] x in degrees.
+     * @param[out] sinx sin(<i>x</i>).
+     * @param[out] cosx cos(<i>x</i>).
+     *
+     * The results obey exactly the elementary properties of the trigonometric
+     * functions, e.g., sin 9° = cos 81° = − sin 123456789°.
+     **********************************************************************/
+    template<typename T> static inline void sincosd(T x, T& sinx, T& cosx) {
+      // In order to minimize round-off errors, this function exactly reduces
+      // the argument to the range [-45, 45] before converting it to radians.
+      using std::sin; using std::cos;
+      T r; int q;
+#if GEOGRAPHICLIB_CXX11_MATH && GEOGRAPHICLIB_PRECISION <= 3 && \
+  !defined(__GNUC__)
+      // Disable for gcc because of bug in glibc version < 2.22, see
+      //   https://sourceware.org/bugzilla/show_bug.cgi?id=17569
+      // Once this fix is widely deployed, should insert a runtime test for the
+      // glibc version number.
+      using std::remquo;
+      r = remquo(x, T(90), &q);
+#else
+      using std::fmod; using std::floor;
+      r = fmod(x, T(360));
+      q = int(floor(r / 90 + T(0.5)));
+      r -= 90 * q;
+#endif
+      // now abs(r) <= 45
+      r *= degree();
+      // Possibly could call the gnu extension sincos
+      T s = sin(r), c = cos(r);
+      switch (unsigned(q) & 3U) {
+      case 0U: sinx =     s; cosx =     c; break;
+      case 1U: sinx =     c; cosx = 0 - s; break;
+      case 2U: sinx = 0 - s; cosx = 0 - c; break;
+      default: sinx = 0 - c; cosx =     s; break; // case 3U
+      }
+    }
+
+    /**
+     * Evaluate the sine function with the argument in degrees
      *
      * @tparam T the type of the argument and the returned value.
      * @param[in] x in degrees.
-     * @return tan(<i>x</i>).
+     * @return sin(<i>x</i>).
+     **********************************************************************/
+    template<typename T> static inline T sind(T x) {
+      // See sincosd
+      using std::sin; using std::cos;
+      T r; int q;
+#if GEOGRAPHICLIB_CXX11_MATH && GEOGRAPHICLIB_PRECISION <= 3 && \
+  !defined(__GNUC__)
+      using std::remquo;
+      r = remquo(x, T(90), &q);
+#else
+      using std::fmod; using std::floor;
+      r = fmod(x, T(360));
+      q = int(floor(r / 90 + T(0.5)));
+      r -= 90 * q;
+#endif
+      // now abs(r) <= 45
+      r *= degree();
+      unsigned p = unsigned(q);
+      r = p & 1U ? cos(r) : sin(r);
+      return p & 2U ? 0 - r : r;
+    }
+
+    /**
+     * Evaluate the cosine function with the argument in degrees
      *
-     * If \e x = ±90°, then a suitably large (but finite) value is
-     * returned.
-     **********************************************************************/
-    template<typename T> static inline T tand(T x) {
-      using std::abs; using std::tan;
-      static const T overflow = 1 / Math::sq(std::numeric_limits<T>::epsilon());
-      return abs(x) != 90 ? tan(x * Math::degree()) :
-        (x < 0 ? -overflow : overflow);
+     * @tparam T the type of the argument and the returned value.
+     * @param[in] x in degrees.
+     * @return cos(<i>x</i>).
+     **********************************************************************/
+    template<typename T> static inline T cosd(T x) {
+      // See sincosd
+      using std::sin; using std::cos;
+      T r; int q;
+#if GEOGRAPHICLIB_CXX11_MATH && GEOGRAPHICLIB_PRECISION <= 3 && \
+  !defined(__GNUC__)
+      using std::remquo;
+      r = remquo(x, T(90), &q);
+#else
+      using std::fmod; using std::floor;
+      r = fmod(x, T(360));
+      q = int(floor(r / 90 + T(0.5)));
+      r -= 90 * q;
+#endif
+      // now abs(r) <= 45
+      r *= degree();
+      unsigned p = unsigned(q + 1);
+      r = p & 1U ? cos(r) : sin(r);
+      return p & 2U ? 0 - r : r;
     }
 
     /**
-     * Evaluate the atan function with the result in degrees
+     * Evaluate the tangent function with the argument in degrees
      *
      * @tparam T the type of the argument and the returned value.
-     * @param[in] x
-     * @return atan(<i>x</i>) in degrees.
+     * @param[in] x in degrees.
+     * @return tan(<i>x</i>).
      *
-     * Large values for the argument return ±90°
+     * If \e x = ±90°, then a suitably large (but finite) value is
+     * returned.
      **********************************************************************/
-    template<typename T> static inline T atand(T x) {
-      using std::abs; using std::atan;
-      static const T
-        overflow = 1 / (Math::sq(std::numeric_limits<T>::epsilon()) * 100);
-      return !(abs(x) >= overflow) ? atan(x) / Math::degree() :
-        (x > 0 ? 90 : -90);
+    template<typename T> static inline T tand(T x) {
+      static const T overflow = 1 / sq(std::numeric_limits<T>::epsilon());
+      T s, c;
+      sincosd(x, s, c);
+      return c ? s / c : (s < 0 ? -overflow : overflow);
     }
 
     /**
@@ -546,15 +668,47 @@ namespace GeographicLib {
      * @param[in] x
      * @return atan2(<i>y</i>, <i>x</i>) in degrees.
      *
-     * The result is in the range [−180° 180°).
+     * The result is in the range [−180° 180°).  N.B.,
+     * atan2d(±0, −1) = −180°; atan2d(+ε,
+     * −1) = +180°, for ε positive and tiny;
+     * atan2d(±0, 1) = ±0°.
      **********************************************************************/
     template<typename T> static inline T atan2d(T y, T x) {
-      using std::atan2;
-      // The "0 -" converts -0 to +0.
-      return 0 - atan2(-y, x) / Math::degree();
+      // In order to minimize round-off errors, this function rearranges the
+      // arguments so that result of atan2 is in the range [-pi/4, pi/4] before
+      // converting it to degrees and mapping the result to the correct
+      // quadrant.
+      using std::atan2; using std::abs;
+      int q = 0;
+      if (abs(y) > abs(x)) { std::swap(x, y); q = 2; }
+      if (x < 0) { x = -x; ++q; }
+      // here x >= 0 and x >= abs(y), so angle is in [-pi/4, pi/4]
+      T ang = atan2(y, x) / degree();
+      switch (q) {
+        // Note that atan2d(-0.0, 1.0) will return -0.  However, we expect that
+        // atan2d will not be called with y = -0.  If need be, include
+        //
+        //   case 0: ang = 0 + ang; break;
+        //
+        // and handle mpfr as in AngRound.
+      case 1: ang = (y > 0 ? 180 : -180) - ang; break;
+      case 2: ang =  90 - ang; break;
+      case 3: ang = -90 + ang; break;
+      }
+      return ang;
     }
 
     /**
+     * Evaluate the atan function with the result in degrees
+     *
+     * @tparam T the type of the argument and the returned value.
+     * @param[in] x
+     * @return atan(<i>x</i>) in degrees.
+     **********************************************************************/
+    template<typename T> static inline T atand(T x)
+    { return atan2d(x, T(1)); }
+
+    /**
      * Evaluate <i>e</i> atanh(<i>e x</i>)
      *
      * @tparam T the type of the argument and the returned value.
diff --git a/include/GeographicLib/OSGB.hpp b/include/GeographicLib/OSGB.hpp
index 9ceec06..ec55fb8 100644
--- a/include/GeographicLib/OSGB.hpp
+++ b/include/GeographicLib/OSGB.hpp
@@ -76,8 +76,7 @@ namespace GeographicLib {
      * @param[out] gamma meridian convergence at point (degrees).
      * @param[out] k scale of projection at point.
      *
-     * \e lat should be in the range [−90°, 90°]; \e lon
-     * should be in the range [−540°, 540°).
+     * \e lat should be in the range [−90°, 90°].
      **********************************************************************/
     static void Forward(real lat, real lon,
                         real& x, real& y, real& gamma, real& k) {
diff --git a/include/GeographicLib/PolarStereographic.hpp b/include/GeographicLib/PolarStereographic.hpp
index 56afae0..fd9e90f 100644
--- a/include/GeographicLib/PolarStereographic.hpp
+++ b/include/GeographicLib/PolarStereographic.hpp
@@ -74,8 +74,7 @@ namespace GeographicLib {
      *
      * No false easting or northing is added.  \e lat should be in the range
      * (−90°, 90°] for \e northp = true and in the range
-     * [−90°, 90°) for \e northp = false; \e lon should
-     * be in the range [−540°, 540°).
+     * [−90°, 90°) for \e northp = false.
      **********************************************************************/
     void Forward(bool northp, real lat, real lon,
                  real& x, real& y, real& gamma, real& k) const;
diff --git a/include/GeographicLib/PolygonArea.hpp b/include/GeographicLib/PolygonArea.hpp
index 5fde947..e3cf32f 100644
--- a/include/GeographicLib/PolygonArea.hpp
+++ b/include/GeographicLib/PolygonArea.hpp
@@ -2,7 +2,7 @@
  * \file PolygonArea.hpp
  * \brief Header for GeographicLib::PolygonAreaT class
  *
- * Copyright (c) Charles Karney (2010-2014) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2010-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -87,14 +87,23 @@ namespace GeographicLib {
     // an alternate version of transit to deal with longitudes in the direct
     // problem.
     static inline int transitdirect(real lon1, real lon2) {
-      using std::fmod;
       // We want to compute exactly
       //   int(floor(lon2 / 360)) - int(floor(lon1 / 360))
-      // Since we only need the parity of the result we can use std::remquo but
-      // this is buggy with g++ 4.8.3 and requires C++11.  So instead we do
+      // Since we only need the parity of the result we can use std::remquo;
+      // but this is buggy with g++ 4.8.3 (glibc version < 2.22), see
+      //   https://sourceware.org/bugzilla/show_bug.cgi?id=17569
+      // and requires C++11.  So instead we do
+#if GEOGRAPHICLIB_CXX11_MATH && GEOGRAPHICLIB_PRECISION != 4
+      using std::remainder;
+      lon1 = remainder(lon1, real(720)); lon2 = remainder(lon2, real(720));
+      return ( (lon2 >= 0 && lon2 < 360 ? 0 : 1) -
+               (lon1 >= 0 && lon1 < 360 ? 0 : 1) );
+#else
+      using std::fmod;
       lon1 = fmod(lon1, real(720)); lon2 = fmod(lon2, real(720));
       return ( ((lon2 >= 0 && lon2 < 360) || lon2 < -360 ? 0 : 1) -
                ((lon1 >= 0 && lon1 < 360) || lon1 < -360 ? 0 : 1) );
+#endif
     }
   public:
 
@@ -131,8 +140,7 @@ namespace GeographicLib {
      * @param[in] lat the latitude of the point (degrees).
      * @param[in] lon the longitude of the point (degrees).
      *
-     * \e lat should be in the range [−90°, 90°] and \e
-     * lon should be in the range [−540°, 540°).
+     * \e lat should be in the range [−90°, 90°].
      **********************************************************************/
     void AddPoint(real lat, real lon);
 
@@ -142,9 +150,8 @@ namespace GeographicLib {
      * @param[in] azi azimuth at current point (degrees).
      * @param[in] s distance from current point to next point (meters).
      *
-     * \e azi should be in the range [−540°, 540°).  This does
-     * nothing if no points have been added yet.  Use PolygonAreaT::CurrentPoint
-     * to determine the position of the new vertex.
+     * This does nothing if no points have been added yet.  Use
+     * PolygonAreaT::CurrentPoint to determine the position of the new vertex.
      **********************************************************************/
     void AddEdge(real azi, real s);
 
@@ -188,8 +195,7 @@ namespace GeographicLib {
      *   constructor.
      * @return the number of points.
      *
-     * \e lat should be in the range [−90°, 90°] and \e
-     * lon should be in the range [−540°, 540°).
+     * \e lat should be in the range [−90°, 90°].
      **********************************************************************/
     unsigned TestPoint(real lat, real lon, bool reverse, bool sign,
                        real& perimeter, real& area) const;
@@ -216,8 +222,6 @@ namespace GeographicLib {
      *   (meters<sup>2</sup>); only set if polyline is false in the
      *   constructor.
      * @return the number of points.
-     *
-     * \e azi should be in the range [−540°, 540°).
      **********************************************************************/
     unsigned TestEdge(real azi, real s, bool reverse, bool sign,
                       real& perimeter, real& area) const;
diff --git a/include/GeographicLib/Rhumb.hpp b/include/GeographicLib/Rhumb.hpp
index 0e2bcb1..58c4db8 100644
--- a/include/GeographicLib/Rhumb.hpp
+++ b/include/GeographicLib/Rhumb.hpp
@@ -262,8 +262,7 @@ namespace GeographicLib {
      * @param[out] lon2 longitude of point 2 (degrees).
      * @param[out] S12 area under the rhumb line (meters<sup>2</sup>).
      *
-     * \e lat1 should be in the range [−90°, 90°]; \e lon1 and \e
-     * azi12 should be in the range [−540°, 540°).  The value of
+     * \e lat1 should be in the range [−90°, 90°].  The value of
      * \e lon2 returned is in the range [−180°, 180°).
      *
      * If point 1 is a pole, the cosine of its latitude is taken to be
@@ -313,10 +312,7 @@ namespace GeographicLib {
      * .
      * With the Rhumb::LONG_UNROLL bit set, the quantity \e lon2 −
      * \e lon1 indicates how many times and in what sense the rhumb line
-     * encircles the ellipsoid.  Because \e lon2 might be outside the normal
-     * allowed range for longitudes, [−540°, 540°), be sure to
-     * normalize it with Math::AngNormalize2 before using it in other
-     * GeographicLib calls.
+     * encircles the ellipsoid.
      **********************************************************************/
     void GenDirect(real lat1, real lon1, real azi12, real s12, unsigned outmask,
                    real& lat2, real& lon2, real& S12) const;
@@ -335,8 +331,7 @@ namespace GeographicLib {
      * The shortest rhumb line is found.  If the end points are on opposite
      * meridians, there are two shortest rhumb lines and the east-going one is
      * chosen.  \e lat1 and \e lat2 should be in the range [−90°,
-     * 90°]; \e lon1 and \e lon2 should be in the range [−540°,
-     * 540°).  The value of \e azi12 returned is in the range
+     * 90°].  The value of \e azi12 returned is in the range
      * [−180°, 180°).
      *
      * If either point is a pole, the cosine of its latitude is taken to be
@@ -391,8 +386,7 @@ namespace GeographicLib {
      * @param[in] azi12 azimuth of the rhumb line (degrees).
      * @return a RhumbLine object.
      *
-     * \e lat1 should be in the range [−90°, 90°]; \e lon1 and \e
-     * azi12 should be in the range [−540°, 540°).
+     * \e lat1 should be in the range [−90°, 90°].
      *
      * If point 1 is a pole, the cosine of its latitude is taken to be
      * 1/ε<sup>2</sup> (where ε is 2<sup>-52</sup>).  This
@@ -558,10 +552,7 @@ namespace GeographicLib {
      * .
      * With the RhumbLine::LONG_UNROLL bit set, the quantity \e lon2 − \e
      * lon1 indicates how many times and in what sense the rhumb line encircles
-     * the ellipsoid.  Because \e lon2 might be outside the normal allowed
-     * range for longitudes, [−540°, 540°), be sure to normalize
-     * it with Math::AngNormalize2 before using it in other GeographicLib
-     * calls.
+     * the ellipsoid.
      *
      * If \e s12 is large enough that the rhumb line crosses a pole, the
      * longitude of point 2 is indeterminate (a NaN is returned for \e lon2 and
diff --git a/include/GeographicLib/SphericalHarmonic.hpp b/include/GeographicLib/SphericalHarmonic.hpp
index a084ea3..0351837 100644
--- a/include/GeographicLib/SphericalHarmonic.hpp
+++ b/include/GeographicLib/SphericalHarmonic.hpp
@@ -44,18 +44,23 @@ namespace GeographicLib {
    * implementation.
    *
    * References:
-   * - C. W. Clenshaw, A note on the summation of Chebyshev series,
+   * - C. W. Clenshaw,
+   *   <a href="https://dx.doi.org/10.1090/S0025-5718-1955-0071856-0">
+   *   A note on the summation of Chebyshev series</a>,
    *   %Math. Tables Aids Comput. 9(51), 118--120 (1955).
    * - R. E. Deakin, Derivatives of the earth's potentials, Geomatics
    *   Research Australasia 68, 31--60, (June 1998).
    * - W. A. Heiskanen and H. Moritz, Physical Geodesy, (Freeman, San
    *   Francisco, 1967).  (See Sec. 1-14, for a definition of Pbar.)
-   * - S. A. Holmes and W. E. Featherstone, A unified approach to the Clenshaw
-   *   summation and the recursive computation of very high degree and order
-   *   normalised associated Legendre functions, J. Geodesy 76(5),
-   *   279--299 (2002).
-   * - C. C. Tscherning and K. Poder, Some geodetic applications of Clenshaw
-   *   summation, Boll. Geod. Sci. Aff. 41(4), 349--375 (1982).
+   * - S. A. Holmes and W. E. Featherstone,
+   *   <a href="https://dx.doi.org/10.1007/s00190-002-0216-2">
+   *   A unified approach to the Clenshaw summation and the recursive
+   *   computation of very high degree and order normalised associated Legendre
+   *   functions</a>, J. Geodesy 76(5), 279--299 (2002).
+   * - C. C. Tscherning and K. Poder,
+   *   <a href="http://cct.gfy.ku.dk/publ_cct/cct80.pdf">
+   *   Some geodetic applications of Clenshaw summation</a>,
+   *   Boll. Geod. Sci. Aff. 41(4), 349--375 (1982).
    *
    * Example of use:
    * \include example-SphericalHarmonic.cpp
diff --git a/include/GeographicLib/TransverseMercator.hpp b/include/GeographicLib/TransverseMercator.hpp
index 52032d2..b92b611 100644
--- a/include/GeographicLib/TransverseMercator.hpp
+++ b/include/GeographicLib/TransverseMercator.hpp
@@ -45,9 +45,18 @@ namespace GeographicLib {
    * error is 5 nm (5 nanometers), ground distance, for all positions within 35
    * degrees of the central meridian.  The error in the convergence is 2
    * × 10<sup>−15</sup>" and the relative error in the scale
-   * is 6 − 10<sup>−12</sup>%%.  See Sec. 4 of
+   * is 6 × 10<sup>−12</sup>%%.  See Sec. 4 of
    * <a href="http://arxiv.org/abs/1002.1417">arXiv:1002.1417</a> for details.
    * The speed penalty in going to 6th order is only about 1%.
+   *
+   * There's a singularity in the projection at φ = 0°, λ
+   * − λ<sub>0</sub> = ±(1 − \e e)90° (≈
+   * ±82.6° for the WGS84 ellipsoid), where \e e is the
+   * eccentricity.  Beyond this point, the series ceases to converge and the
+   * results from this method will be garbage.  To be on the safe side, don't
+   * use this method if the angular distance from the central meridian exceeds
+   * (1 − 2e)90° (≈ 75° for the WGS84 ellipsoid)
+   *
    * TransverseMercatorExact is an alternative implementation of the projection
    * using exact formulas which yield accurate (to 8 nm) results over the
    * entire ellipsoid.
@@ -113,8 +122,7 @@ namespace GeographicLib {
      * @param[out] k scale of projection at point.
      *
      * No false easting or northing is added. \e lat should be in the range
-     * [−90°, 90°]; \e lon and \e lon0 should be in the
-     * range [−540°, 540°).
+     * [−90°, 90°].
      **********************************************************************/
     void Forward(real lon0, real lat, real lon,
                  real& x, real& y, real& gamma, real& k) const;
@@ -130,9 +138,8 @@ namespace GeographicLib {
      * @param[out] gamma meridian convergence at point (degrees).
      * @param[out] k scale of projection at point.
      *
-     * No false easting or northing is added.  \e lon0 should be in the range
-     * [−540°, 540°).  The value of \e lon returned is in
-     * the range [−180°, 180°).
+     * No false easting or northing is added.  The value of \e lon returned is
+     * in the range [−180°, 180°).
      **********************************************************************/
     void Reverse(real lon0, real x, real y,
                  real& lat, real& lon, real& gamma, real& k) const;
diff --git a/include/GeographicLib/TransverseMercatorExact.hpp b/include/GeographicLib/TransverseMercatorExact.hpp
index 66f16bf..8d4d546 100644
--- a/include/GeographicLib/TransverseMercatorExact.hpp
+++ b/include/GeographicLib/TransverseMercatorExact.hpp
@@ -84,12 +84,6 @@ namespace GeographicLib {
     real _a, _f, _k0, _mu, _mv, _e;
     bool _extendp;
     EllipticFunction _Eu, _Ev;
-    static inline real overflow() {
-      // Overflow value s.t. atan(overflow_) = pi/2
-      static const real
-        overflow = 1 / Math::sq(std::numeric_limits<real>::epsilon());
-      return overflow;
-    }
 
     void zeta(real u, real snu, real cnu, real dnu,
               real v, real snv, real cnv, real dnv,
@@ -184,8 +178,7 @@ namespace GeographicLib {
      * @param[out] k scale of projection at point.
      *
      * No false easting or northing is added. \e lat should be in the range
-     * [−90°, 90°]; \e lon and \e lon0 should be in the
-     * range [−540°, 540°).
+     * [−90°, 90°].
      **********************************************************************/
     void Forward(real lon0, real lat, real lon,
                  real& x, real& y, real& gamma, real& k) const;
@@ -201,9 +194,8 @@ namespace GeographicLib {
      * @param[out] gamma meridian convergence at point (degrees).
      * @param[out] k scale of projection at point.
      *
-     * No false easting or northing is added.  \e lon0 should be in the range
-     * [−540°, 540°).  The value of \e lon returned is in
-     * the range [−180°, 180°).
+     * No false easting or northing is added.  The value of \e lon returned is
+     * in the range [−180°, 180°).
      **********************************************************************/
     void Reverse(real lon0, real x, real y,
                  real& lat, real& lon, real& gamma, real& k) const;
diff --git a/include/GeographicLib/UTMUPS.hpp b/include/GeographicLib/UTMUPS.hpp
index a643abf..d77bd5e 100644
--- a/include/GeographicLib/UTMUPS.hpp
+++ b/include/GeographicLib/UTMUPS.hpp
@@ -2,7 +2,7 @@
  * \file UTMUPS.hpp
  * \brief Header for GeographicLib::UTMUPS class
  *
- * Copyright (c) Charles Karney (2008-2014) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2008-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -89,7 +89,6 @@ namespace GeographicLib {
     static const int epsgS   = 32761; // EPSG code for UPS   S
     static real CentralMeridian(int zone)
     { return real(6 * zone - 183); }
-    static void CheckLatLon(real lat, real lon);
     // Throw an error if easting or northing are outside standard ranges.  If
     // throwp = false, return bool instead.
     static bool CheckCoords(bool utmp, bool northp, real x, real y,
@@ -195,8 +194,6 @@ namespace GeographicLib {
      *   coordinates (default = false).
      * @exception GeographicErr if \e lat is not in [−90°,
      *   90°].
-     * @exception GeographicErr if \e lon is not in [−540°,
-     *   540°).
      * @exception GeographicErr if the resulting \e x or \e y is out of allowed
      *   range (see Reverse); in this case, these arguments are unchanged.
      *
diff --git a/include/GeographicLib/Utility.hpp b/include/GeographicLib/Utility.hpp
index 69feaee..a015632 100644
--- a/include/GeographicLib/Utility.hpp
+++ b/include/GeographicLib/Utility.hpp
@@ -2,7 +2,7 @@
  * \file Utility.hpp
  * \brief Header for GeographicLib::Utility class
  *
- * Copyright (c) Charles Karney (2011-2014) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2011-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -299,14 +299,16 @@ namespace GeographicLib {
 #if GEOGRAPHICLIB_PRECISION == 4
       // boost-quadmath treats precision == 0 as "use as many digits as
       // necessary", so...
-      using std::floor;
+      using std::floor; using std::fmod;
       if (p == 0) {
-        long long ix = (long long)(floor(x + Math::real(0.5)));
+        x += Math::real(0.5);
+        Math::real ix = floor(x);
         // Implement the "round ties to even" rule
-        if (Math::real(ix) == x + Math::real(0.5) && (ix % 2) == 1)
-          --ix;
-        s << ix;
-        return s.str();
+        x = (ix == x && fmod(ix, Math::real(2)) == 1) ? ix - 1 : ix;
+        s << std::fixed << std::setprecision(1) << x;
+        std::string r(s.str());
+        // strip off trailing ".0"
+        return r.substr(0, (std::max)(int(r.size()) - 2, 0));
       }
 #endif
       if (p >= 0) s << std::fixed << std::setprecision(p);
@@ -572,7 +574,13 @@ namespace GeographicLib {
      *   256 (i.e., about 77 decimal digits).
      * @return the resulting number of bits of precision.
      *
-     * This only has an effect when GEOGRAPHICLIB_PRECISION == 5.
+     * This only has an effect when GEOGRAPHICLIB_PRECISION == 5.  The
+     * precision should only be set once and before calls to any other
+     * GeographicLib functions.  (Several functions, for example Math::pi(),
+     * cache the return value in a static local variable.  The precision needs
+     * to be set before a call to any such functions.)  In multi-threaded
+     * applications, it is necessary also to set the precision in each thread
+     * (see the example GeoidToGTX.cpp).
      **********************************************************************/
     static int set_digits(int ndigits = 0);
 
diff --git a/include/Makefile.am b/include/Makefile.am
index 89ff622..2415eb4 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -12,6 +12,7 @@ nobase_include_HEADERS = GeographicLib/Accumulator.hpp \
 			GeographicLib/DMS.hpp \
 			GeographicLib/Ellipsoid.hpp \
 			GeographicLib/EllipticFunction.hpp \
+			GeographicLib/GARS.hpp \
 			GeographicLib/GeoCoords.hpp \
 			GeographicLib/Geocentric.hpp \
 			GeographicLib/Geodesic.hpp \
@@ -20,6 +21,7 @@ nobase_include_HEADERS = GeographicLib/Accumulator.hpp \
 			GeographicLib/GeodesicLineExact.hpp \
 			GeographicLib/Geohash.hpp \
 			GeographicLib/Geoid.hpp \
+			GeographicLib/Georef.hpp \
 			GeographicLib/Gnomonic.hpp \
 			GeographicLib/GravityCircle.hpp \
 			GeographicLib/GravityModel.hpp \
diff --git a/include/Makefile.in b/include/Makefile.in
index 98839f3..18297df 100644
--- a/include/Makefile.in
+++ b/include/Makefile.in
@@ -309,6 +309,7 @@ nobase_include_HEADERS = GeographicLib/Accumulator.hpp \
 			GeographicLib/DMS.hpp \
 			GeographicLib/Ellipsoid.hpp \
 			GeographicLib/EllipticFunction.hpp \
+			GeographicLib/GARS.hpp \
 			GeographicLib/GeoCoords.hpp \
 			GeographicLib/Geocentric.hpp \
 			GeographicLib/Geodesic.hpp \
@@ -317,6 +318,7 @@ nobase_include_HEADERS = GeographicLib/Accumulator.hpp \
 			GeographicLib/GeodesicLineExact.hpp \
 			GeographicLib/Geohash.hpp \
 			GeographicLib/Geoid.hpp \
+			GeographicLib/Georef.hpp \
 			GeographicLib/Gnomonic.hpp \
 			GeographicLib/GravityCircle.hpp \
 			GeographicLib/GravityModel.hpp \
diff --git a/include/Makefile.mk b/include/Makefile.mk
index 6355a8a..6337b24 100644
--- a/include/Makefile.mk
+++ b/include/Makefile.mk
@@ -6,6 +6,7 @@ MODULES = Accumulator \
 	DMS \
 	Ellipsoid \
 	EllipticFunction \
+	GARS \
 	GeoCoords \
 	Geocentric \
 	Geodesic \
@@ -14,6 +15,7 @@ MODULES = Accumulator \
 	GeodesicLineExact \
 	Geohash \
 	Geoid \
+	Georef \
 	Gnomonic \
 	GravityCircle \
 	GravityModel \
diff --git a/java/direct/pom.xml b/java/direct/pom.xml
index be0fdb3..297706d 100644
--- a/java/direct/pom.xml
+++ b/java/direct/pom.xml
@@ -9,7 +9,7 @@
   <groupId>net.sf.geographiclib.example</groupId>
   <artifactId>Direct</artifactId>
   <name>Direct</name>
-  <version>1.43</version>
+  <version>1.44-SNAPSHOT</version>
 
   <packaging>jar</packaging>
 
@@ -28,7 +28,7 @@
     <dependency>
       <groupId>net.sf.geographiclib</groupId>
       <artifactId>GeographicLib-Java</artifactId>
-      <version>1.43</version>
+      <version>1.44</version>
     </dependency>
   </dependencies>
 
diff --git a/java/inverse/pom.xml b/java/inverse/pom.xml
index b85e0f2..aa231a4 100644
--- a/java/inverse/pom.xml
+++ b/java/inverse/pom.xml
@@ -9,7 +9,7 @@
   <groupId>net.sf.geographiclib.example</groupId>
   <artifactId>Inverse</artifactId>
   <name>Inverse</name>
-  <version>1.43</version>
+  <version>1.44-SNAPSHOT</version>
 
   <packaging>jar</packaging>
 
@@ -28,7 +28,7 @@
     <dependency>
       <groupId>net.sf.geographiclib</groupId>
       <artifactId>GeographicLib-Java</artifactId>
-      <version>1.43</version>
+      <version>1.44</version>
     </dependency>
   </dependencies>
 
diff --git a/java/planimeter/pom.xml b/java/planimeter/pom.xml
index dbc5847..6aee27c 100644
--- a/java/planimeter/pom.xml
+++ b/java/planimeter/pom.xml
@@ -9,7 +9,7 @@
   <groupId>net.sf.geographiclib.example</groupId>
   <artifactId>Planimeter</artifactId>
   <name>Planimeter</name>
-  <version>1.43</version>
+  <version>1.44-SNAPSHOT</version>
 
   <packaging>jar</packaging>
 
@@ -28,7 +28,7 @@
     <dependency>
       <groupId>net.sf.geographiclib</groupId>
       <artifactId>GeographicLib-Java</artifactId>
-      <version>1.43</version>
+      <version>1.44</version>
     </dependency>
   </dependencies>
 
diff --git a/java/pom.xml b/java/pom.xml
index dea78eb..151aa1b 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -8,7 +8,7 @@
 
   <groupId>net.sf.geographiclib</groupId>
   <artifactId>GeographicLib-Java</artifactId>
-  <version>1.43</version>
+  <version>1.44</version>
 
   <packaging>jar</packaging>
 
diff --git a/java/src/main/java/net/sf/geographiclib/GeoMath.java b/java/src/main/java/net/sf/geographiclib/GeoMath.java
index c7e0765..60113ca 100644
--- a/java/src/main/java/net/sf/geographiclib/GeoMath.java
+++ b/java/src/main/java/net/sf/geographiclib/GeoMath.java
@@ -1,7 +1,7 @@
 /**
  * Implementation of the net.sf.geographiclib.GeoMath class
  *
- * Copyright (c) Charles Karney (2013) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2013-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -111,7 +111,7 @@ public class GeoMath {
   }
 
   public static Pair norm(double sinx, double cosx) {
-    double r = GeoMath.hypot(sinx, cosx);
+    double r = hypot(sinx, cosx);
     return new Pair(sinx/r, cosx/r);
   }
 
@@ -178,21 +178,23 @@ public class GeoMath {
    * @param x the angle in degrees.
    * @return the angle reduced to the range [−180°, 180°).
    * <p>
-   * <i>x</i> must lie in [−540°, 540°).
+   * The range of <i>x</i> is unrestricted.
    **********************************************************************/
-  public static double AngNormalize(double x)
-  { return x >= 180 ? x - 360 : (x < -180 ? x + 360 : x); }
+  public static double AngNormalize(double x) {
+    x = x % 360.0;
+    return x < -180 ? x + 360 : (x < 180 ? x : x - 360);
+  }
 
   /**
-   * Normalize an arbitrary angle.
+   * Normalize a latitude.
    * <p>
    * @param x the angle in degrees.
-   * @return the angle reduced to the range [−180°, 180°).
-   * <p>
-   * The range of <i>x</i> is unrestricted.
+   * @return x if it is in the range [−90°, 90°], otherwise
+   *   return NaN.
    **********************************************************************/
-  public static double AngNormalize2(double x)
-  { return AngNormalize(x % 360.0); }
+  public static double LatFix(double x) {
+    return Math.abs(x) > 90 ? Double.NaN : x;
+  }
 
   /**
    * Difference of two angles reduced to [−180°, 180°]
@@ -210,13 +212,80 @@ public class GeoMath {
    **********************************************************************/
   public static double AngDiff(double x, double y) {
     double d, t;
-    { Pair r = sum(-x, y); d = r.first; t = r.second; }
-    if ((d - 180.0) + t > 0.0) // y - x > 180
-      d -= 360.0;            // exact
-    else if ((d + 180.0) + t <= 0.0) // y - x <= -180
-      d += 360.0;            // exact
-    return d + t;
+    {
+      Pair r = sum(AngNormalize(x), AngNormalize(-y));
+      d = - AngNormalize(r.first); t = r.second;
+    }
+    return (d == 180 && t < 0 ? -180 : d) - t;
   }
+
+  /**
+   * Evaluate the sine and cosine function with the argument in degrees
+   *
+   * @param x in degrees.
+   * @return Pair(<i>s</i>, <i>t</i>) with <i>s</i> = sin(<i>x</i>) and
+   *   <i>c</i> = cos(<i>x</i>).
+   *
+   * The results obey exactly the elementary properties of the trigonometric
+   * functions, e.g., sin 9° = cos 81° = − sin 123456789°.
+   **********************************************************************/
+  public static Pair sincosd(double x) {
+    // In order to minimize round-off errors, this function exactly reduces
+    // the argument to the range [-45, 45] before converting it to radians.
+    double r; int q;
+    r = x % 360.0;
+    q = (int)Math.floor(r / 90 + 0.5);
+    r -= 90 * q;
+    // now abs(r) <= 45
+    r *= degree;
+    // Possibly could call the gnu extension sincos
+    double s = Math.sin(r), c = Math.cos(r);
+    double sinx, cosx;
+    switch (q & 3) {
+    case  0: sinx =     s; cosx =     c; break;
+    case  1: sinx =     c; cosx = 0 - s; break;
+    case  2: sinx = 0 - s; cosx = 0 - c; break;
+    default: sinx = 0 - c; cosx =     s; break; // case 3
+    }
+    return new Pair(sinx, cosx);
+  }
+
+    /**
+     * Evaluate the atan2 function with the result in degrees
+     *
+     * @param y
+     * @param x
+     * @return atan2(<i>y</i>, <i>x</i>) in degrees.
+     *
+     * The result is in the range [−180° 180°).  N.B.,
+     * atan2d(±0, −1) = −180°; atan2d(+ε,
+     * −1) = +180°, for ε positive and tiny;
+     * atan2d(±0, 1) = ±0°.
+     **********************************************************************/
+  public static double atan2d(double y, double x) {
+    // In order to minimize round-off errors, this function rearranges the
+    // arguments so that result of atan2 is in the range [-pi/4, pi/4] before
+    // converting it to degrees and mapping the result to the correct
+    // quadrant.
+    int q = 0;
+    if (Math.abs(y) > Math.abs(x)) { double t; t = x; x = y; y = t; q = 2; }
+    if (x < 0) { x = -x; ++q; }
+    // here x >= 0 and x >= abs(y), so angle is in [-pi/4, pi/4]
+    double ang = Math.atan2(y, x) / degree;
+    switch (q) {
+      // Note that atan2d(-0.0, 1.0) will return -0.  However, we expect that
+      // atan2d will not be called with y = -0.  If need be, include
+      //
+      //   case 0: ang = 0 + ang; break;
+      //
+      // and handle mpfr as in AngRound.
+    case 1: ang = (y > 0 ? 180 : -180) - ang; break;
+    case 2: ang =  90 - ang; break;
+    case 3: ang = -90 + ang; break;
+    }
+    return ang;
+  }
+
   /**
    * Test for finiteness.
    * <p>
diff --git a/java/src/main/java/net/sf/geographiclib/Geodesic.java b/java/src/main/java/net/sf/geographiclib/Geodesic.java
index 0a19dad..3457745 100644
--- a/java/src/main/java/net/sf/geographiclib/Geodesic.java
+++ b/java/src/main/java/net/sf/geographiclib/Geodesic.java
@@ -1,7 +1,7 @@
 /**
  * Implementation of the net.sf.geographiclib.Geodesic class
  *
- * Copyright (c) Charles Karney (2013-2014) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2013-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -300,10 +300,9 @@ public class Geodesic {
    *   <i>lat1</i>, <i>lon1</i>, <i>azi1</i>, <i>lat2</i>, <i>lon2</i>,
    *   <i>azi2</i>, <i>s12</i>, <i>a12</i>.
    * <p>
-   * <i>lat1</i> should be in the range [−90°, 90°]; <i>lon1</i>
-   * and <i>azi1</i> should be in the range [−540°, 540°).  The
-   * values of <i>lon2</i> and <i>azi2</i> returned are in the range
-   * [−180°, 180°).
+   * <i>lat1</i> should be in the range [−90°, 90°].  The values
+   * of <i>lon2</i> and <i>azi2</i> returned are in the range [−180°,
+   * 180°).
    * <p>
    * If either point is at a pole, the azimuth is defined by keeping the
    * longitude fixed, writing <i>lat</i> = ±(90° − ε),
@@ -356,10 +355,9 @@ public class Geodesic {
    *   <i>lat1</i>, <i>lon1</i>, <i>azi1</i>, <i>lat2</i>, <i>lon2</i>,
    *   <i>azi2</i>, <i>s12</i>, <i>a12</i>.
    * <p>
-   * <i>lat1</i> should be in the range [−90°, 90°]; <i>lon1</i>
-   * and <i>azi1</i> should be in the range [−540°, 540°).  The
-   * values of <i>lon2</i> and <i>azi2</i> returned are in the range
-   * [−180°, 180°).
+   * <i>lat1</i> should be in the range [−90°, 90°].  The values
+   * of <i>lon2</i> and <i>azi2</i> returned are in the range [−180°,
+   * 180°).
    * <p>
    * If either point is at a pole, the azimuth is defined by keeping the
    * longitude fixed, writing <i>lat</i> = ±(90° − ε),
@@ -438,8 +436,11 @@ public class Geodesic {
    * <li>
    *   <i>outmask</i> |= GeodesicMask.ALL for all of the above;
    * <li>
-   *   <i>outmask</i> |= GeodesicMask.LONG_UNROLL to unroll <i>lon2</i>
-   *   (instead of reducing it to the range [−180°, 180°)).
+   *   <i>outmask</i> |= GeodesicMask.LONG_UNROLL, if set then <i>lon1</i> is
+   *   unchanged and <i>lon2</i> − <i>lon1</i> indicates how many times
+   *   and in what sense the geodesic encircles the ellipsoid.  Otherwise
+   *   <i>lon1</i> and <i>lon2</i> are both reduced to the range
+   *   [−180°, 180°).
    * </ul>
    * <p>
    * The function value <i>a12</i> is always computed and returned and this
@@ -471,9 +472,8 @@ public class Geodesic {
    *   <i>azi2</i>, <i>s12</i>, <i>a12</i>.
    * <p>
    * <i>lat1</i> and <i>lat2</i> should be in the range [−90°,
-   * 90°]; <i>lon1</i> and <i>lon2</i> should be in the range
-   * [−540°, 540°).  The values of <i>azi1</i> and <i>azi2</i>
-   * returned are in the range [−180°, 180°).
+   * 90°].  The values of <i>azi1</i> and <i>azi2</i> returned are in the
+   * range [−180°, 180°).
    * <p>
    * If either point is at a pole, the azimuth is defined by keeping the
    * longitude fixed, writing <i>lat</i> = ±(90° − ε),
@@ -519,6 +519,11 @@ public class Geodesic {
    *   <i>outmask</i> |= GeodesicMask.AREA for the area <i>S12</i>;
    * <li>
    *   <i>outmask</i> |= GeodesicMask.ALL for all of the above.
+   * <li>
+   *   <i>outmask</i> |= GeodesicMask.LONG_UNROLL, if set then <i>lon1</i> is
+   *   unchanged and <i>lon2</i> − <i>lon1</i> indicates whether the
+   *   geodesic is east going or west going.  Otherwise <i>lon1</i> and
+   *   <i>lon2</i> are both reduced to the range [−180°, 180°).
    * </ul>
    * <p>
    * <i>lat1</i>, <i>lon1</i>, <i>lat2</i>, <i>lon2</i>, and <i>a12</i> are
@@ -528,22 +533,24 @@ public class Geodesic {
                               double lat2, double lon2, int outmask) {
     outmask &= GeodesicMask.OUT_MASK;
     GeodesicData r = new GeodesicData();
-    lon1 = GeoMath.AngNormalize(lon1);
-    lon2 = GeoMath.AngNormalize(lon2);
     // Compute longitude difference (AngDiff does this carefully).  Result is
     // in [-180, 180] but -180 is only for west-going geodesics.  180 is for
     // east-going and meridional geodesics.
+    r.lat1 = lat1 = GeoMath.LatFix(lat1); r.lat2 = lat2 = GeoMath.LatFix(lat2);
+    // If really close to the equator, treat as on equator.
+    lat1 = GeoMath.AngRound(lat1);
+    lat2 = GeoMath.AngRound(lat2);
     double lon12 = GeoMath.AngDiff(lon1, lon2);
+    if ((outmask & GeodesicMask.LONG_UNROLL) != 0) {
+      r.lon1 = lon1; r.lon2 = lon1 + lon12;
+    } else {
+      r.lon1 = GeoMath.AngNormalize(lon1); r.lon2 = GeoMath.AngNormalize(lon2);
+    }
     // If very close to being on the same half-meridian, then make it so.
     lon12 = GeoMath.AngRound(lon12);
     // Make longitude difference positive.
     int lonsign = lon12 >= 0 ? 1 : -1;
     lon12 *= lonsign;
-    // If really close to the equator, treat as on equator.
-    lat1 = GeoMath.AngRound(lat1);
-    lat2 = GeoMath.AngRound(lat2);
-    // Save input parameters post normalization
-    r.lat1 = lat1; r.lon1 = lon1; r.lat2 = lat2; r.lon2 = lon2;
     // Swap points so that point with higher (abs) latitude is point 1
     int swapp = Math.abs(lat1) >= Math.abs(lat2) ? 1 : -1;
     if (swapp < 0) {
@@ -566,22 +573,19 @@ public class Geodesic {
     // check, e.g., on verifying quadrants in atan2.  In addition, this
     // enforces some symmetries in the results returned.
 
-    double phi, sbet1, cbet1, sbet2, cbet2, s12x, m12x;
+    double sbet1, cbet1, sbet2, cbet2, s12x, m12x;
     s12x = m12x = Double.NaN;
 
-    phi = lat1 * GeoMath.degree;
-    // Ensure cbet1 = +epsilon at poles
-    sbet1 = _f1 * Math.sin(phi);
-    cbet1 = lat1 == -90 ? tiny_ : Math.cos(phi);
-    { Pair p = GeoMath.norm(sbet1, cbet1);
-      sbet1 = p.first; cbet1 = p.second; }
+    { Pair p = GeoMath.sincosd(lat1); sbet1 = _f1 * p.first; cbet1 = p.second; }
+    // Ensure cbet1 = +epsilon at poles; doing the fix on beta means that sig12
+    // will be <= 2*tiny for two points at the same pole.
+    { Pair p = GeoMath.norm(sbet1, cbet1); sbet1 = p.first; cbet1 = p.second; }
+    cbet1 = Math.max(tiny_, cbet1);
 
-    phi = lat2 * GeoMath.degree;
+    { Pair p = GeoMath.sincosd(lat2); sbet2 = _f1 * p.first; cbet2 = p.second; }
     // Ensure cbet2 = +epsilon at poles
-    sbet2 = _f1 * Math.sin(phi);
-    cbet2 = Math.abs(lat2) == 90 ? tiny_ : Math.cos(phi);
-    { Pair p = GeoMath.norm(sbet2, cbet2);
-      sbet2 = p.first; cbet2 = p.second; }
+    { Pair p = GeoMath.norm(sbet2, cbet2); sbet2 = p.first; cbet2 = p.second; }
+    cbet2 = Math.max(tiny_, cbet2);
 
     // If cbet1 < -sbet1, then cbet2 - cbet1 is a sensitive measure of the
     // |bet1| - |bet2|.  Alternatively (cbet1 >= -sbet1), abs(sbet2) + sbet1 is
@@ -604,9 +608,8 @@ public class Geodesic {
       dn2 = Math.sqrt(1 + _ep2 * GeoMath.sq(sbet2));
 
     double
-      lam12 = lon12 * GeoMath.degree,
-      slam12 = Math.abs(lon12) == 180 ? 0 : Math.sin(lam12),
-      clam12 = Math.cos(lam12);      // lon12 == 90 isn't interesting
+      lam12 = lon12 * GeoMath.degree, slam12, clam12;
+    { Pair p = GeoMath.sincosd(lon12); slam12 = p.first; clam12 = p.second; }
 
     double a12, sig12, calp1, salp1, calp2, salp2;
     a12 = sig12 = calp1 = salp1 = calp2 = salp2 = Double.NaN;
@@ -635,9 +638,9 @@ public class Geodesic {
                     csig1 * csig2 + ssig1 * ssig2);
       {
         LengthsV v =
-          Lengths(_n, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2,
-                  cbet1, cbet2,
-                  (outmask & GeodesicMask.GEODESICSCALE) != 0, C1a, C2a);
+          Lengths(_n, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2, cbet1, cbet2,
+                  outmask | GeodesicMask.DISTANCE | GeodesicMask.REDUCEDLENGTH,
+                  C1a, C2a);
         s12x = v.s12b; m12x = v.m12b;
         if ((outmask & GeodesicMask.GEODESICSCALE) != 0) {
           r.M12 = v.M12; r.M21 = v.M21;
@@ -651,6 +654,9 @@ public class Geodesic {
       // In fact, we will have sig12 > pi/2 for meridional geodesic which is
       // not a shortest path.
       if (sig12 < 1 || m12x >= 0) {
+        // Need at least 2, to handle 90 0 90 180
+        if (sig12 < 3 * tiny_)
+          sig12 = m12x = s12x = 0;
         m12x *= _b;
         s12x *= _b;
         a12 = sig12 / GeoMath.degree;
@@ -777,10 +783,16 @@ public class Geodesic {
                    Math.abs(salp1 - salp1b) + (calp1 - calp1b) < tolb_);
         }
         {
+          // Ensure that the reduced length and geodesic scale are computed in
+          // a "canonical" way, with the I2 integral.
+          int lengthmask = outmask |
+            ((outmask &
+              (GeodesicMask.REDUCEDLENGTH | GeodesicMask.GEODESICSCALE)) != 0 ?
+             GeodesicMask.DISTANCE : GeodesicMask.NONE);
           LengthsV v =
-            Lengths(eps, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2,
-                    cbet1, cbet2,
-                    (outmask & GeodesicMask.GEODESICSCALE) != 0, C1a, C2a);
+            Lengths(eps, sig12,
+                    ssig1, csig1, dn1, ssig2, csig2, dn2, cbet1, cbet2,
+                    lengthmask, C1a, C2a);
           s12x = v.s12b; m12x = v.m12b;
           if ((outmask & GeodesicMask.GEODESICSCALE) != 0) {
             r.M12 = v.M12; r.M21 = v.M21;
@@ -872,9 +884,8 @@ public class Geodesic {
     salp2 *= swapp * lonsign; calp2 *= swapp * latsign;
 
     if ((outmask & GeodesicMask.AZIMUTH) != 0) {
-      // minus signs give range [-180, 180). 0- converts -0 to +0.
-      r.azi1 = 0 - Math.atan2(-salp1, calp1) / GeoMath.degree;
-      r.azi2 = 0 - Math.atan2(-salp2, calp2) / GeoMath.degree;
+      r.azi1 = GeoMath.atan2d(salp1, calp1);
+      r.azi2 = GeoMath.atan2d(salp2, calp2);
     }
     // Returned value in [0, 180]
     r.a12 = a12;
@@ -889,9 +900,8 @@ public class Geodesic {
    * @param azi1 azimuth at point 1 (degrees).
    * @return a {@link GeodesicLine} object.
    * <p>
-   * <i>lat1</i> should be in the range [−90°, 90°]; <i>lon1</i>
-   * and <i>azi1</i> should be in the range [−540°, 540°).  The
-   * full set of capabilities is included.
+   * <i>lat1</i> should be in the range [−90°, 90°].  The full
+   * set of capabilities is included.
    * <p>
    * If the point is at a pole, the azimuth is defined by keeping the
    * <i>lon1</i> fixed, writing <i>lat1</i> = ±(90 − ε),
@@ -1031,31 +1041,56 @@ public class Geodesic {
                            double ssig1, double csig1, double dn1,
                            double ssig2, double csig2, double dn2,
                            double cbet1, double cbet2,
-                           boolean scalep,
+                           int outmask,
                            // Scratch areas of the right size
                            double C1a[], double C2a[]) {
     // Return m12b = (reduced length)/_b; also calculate s12b = distance/_b,
     // and m0 = coefficient of secular term in expression for reduced length.
+    outmask &= GeodesicMask.OUT_MASK;
     LengthsV v = new LengthsV(); // To hold s12b, m12b, m0, M12, M21;
-    C1f(eps, C1a);
-    C2f(eps, C2a);
-    double
-      A1m1 = A1m1f(eps),
-      AB1 = (1 + A1m1) * (SinCosSeries(true, ssig2, csig2, C1a) -
-                          SinCosSeries(true, ssig1, csig1, C1a)),
-      A2m1 = A2m1f(eps),
-      AB2 = (1 + A2m1) * (SinCosSeries(true, ssig2, csig2, C2a) -
-                          SinCosSeries(true, ssig1, csig1, C2a));
-    v.m0 = A1m1 - A2m1;
-    double J12 = v.m0 * sig12 + (AB1 - AB2);
-    // Missing a factor of _b.
-    // Add parens around (csig1 * ssig2) and (ssig1 * csig2) to ensure accurate
-    // cancellation in the case of coincident points.
-    v.m12b = dn2 * (csig1 * ssig2) - dn1 * (ssig1 * csig2) -
-      csig1 * csig2 * J12;
-    // Missing a factor of _b
-    v.s12b = (1 + A1m1) * sig12 + AB1;
-    if (scalep) {
+
+    double m0x = 0, J12 = 0, A1 = 0, A2 = 0;
+    if ((outmask & (GeodesicMask.DISTANCE | GeodesicMask.REDUCEDLENGTH |
+                    GeodesicMask.GEODESICSCALE)) != 0) {
+      A1 = A1m1f(eps);
+      C1f(eps, C1a);
+      if ((outmask & (GeodesicMask.REDUCEDLENGTH |
+                      GeodesicMask.GEODESICSCALE)) != 0) {
+        A2 = A2m1f(eps);
+        C2f(eps, C2a);
+        m0x = A1 - A2;
+        A2 = 1 + A2;
+      }
+      A1 = 1 + A1;
+    }
+    if ((outmask & GeodesicMask.DISTANCE) != 0) {
+      double B1 = SinCosSeries(true, ssig2, csig2, C1a) -
+        SinCosSeries(true, ssig1, csig1, C1a);
+      // Missing a factor of _b
+      v.s12b = A1 * (sig12 + B1);
+      if ((outmask & (GeodesicMask.REDUCEDLENGTH |
+                      GeodesicMask.GEODESICSCALE)) != 0) {
+        double B2 = SinCosSeries(true, ssig2, csig2, C2a) -
+          SinCosSeries(true, ssig1, csig1, C2a);
+        J12 = m0x * sig12 + (A1 * B1 - A2 * B2);
+      }
+    } else if ((outmask & (GeodesicMask.REDUCEDLENGTH |
+                           GeodesicMask.GEODESICSCALE)) != 0) {
+      // Assume here that nC1_ >= nC2_
+      for (int l = 1; l <= nC2_; ++l)
+        C2a[l] = A1 * C1a[l] - A2 * C2a[l];
+      J12 = m0x * sig12 + (SinCosSeries(true, ssig2, csig2, C2a) -
+                           SinCosSeries(true, ssig1, csig1, C2a));
+    }
+    if ((outmask & GeodesicMask.REDUCEDLENGTH) != 0) {
+      v.m0 = m0x;
+      // Missing a factor of _b.
+      // Add parens around (csig1 * ssig2) and (ssig1 * csig2) to ensure
+      // accurate cancellation in the case of coincident points.
+      v.m12b = dn2 * (csig1 * ssig2) - dn1 * (ssig1 * csig2) -
+        csig1 * csig2 * J12;
+    }
+    if ((outmask & GeodesicMask.GEODESICSCALE) != 0) {
       double csig12 = csig1 * csig2 + ssig1 * ssig2;
       double t = _ep2 * (cbet1 - cbet2) * (cbet1 + cbet2) / (dn1 + dn2);
       v.M12 = csig12 + (t * ssig2 - csig2 * J12) * ssig1 / dn1;
@@ -1079,7 +1114,7 @@ public class Geodesic {
         S = p * q / 4,            // S = r^3 * s
         r2 = GeoMath.sq(r),
         r3 = r * r2,
-        // The discrimant of the quadratic equation for T3.  This is zero on
+        // The discriminant of the quadratic equation for T3.  This is zero on
         // the evolute curve p^(1/3)+q^(1/3) = 1
         disc = S * (S + 2 * r3);
       double u = r;
@@ -1210,7 +1245,7 @@ public class Geodesic {
         LengthsV v =
           Lengths(_n, Math.PI + bet12a,
                   sbet1, -cbet1, dn1, sbet2, cbet2, dn2,
-                  cbet1, cbet2, false, C1a, C2a);
+                  cbet1, cbet2, GeodesicMask.REDUCEDLENGTH, C1a, C2a);
         m12b = v.m12b; m0 = v.m0;
 
         x = -1 + m12b / (cbet1 * cbet2 * m0 * Math.PI);
@@ -1366,10 +1401,9 @@ public class Geodesic {
       if (w.calp2 == 0)
         w.dlam12 = - 2 * _f1 * dn1 / sbet1;
       else {
-        double dummy;
         LengthsV v =
           Lengths(w.eps, w.sig12, w.ssig1, w.csig1, dn1, w.ssig2, w.csig2, dn2,
-                  cbet1, cbet2, false, C1a, C2a);
+                  cbet1, cbet2, GeodesicMask.REDUCEDLENGTH, C1a, C2a);
         w.dlam12 = v.m12b;
         w.dlam12 *= _f1 / (w.calp2 * cbet2);
       }
@@ -1479,12 +1513,12 @@ public class Geodesic {
   // The scale factor A2-1 = mean value of (d/dsigma)I2 - 1
   protected static double A2m1f(double eps) {
     final double coeff[] = {
-      // A2/(1-eps)-1, polynomial in eps2 of order 3
-      25, 36, 64, 0, 256,
+      // (eps+1)*A2-1, polynomial in eps2 of order 3
+      -11, -28, -192, 0, 256,
     };
     int m = nA2_/2;
     double t = GeoMath.polyval(m, coeff, 0, GeoMath.sq(eps)) / coeff[m + 1];
-    return t * (1 - eps) - eps;
+    return (t - eps) / (1 + eps);
   }
 
   // The coefficients C2[l] in the Fourier expansion of B2
diff --git a/java/src/main/java/net/sf/geographiclib/GeodesicLine.java b/java/src/main/java/net/sf/geographiclib/GeodesicLine.java
index 5dd9a73..d233858 100644
--- a/java/src/main/java/net/sf/geographiclib/GeodesicLine.java
+++ b/java/src/main/java/net/sf/geographiclib/GeodesicLine.java
@@ -1,7 +1,7 @@
 /**
  * Implementation of the net.sf.geographiclib.GeodesicLine class
  *
- * Copyright (c) Charles Karney (2013-2014) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2013-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -103,8 +103,7 @@ public class GeodesicLine {
    * @param lon1 longitude of point 1 (degrees).
    * @param azi1 azimuth at point 1 (degrees).
    * <p>
-   * <i>lat1</i> should be in the range [−90°, 90°]; <i>lon1</i>
-   * and <i>azi1</i> should be in the range [−540°, 540°).
+   * <i>lat1</i> should be in the range [−90°, 90°].
    * <p>
    * If the point is at a pole, the azimuth is defined by keeping <i>lon1</i>
    * fixed, writing <i>lat1</i> = ±(90° − ε), and
@@ -170,24 +169,17 @@ public class GeodesicLine {
     _caps = caps | GeodesicMask.LATITUDE | GeodesicMask.AZIMUTH |
       GeodesicMask.LONG_UNROLL;
 
-    // Guard against underflow in salp0
-    azi1 = GeoMath.AngRound(GeoMath.AngNormalize(azi1));
-    _lat1 = lat1;
+    _lat1 = GeoMath.LatFix(lat1);
     _lon1 = lon1;
-    _azi1 = azi1;
-    // alp1 is in [0, pi]
-    double alp1 = azi1 * GeoMath.degree;
-    // Enforce sin(pi) == 0 and cos(pi/2) == 0.  Better to face the ensuing
-    // problems directly than to skirt them.
-    _salp1 =          azi1  == -180 ? 0 : Math.sin(alp1);
-    _calp1 = Math.abs(azi1) ==   90 ? 0 : Math.cos(alp1);
-    double cbet1, sbet1, phi;
-    phi = lat1 * GeoMath.degree;
+    _azi1 = GeoMath.AngNormalize(azi1);
+    // Guard against underflow in salp0
+    { Pair p = GeoMath.sincosd(GeoMath.AngRound(_azi1));
+      _salp1 = p.first; _calp1 = p.second; }
+    double cbet1, sbet1;
+    { Pair p = GeoMath.sincosd(GeoMath.AngRound(_lat1));
+      sbet1 = _f1 * p.first; cbet1 = p.second; }
     // Ensure cbet1 = +epsilon at poles
-    sbet1 = _f1 * Math.sin(phi);
-    cbet1 = Math.abs(lat1) == 90 ? Geodesic.tiny_ : Math.cos(phi);
-    { Pair p = GeoMath.norm(sbet1, cbet1);
-      sbet1 = p.first; cbet1 = p.second; }
+    { Pair p = GeoMath.norm(sbet1, cbet1); sbet1 = p.first; cbet1 = p.second; }
     _dn1 = Math.sqrt(1 + g._ep2 * GeoMath.sq(sbet1));
 
     // Evaluate alp0 from sin(alp1) * cos(bet1) = sin(alp0),
@@ -414,10 +406,8 @@ public class GeodesicLine {
       // Interpret s12_a12 as spherical arc length
       r.a12 = s12_a12;
       sig12 = s12_a12 * GeoMath.degree;
-      double s12a = Math.abs(s12_a12);
-      s12a -= 180 * Math.floor(s12a / 180);
-      ssig12 = s12a ==  0 ? 0 : Math.sin(sig12);
-      csig12 = s12a == 90 ? 0 : Math.cos(sig12);
+      { Pair p = GeoMath.sincosd(s12_a12);
+        ssig12 = p.first; csig12 = p.second; }
     } else {
       // Interpret s12_a12 as distance
       r.s12 = s12_a12;
@@ -506,18 +496,15 @@ public class GeodesicLine {
         ( sig12 + (Geodesic.SinCosSeries(true, ssig2, csig2, _C3a)
                    - _B31));
       lon12 = lam12 / GeoMath.degree;
-      // Use GeoMath.AngNormalize2 because longitude might have wrapped
-      // multiple times.
       r.lon2 = ((outmask & GeodesicMask.LONG_UNROLL) != 0) ? _lon1 + lon12 :
-        GeoMath.AngNormalize(r.lon1 + GeoMath.AngNormalize2(lon12));
+        GeoMath.AngNormalize(r.lon1 + GeoMath.AngNormalize(lon12));
     }
 
     if ((outmask & GeodesicMask.LATITUDE) != 0)
-      r.lat2 = Math.atan2(sbet2, _f1 * cbet2) / GeoMath.degree;
+      r.lat2 = GeoMath.atan2d(sbet2, _f1 * cbet2);
 
     if ((outmask & GeodesicMask.AZIMUTH) != 0)
-      // minus signs give range [-180, 180). 0- converts -0 to +0.
-      r.azi2 = 0 - Math.atan2(-salp2, calp2) / GeoMath.degree;
+      r.azi2 = GeoMath.atan2d(salp2, calp2);
 
     if ((outmask &
          (GeodesicMask.REDUCEDLENGTH | GeodesicMask.GEODESICSCALE)) != 0) {
@@ -602,7 +589,7 @@ public class GeodesicLine {
    **********************************************************************/
   public double EquatorialAzimuth() {
     return Init() ?
-      Math.atan2(_salp0, _calp0) / GeoMath.degree : Double.NaN;
+      GeoMath.atan2d(_salp0, _calp0) : Double.NaN;
   }
 
   /**
@@ -611,7 +598,7 @@ public class GeodesicLine {
    **********************************************************************/
   public double EquatorialArc() {
     return Init() ?
-      Math.atan2(_ssig1, _csig1) / GeoMath.degree : Double.NaN;
+      GeoMath.atan2d(_ssig1, _csig1) : Double.NaN;
   }
 
   /**
diff --git a/java/src/main/java/net/sf/geographiclib/PolygonArea.java b/java/src/main/java/net/sf/geographiclib/PolygonArea.java
index d1a7f58..019b3bd 100644
--- a/java/src/main/java/net/sf/geographiclib/PolygonArea.java
+++ b/java/src/main/java/net/sf/geographiclib/PolygonArea.java
@@ -1,7 +1,7 @@
 /**
  * Implementation of the net.sf.geographiclib.PolygonArea class
  *
- * Copyright (c) Charles Karney (2013-2014) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2013-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -128,8 +128,7 @@ public class PolygonArea {
    * @param lat the latitude of the point (degrees).
    * @param lon the latitude of the point (degrees).
    * <p>
-   * <i>lat</i> should be in the range [−90°, 90°] and <i>lon</i>
-   * should be in the range [−540°, 540°).
+   * <i>lat</i> should be in the range [−90°, 90°].
    **********************************************************************/
   public void AddPoint(double lat, double lon) {
     lon = GeoMath.AngNormalize(lon);
@@ -154,9 +153,8 @@ public class PolygonArea {
    * @param azi azimuth at current point (degrees).
    * @param s distance from current point to next point (meters).
    * <p>
-   * <i>azi</i> should be in the range [−540°, 540°).  This does
-   * nothing if no points have been added yet.  Use PolygonArea.CurrentPoint to
-   * determine the position of the new vertex.
+   * This does nothing if no points have been added yet.  Use
+   * PolygonArea.CurrentPoint to determine the position of the new vertex.
    **********************************************************************/
   public void AddEdge(double azi, double s) {
     if (_num > 0) {             // Do nothing if _num is zero
@@ -249,8 +247,7 @@ public class PolygonArea {
    *   is the area of the polygon (meters<sup>2</sup>) or Double.NaN of
    *   <i>polyline</i> is true in the constructor.
    * <p>
-   * <i>lat</i> should be in the range [−90°, 90°] and <i>lon</i>
-   * should be in the range [−540°, 540°).
+   * <i>lat</i> should be in the range [−90°, 90°].
    **********************************************************************/
   public PolygonResult TestPoint(double lat, double lon,
                                  boolean reverse, boolean sign) {
@@ -318,8 +315,6 @@ public class PolygonArea {
    *   of the polygon or the length of the polyline (meters), and <i>area</i>
    *   is the area of the polygon (meters<sup>2</sup>) or Double.NaN of
    *   <i>polyline</i> is true in the constructor.
-   * <p>
-   * <i>azi</i> should be in the range [−540°, 540°).
    **********************************************************************/
   public PolygonResult TestEdge(double azi, double s,
                                 boolean reverse, boolean sign) {
diff --git a/java/src/main/java/net/sf/geographiclib/package-info.java b/java/src/main/java/net/sf/geographiclib/package-info.java
index 6691850..4ad3f2c 100644
--- a/java/src/main/java/net/sf/geographiclib/package-info.java
+++ b/java/src/main/java/net/sf/geographiclib/package-info.java
@@ -1,7 +1,7 @@
 /**
  * <h1>Geodesic routines from GeographicLib implemented in Java</h1>
  * @author Charles F. F. Karney (charles at karney.com)
- * @version 1.43
+ * @version 1.44
  *
  * <h2>Abstract</h2>
  * <p>
@@ -19,15 +19,15 @@
  * GeographicLib-Java is part of GeographicLib which available for download at
  * <ul>
  * <li>
- *   <a href="https://sf.net/projects/geographiclib/files/distrib/GeographicLib-1.43.tar.gz">
- *   GeographicLib-1.43.tar.gz</a>
+ *   <a href="https://sf.net/projects/geographiclib/files/distrib/GeographicLib-1.44.tar.gz">
+ *   GeographicLib-1.44.tar.gz</a>
  * <li>
- *   <a href="https://sf.net/projects/geographiclib/files/distrib/GeographicLib-1.43.zip">
- *   GeographicLib-1.43.zip</a>
+ *   <a href="https://sf.net/projects/geographiclib/files/distrib/GeographicLib-1.44.zip">
+ *   GeographicLib-1.44.zip</a>
  * </ul>
  * <p>
  * as either a compressed tar file (tar.gz) or a zip file.  After unpacking
- * the source, the Java library can be found in GeographicLib-1.43/java.  (This
+ * the source, the Java library can be found in GeographicLib-1.44/java.  (This
  * library is completely independent from the rest of GeodegraphicLib.)  The
  * library consists of the files in the src/main/java/net/sf/geographiclib
  * subdirectory.
@@ -40,7 +40,7 @@
  *   <dependency>
  *     <groupId>net.sf.geographiclib</groupId>
  *     <artifactId>GeographicLib-Java</artifactId>
- *     <version>1.43</version>
+ *     <version>1.44</version>
  *   </dependency> }</pre>
  * in your {@code pom.xml}.
  *
@@ -105,9 +105,9 @@
  * some additional packages to your local repository.)  Then compile and run
  * Inverse.java with <pre>
  * cd inverse/src/main/java
- * javac -cp .:../../../../target/GeographicLib-Java-1.43.jar Inverse.java
+ * javac -cp .:../../../../target/GeographicLib-Java-1.44.jar Inverse.java
  * echo -30 0 29.5 179.5 |
- *   java -cp .:../../../../target/GeographicLib-Java-1.43.jar Inverse </pre>
+ *   java -cp .:../../../../target/GeographicLib-Java-1.44.jar Inverse </pre>
  *
  * <h3>Using maven to build and run {@code Inverse.java}</h3>
  * The sample code includes a {@code pom.xml} which specifies
@@ -199,6 +199,36 @@
  * <li>
  *   <a href="http://geographiclib.sf.net/geodesic-papers/biblio.html">
  *   An online geodesic bibliography</a>.
+ * <li>
+ *   The wikipedia page,
+ *   <a href="https://en.wikipedia.org/wiki/Geodesics_on_an_ellipsoid">
+ *   Geodesics on an ellipsoid</a>.
+ * </ul>
+ *
+ * <h2>Change log</h2>
+ * <p>
+ * <ul>
+ * <li>
+ *   <a href="http://geographiclib.sf.net/1.44">Version 1.44</a>
+ *   (released 2015-08-14)
+ * <ul>
+ * <li>
+ *   Improve accuracy of calculations by evaluating trigonometric
+ *   functions more carefully and replacing the series for the reduced
+ *   length with one with a smaller truncation error.
+ * <li>
+ *   The allowed ranges for longitudes and azimuths is now unlimited;
+ *   it used to be [−540°, 540°).
+ * <li>
+ *   Enforce the restriction of latitude to [−90°, 90°] by
+ *   returning NaNs if the latitude is outside this range.
+ * <li>
+ *   Geodesic.Inverse sets <i>s12</i> to zero for coincident points at pole
+ *   (instead of returning a tiny quantity).
+ * <li>
+ *   Geodesic.Inverse pays attentions to the GeodesicMask.LONG_UNROLL bit in
+ *   <i>outmask</i>.
+ * </ul>
  * </ul>
  **********************************************************************/
 package net.sf.geographiclib;
diff --git a/legacy/C/geodesic.c b/legacy/C/geodesic.c
index 9a8f043..2dee45e 100644
--- a/legacy/C/geodesic.c
+++ b/legacy/C/geodesic.c
@@ -38,6 +38,7 @@
 #define nC3x  ((nC3 * (nC3 - 1)) / 2)
 #define nC4   GEOGRAPHICLIB_GEODESIC_ORDER
 #define nC4x  ((nC4 * (nC4 + 1)) / 2)
+#define nC    (GEOGRAPHICLIB_GEODESIC_ORDER + 1)
 
 typedef double real;
 typedef int boolx;
@@ -160,18 +161,23 @@ static void norm2(real* sinx, real* cosx) {
   *cosx /= r;
 }
 
-static real AngNormalize(real x)
-{ return x >= 180 ? x - 360 : (x < -180 ? x + 360 : x); }
-static real AngNormalize2(real x)
-{ return AngNormalize(fmod(x, (real)(360))); }
+static real AngNormalize(real x) {
+  x = fmod(x, (real)(360));
+  return x < -180 ? x + 360 : (x < 180 ? x : x - 360);
+}
+
+static real LatFix(real x)
+{ return fabs(x) > 90 ? NaN : x; }
 
 static real AngDiff(real x, real y) {
-  real t, d = sumx(-x, y, &t);
-  if ((d - (real)(180)) + t > (real)(0))       /* y - x > 180 */
-    d -= (real)(360);                          /* exact */
-  else if ((d + (real)(180)) + t <= (real)(0)) /* y - x <= -180 */
-    d += (real)(360);                          /* exact */
-  return d + t;
+  real t, d = - AngNormalize(sumx(AngNormalize(x), AngNormalize(-y), &t));
+  /* Here y - x = d - t (mod 360), exactly, where d is in (-180,180] and
+   * abs(t) <= eps (eps = 2^-45 for doubles).  The only case where the
+   * addition of t takes the result outside the range (-180,180] is d = 180
+   * and t < 0.  The case, d = -180 + eps, t = eps, can't happen, since
+   * sum would have returned the exact result in such a case (i.e., given t
+   * = 0). */
+  return (d == 180 && t < 0 ? -180 : d) - t;
 }
 
 static real AngRound(real x) {
@@ -182,6 +188,48 @@ static real AngRound(real x) {
   return x < 0 ? 0 - y : y;
 }
 
+static void sincosdx(real x, real* sinx, real* cosx) {
+  /* In order to minimize round-off errors, this function exactly reduces
+   * the argument to the range [-45, 45] before converting it to radians. */
+  real r, s, c; int q;
+  r = fmod(x, (real)(360));
+  q = (int)(floor(r / 90 + (real)(0.5)));
+  r -= 90 * q;
+  /* now abs(r) <= 45 */
+  r *= degree;
+  /* Possibly could call the gnu extension sincos */
+  s = sin(r); c = cos(r);
+  switch ((unsigned)q & 3U) {
+  case 0U: *sinx =     s; *cosx =     c; break;
+  case 1U: *sinx =     c; *cosx = 0 - s; break;
+  case 2U: *sinx = 0 - s; *cosx = 0 - c; break;
+  default: *sinx = 0 - c; *cosx =     s; break; /* case 3U */
+  }
+}
+
+static real atan2dx(real y, real x) {
+  /* In order to minimize round-off errors, this function rearranges the
+   * arguments so that result of atan2 is in the range [-pi/4, pi/4] before
+   * converting it to degrees and mapping the result to the correct
+   * quadrant. */
+  int q = 0; real ang;
+  if (fabs(y) > fabs(x)) { swapx(&x, &y); q = 2; }
+  if (x < 0) { x = -x; ++q; }
+  /* here x >= 0 and x >= abs(y), so angle is in [-pi/4, pi/4] */
+  ang = atan2(y, x) / degree;
+  switch (q) {
+    /* Note that atan2d(-0.0, 1.0) will return -0.  However, we expect that
+     * atan2d will not be called with y = -0.  If need be, include
+     *
+     *   case 0: ang = 0 + ang; break;
+     */
+  case 1: ang = (y > 0 ? 180 : -180) - ang; break;
+  case 2: ang =  90 - ang; break;
+  case 3: ang = -90 + ang; break;
+  }
+  return ang;
+}
+
 static void A3coeff(struct geod_geodesic* g);
 static void C3coeff(struct geod_geodesic* g);
 static void C4coeff(struct geod_geodesic* g);
@@ -194,9 +242,9 @@ static void Lengths(const struct geod_geodesic* g,
                     real ssig2, real csig2, real dn2,
                     real cbet1, real cbet2,
                     real* ps12b, real* pm12b, real* pm0,
-                    boolx scalep, real* pM12, real* pM21,
-                    /* Scratch areas of the right size */
-                    real C1a[], real C2a[]);
+                    real* pM12, real* pM21,
+                    /* Scratch area of the right size */
+                    real Ca[]);
 static real Astroid(real x, real y);
 static real InverseStart(const struct geod_geodesic* g,
                          real sbet1, real cbet1, real dn1,
@@ -207,8 +255,8 @@ static real InverseStart(const struct geod_geodesic* g,
                          real* psalp2, real* pcalp2,
                          /* Only updated for short lines */
                          real* pdnm,
-                         /* Scratch areas of the right size */
-                         real C1a[], real C2a[]);
+                         /* Scratch area of the right size */
+                         real Ca[]);
 static real Lambda12(const struct geod_geodesic* g,
                      real sbet1, real cbet1, real dn1,
                      real sbet2, real cbet2, real dn2,
@@ -219,8 +267,8 @@ static real Lambda12(const struct geod_geodesic* g,
                      real* pssig2, real* pcsig2,
                      real* peps, real* pdomg12,
                      boolx diffp, real* pdlam12,
-                     /* Scratch areas of the right size */
-                     real C1a[], real C2a[], real C3a[]);
+                     /* Scratch area of the right size */
+                     real Ca[]);
 static real A3f(const struct geod_geodesic* g, real eps);
 static void C3f(const struct geod_geodesic* g, real eps, real c[]);
 static void C4f(const struct geod_geodesic* g, real eps, real c[]);
@@ -270,7 +318,7 @@ void geod_init(struct geod_geodesic* g, real a, real f) {
 void geod_lineinit(struct geod_geodesicline* l,
                    const struct geod_geodesic* g,
                    real lat1, real lon1, real azi1, unsigned caps) {
-  real alp1, cbet1, sbet1, phi, eps;
+  real cbet1, sbet1, eps;
   l->a = g->a;
   l->f = g->f;
   l->b = g->b;
@@ -281,21 +329,15 @@ void geod_lineinit(struct geod_geodesicline* l,
     /* always allow latitude and azimuth and unrolling of longitude */
     GEOD_LATITUDE | GEOD_AZIMUTH | GEOD_LONG_UNROLL;
 
-  l->lat1 = lat1;
+  l->lat1 = LatFix(lat1);
   l->lon1 = lon1;
+  l->azi1 = AngNormalize(azi1);
   /* Guard against underflow in salp0 */
-  l->azi1 = AngRound(AngNormalize(azi1));
-  /* alp1 is in [0, pi] */
-  alp1 = l->azi1 * degree;
-  /* Enforce sin(pi) == 0 and cos(pi/2) == 0.  Better to face the ensuing
-   * problems directly than to skirt them. */
-  l->salp1 =      l->azi1  == -180 ? 0 : sin(alp1);
-  l->calp1 = fabs(l->azi1) ==   90 ? 0 : cos(alp1);
-  phi = lat1 * degree;
+  sincosdx(AngRound(l->azi1), &l->salp1, &l->calp1);
+
+  sincosdx(AngRound(l->lat1), &sbet1, &cbet1); sbet1 *= l->f1;
   /* Ensure cbet1 = +epsilon at poles */
-  sbet1 = l->f1 * sin(phi);
-  cbet1 = fabs(lat1) == 90 ? tiny : cos(phi);
-  norm2(&sbet1, &cbet1);
+  norm2(&sbet1, &cbet1); cbet1 = maxx(tiny, cbet1);
   l->dn1 = sqrt(1 + g->ep2 * sq(sbet1));
 
   /* Evaluate alp0 from sin(alp1) * cos(bet1) = sin(alp0), */
@@ -384,13 +426,9 @@ real geod_genposition(const struct geod_geodesicline* l,
     return NaN;
 
   if (flags & GEOD_ARCMODE) {
-    real s12a;
     /* Interpret s12_a12 as spherical arc length */
     sig12 = s12_a12 * degree;
-    s12a = fabs(s12_a12);
-    s12a -= 180 * floor(s12a / 180);
-    ssig12 = s12a ==  0 ? 0 : sin(sig12);
-    csig12 = s12a == 90 ? 0 : cos(sig12);
+    sincosdx(s12_a12, &ssig12, &csig12);
   } else {
     /* Interpret s12_a12 as distance */
     real
@@ -475,18 +513,15 @@ real geod_genposition(const struct geod_geodesicline* l,
       ( sig12 + (SinCosSeries(TRUE, ssig2, csig2, l->C3a, nC3-1)
                  - l->B31));
     lon12 = lam12 / degree;
-    /* Use AngNormalize2 because longitude might have wrapped multiple
-     * times. */
     lon2 = flags & GEOD_LONG_UNROLL ? l->lon1 + lon12 :
-      AngNormalize(AngNormalize(l->lon1) + AngNormalize2(lon12));
+      AngNormalize(AngNormalize(l->lon1) + AngNormalize(lon12));
   }
 
   if (outmask & GEOD_LATITUDE)
-    lat2 = atan2(sbet2, l->f1 * cbet2) / degree;
+    lat2 = atan2dx(sbet2, l->f1 * cbet2);
 
   if (outmask & GEOD_AZIMUTH)
-    /* minus signs give range [-180, 180). 0- converts -0 to +0. */
-    azi2 = 0 - atan2(-salp2, calp2) / degree;
+    azi2 = atan2dx(salp2, calp2);
 
   if (outmask & (GEOD_REDUCEDLENGTH | GEOD_GEODESICSCALE)) {
     real
@@ -602,11 +637,10 @@ real geod_geninverse(const struct geod_geodesic* g,
   real s12 = 0, azi1 = 0, azi2 = 0, m12 = 0, M12 = 0, M21 = 0, S12 = 0;
   real lon12;
   int latsign, lonsign, swapp;
-  real phi, sbet1, cbet1, sbet2, cbet2, s12x = 0, m12x = 0;
+  real sbet1, cbet1, sbet2, cbet2, s12x = 0, m12x = 0;
   real dn1, dn2, lam12, slam12, clam12;
   real a12 = 0, sig12, calp1 = 0, salp1 = 0, calp2 = 0, salp2 = 0;
-  /* index zero elements of these arrays are unused */
-  real C1a[nC1 + 1], C2a[nC2 + 1], C3a[nC3];
+  real Ca[nC];
   boolx meridian;
   real omg12 = 0;
 
@@ -621,15 +655,14 @@ real geod_geninverse(const struct geod_geodesic* g,
   /* Compute longitude difference (AngDiff does this carefully).  Result is
    * in [-180, 180] but -180 is only for west-going geodesics.  180 is for
    * east-going and meridional geodesics. */
-  lon12 = AngDiff(AngNormalize(lon1), AngNormalize(lon2));
   /* If very close to being on the same half-meridian, then make it so. */
-  lon12 = AngRound(lon12);
+  lon12 = AngRound(AngDiff(lon1, lon2));
   /* Make longitude difference positive. */
   lonsign = lon12 >= 0 ? 1 : -1;
   lon12 *= lonsign;
   /* If really close to the equator, treat as on equator. */
-  lat1 = AngRound(lat1);
-  lat2 = AngRound(lat2);
+  lat1 = AngRound(LatFix(lat1));
+  lat2 = AngRound(LatFix(lat2));
   /* Swap points so that point with higher (abs) latitude is point 1 */
   swapp = fabs(lat1) >= fabs(lat2) ? 1 : -1;
   if (swapp < 0) {
@@ -652,17 +685,13 @@ real geod_geninverse(const struct geod_geodesic* g,
    * check, e.g., on verifying quadrants in atan2.  In addition, this
    * enforces some symmetries in the results returned. */
 
-  phi = lat1 * degree;
+  sincosdx(lat1, &sbet1, &cbet1); sbet1 *= g->f1;
   /* Ensure cbet1 = +epsilon at poles */
-  sbet1 = g->f1 * sin(phi);
-  cbet1 = lat1 == -90 ? tiny : cos(phi);
-  norm2(&sbet1, &cbet1);
+  norm2(&sbet1, &cbet1); cbet1 = maxx(tiny, cbet1);
 
-  phi = lat2 * degree;
+  sincosdx(lat2, &sbet2, &cbet2); sbet2 *= g->f1;
   /* Ensure cbet2 = +epsilon at poles */
-  sbet2 = g->f1 * sin(phi);
-  cbet2 = fabs(lat2) == 90 ? tiny : cos(phi);
-  norm2(&sbet2, &cbet2);
+  norm2(&sbet2, &cbet2); cbet2 = maxx(tiny, cbet2);
 
   /* If cbet1 < -sbet1, then cbet2 - cbet1 is a sensitive measure of the
    * |bet1| - |bet2|.  Alternatively (cbet1 >= -sbet1), abs(sbet2) + sbet1 is
@@ -684,8 +713,7 @@ real geod_geninverse(const struct geod_geodesic* g,
   dn2 = sqrt(1 + g->ep2 * sq(sbet2));
 
   lam12 = lon12 * degree;
-  slam12 = lon12 == 180 ? 0 : sin(lam12);
-  clam12 = cos(lam12);      /* lon12 == 90 isn't interesting */
+  sincosdx(lon12, &slam12, &clam12);
 
   meridian = lat1 == -90 || slam12 == 0;
 
@@ -705,12 +733,11 @@ real geod_geninverse(const struct geod_geodesic* g,
     /* sig12 = sig2 - sig1 */
     sig12 = atan2(maxx(csig1 * ssig2 - ssig1 * csig2, (real)(0)),
                   csig1 * csig2 + ssig1 * ssig2);
-    {
-      real dummy;
-      Lengths(g, g->n, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2,
-              cbet1, cbet2, &s12x, &m12x, &dummy,
-              (outmask & GEOD_GEODESICSCALE) != 0U, &M12, &M21, C1a, C2a);
-    }
+    Lengths(g, g->n, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2,
+            cbet1, cbet2, &s12x, &m12x, 0,
+            outmask & GEOD_GEODESICSCALE ? &M12 : 0,
+            outmask & GEOD_GEODESICSCALE ? &M21 : 0,
+            Ca);
     /* Add the check for sig12 since zero length geodesics might yield m12 <
      * 0.  Test case was
      *
@@ -719,6 +746,9 @@ real geod_geninverse(const struct geod_geodesic* g,
      * In fact, we will have sig12 > pi/2 for meridional geodesic which is
      * not a shortest path. */
     if (sig12 < 1 || m12x >= 0) {
+      /* Need at least 2, to handle 90 0 90 180 */
+      if (sig12 < 3 * tiny)
+        sig12 = m12x = s12x = 0;
       m12x *= g->b;
       s12x *= g->b;
       a12 = sig12 / degree;
@@ -751,7 +781,7 @@ real geod_geninverse(const struct geod_geodesic* g,
     sig12 = InverseStart(g, sbet1, cbet1, dn1, sbet2, cbet2, dn2,
                          lam12,
                          &salp1, &calp1, &salp2, &calp2, &dnm,
-                         C1a, C2a);
+                         Ca);
 
     if (sig12 >= 0) {
       /* Short lines (InverseStart sets salp2, calp2, dnm) */
@@ -785,7 +815,7 @@ real geod_geninverse(const struct geod_geodesic* g,
         real dv = 0,
           v = (Lambda12(g, sbet1, cbet1, dn1, sbet2, cbet2, dn2, salp1, calp1,
                         &salp2, &calp2, &sig12, &ssig1, &csig1, &ssig2, &csig2,
-                        &eps, &omg12, numit < maxit1, &dv, C1a, C2a, C3a)
+                        &eps, &omg12, numit < maxit1, &dv, Ca)
                - lam12);
         /* 2 * tol0 is approximately 1 ulp for a number in [0, pi]. */
         /* Reversed test to allow escape with NaNs */
@@ -827,12 +857,10 @@ real geod_geninverse(const struct geod_geodesic* g,
         tripb = (fabs(salp1a - salp1) + (calp1a - calp1) < tolb ||
                  fabs(salp1 - salp1b) + (calp1 - calp1b) < tolb);
       }
-      {
-        real dummy;
-        Lengths(g, eps, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2,
-                cbet1, cbet2, &s12x, &m12x, &dummy,
-                (outmask & GEOD_GEODESICSCALE) != 0U, &M12, &M21, C1a, C2a);
-      }
+      Lengths(g, eps, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2,
+              cbet1, cbet2, &s12x, &m12x, 0,
+              outmask & GEOD_GEODESICSCALE ? &M12 : 0,
+              outmask & GEOD_GEODESICSCALE ? &M21 : 0, Ca);
       m12x *= g->b;
       s12x *= g->b;
       a12 = sig12 / degree;
@@ -861,13 +889,12 @@ real geod_geninverse(const struct geod_geodesic* g,
         eps = k2 / (2 * (1 + sqrt(1 + k2)) + k2),
         /* Multiplier = a^2 * e^2 * cos(alpha0) * sin(alpha0). */
         A4 = sq(g->a) * calp0 * salp0 * g->e2;
-      real C4a[nC4];
       real B41, B42;
       norm2(&ssig1, &csig1);
       norm2(&ssig2, &csig2);
-      C4f(g, eps, C4a);
-      B41 = SinCosSeries(FALSE, ssig1, csig1, C4a, nC4);
-      B42 = SinCosSeries(FALSE, ssig2, csig2, C4a, nC4);
+      C4f(g, eps, Ca);
+      B41 = SinCosSeries(FALSE, ssig1, csig1, Ca, nC4);
+      B42 = SinCosSeries(FALSE, ssig2, csig2, Ca, nC4);
       S12 = A4 * (B42 - B41);
     } else
       /* Avoid problems with indeterminate sig1, sig2 on equator */
@@ -918,8 +945,8 @@ real geod_geninverse(const struct geod_geodesic* g,
 
   if (outmask & GEOD_AZIMUTH) {
     /* minus signs give range [-180, 180). 0- converts -0 to +0. */
-    azi1 = 0 - atan2(-salp1, calp1) / degree;
-    azi2 = 0 - atan2(-salp2, calp2) / degree;
+    azi1 = atan2dx(salp1, calp1);
+    azi2 = atan2dx(salp2, calp2);
   }
 
   if (outmask & GEOD_DISTANCE)
@@ -975,42 +1002,58 @@ void Lengths(const struct geod_geodesic* g,
              real ssig2, real csig2, real dn2,
              real cbet1, real cbet2,
              real* ps12b, real* pm12b, real* pm0,
-             boolx scalep, real* pM12, real* pM21,
-             /* Scratch areas of the right size */
-             real C1a[], real C2a[]) {
-  real s12b = 0, m12b = 0, m0 = 0, M12 = 0, M21 = 0;
-  real A1m1, AB1, A2m1, AB2, J12;
+             real* pM12, real* pM21,
+             /* Scratch area of the right size */
+             real Ca[]) {
+  real m0 = 0, J12 = 0, A1 = 0, A2 = 0;
+  real Cb[nC];
 
   /* Return m12b = (reduced length)/b; also calculate s12b = distance/b,
    * and m0 = coefficient of secular term in expression for reduced length. */
-  C1f(eps, C1a);
-  C2f(eps, C2a);
-  A1m1 = A1m1f(eps);
-  AB1 = (1 + A1m1) * (SinCosSeries(TRUE, ssig2, csig2, C1a, nC1) -
-                      SinCosSeries(TRUE, ssig1, csig1, C1a, nC1));
-  A2m1 = A2m1f(eps);
-  AB2 = (1 + A2m1) * (SinCosSeries(TRUE, ssig2, csig2, C2a, nC2) -
-                      SinCosSeries(TRUE, ssig1, csig1, C2a, nC2));
-  m0 = A1m1 - A2m1;
-  J12 = m0 * sig12 + (AB1 - AB2);
-  /* Missing a factor of b.
-   * Add parens around (csig1 * ssig2) and (ssig1 * csig2) to ensure accurate
-   * cancellation in the case of coincident points. */
-  m12b = dn2 * (csig1 * ssig2) - dn1 * (ssig1 * csig2) - csig1 * csig2 * J12;
-  /* Missing a factor of b */
-  s12b = (1 + A1m1) * sig12 + AB1;
-  if (scalep) {
+  boolx redlp = pm12b || pm0 || pM12 || pM21;
+  if (ps12b || redlp) {
+    A1 = A1m1f(eps);
+    C1f(eps, Ca);
+    if (redlp) {
+      A2 = A2m1f(eps);
+      C2f(eps, Cb);
+      m0 = A1 - A2;
+      A2 = 1 + A2;
+    }
+    A1 = 1 + A1;
+  }
+  if (ps12b) {
+    real B1 = SinCosSeries(TRUE, ssig2, csig2, Ca, nC1) -
+      SinCosSeries(TRUE, ssig1, csig1, Ca, nC1);
+    /* Missing a factor of b */
+    *ps12b = A1 * (sig12 + B1);
+    if (redlp) {
+      real B2 = SinCosSeries(TRUE, ssig2, csig2, Cb, nC2) -
+        SinCosSeries(TRUE, ssig1, csig1, Cb, nC2);
+      J12 = m0 * sig12 + (A1 * B1 - A2 * B2);
+    }
+  } else if (redlp) {
+    /* Assume here that nC1 >= nC2 */
+    int l;
+    for (l = 1; l <= nC2; ++l)
+      Cb[l] = A1 * Ca[l] - A2 * Cb[l];
+    J12 = m0 * sig12 + (SinCosSeries(TRUE, ssig2, csig2, Cb, nC2) -
+                        SinCosSeries(TRUE, ssig1, csig1, Cb, nC2));
+  }
+  if (pm0) *pm0 = m0;
+  if (pm12b)
+    /* Missing a factor of b.
+     * Add parens around (csig1 * ssig2) and (ssig1 * csig2) to ensure
+     * accurate cancellation in the case of coincident points. */
+    *pm12b = dn2 * (csig1 * ssig2) - dn1 * (ssig1 * csig2) -
+      csig1 * csig2 * J12;
+  if (pM12 || pM21) {
     real csig12 = csig1 * csig2 + ssig1 * ssig2;
     real t = g->ep2 * (cbet1 - cbet2) * (cbet1 + cbet2) / (dn1 + dn2);
-    M12 = csig12 + (t * ssig2 - csig2 * J12) * ssig1 / dn1;
-    M21 = csig12 - (t * ssig1 - csig1 * J12) * ssig2 / dn2;
-  }
-  *ps12b = s12b;
-  *pm12b = m12b;
-  *pm0 = m0;
-  if (scalep) {
-    *pM12 = M12;
-    *pM21 = M21;
+    if (pM12)
+      *pM12 = csig12 + (t * ssig2 - csig2 * J12) * ssig1 / dn1;
+    if (pM21)
+      *pM21 = csig12 - (t * ssig1 - csig1 * J12) * ssig2 / dn2;
   }
 }
 
@@ -1029,7 +1072,7 @@ real Astroid(real x, real y) {
       S = p * q / 4,            /* S = r^3 * s */
       r2 = sq(r),
       r3 = r * r2,
-      /* The discrimant of the quadratic equation for T3.  This is zero on
+      /* The discriminant of the quadratic equation for T3.  This is zero on
        * the evolute curve p^(1/3)+q^(1/3) = 1 */
       disc = S * (S + 2 * r3);
     real u = r;
@@ -1075,8 +1118,8 @@ real InverseStart(const struct geod_geodesic* g,
                   real* psalp2, real* pcalp2,
                   /* Only updated for short lines */
                   real* pdnm,
-                  /* Scratch areas of the right size */
-                  real C1a[], real C2a[]) {
+                  /* Scratch area of the right size */
+                  real Ca[]) {
   real salp1 = 0, calp1 = 0, salp2 = 0, calp2 = 0, dnm = 0;
 
   /* Return a starting point for Newton's method in salp1 and calp1 (function
@@ -1087,6 +1130,10 @@ real InverseStart(const struct geod_geodesic* g,
     /* bet12 = bet2 - bet1 in [0, pi); bet12a = bet2 + bet1 in (-pi, 0] */
     sbet12 = sbet2 * cbet1 - cbet2 * sbet1,
     cbet12 = cbet2 * cbet1 + sbet2 * sbet1;
+  real sbet12a;
+  boolx shortline = cbet12 >= 0 && sbet12 < (real)(0.5) &&
+    cbet2 * lam12 < (real)(0.5);
+  real omg12 = lam12, somg12, comg12, ssig12, csig12;
 #if defined(__GNUC__) && __GNUC__ == 4 &&       \
   (__GNUC_MINOR__ < 6 || defined(__MINGW32__))
   /* Volatile declaration needed to fix inverse cases
@@ -1095,18 +1142,14 @@ real InverseStart(const struct geod_geodesic* g,
    * 89.333123580033 0 -89.333123580032997687 179.99295812360148422
    * which otherwise fail with g++ 4.4.4 x86 -O3 (Linux)
    * and g++ 4.4.0 (mingw) and g++ 4.6.1 (tdm mingw). */
-  real sbet12a;
   {
     volatile real xx1 = sbet2 * cbet1;
     volatile real xx2 = cbet2 * sbet1;
     sbet12a = xx1 + xx2;
   }
 #else
-  real sbet12a = sbet2 * cbet1 + cbet2 * sbet1;
+  sbet12a = sbet2 * cbet1 + cbet2 * sbet1;
 #endif
-  boolx shortline = cbet12 >= 0 && sbet12 < (real)(0.5) &&
-    cbet2 * lam12 < (real)(0.5);
-  real omg12 = lam12, somg12, comg12, ssig12, csig12;
   if (shortline) {
     real sbetm2 = sq(sbet1 + sbet2);
     /* sin((bet1+bet2)/2)^2
@@ -1162,13 +1205,12 @@ real InverseStart(const struct geod_geodesic* g,
       real
         cbet12a = cbet2 * cbet1 - sbet2 * sbet1,
         bet12a = atan2(sbet12a, cbet12a);
-      real m12b, m0, dummy;
+      real m12b, m0;
       /* In the case of lon12 = 180, this repeats a calculation made in
        * Inverse. */
       Lengths(g, g->n, pi + bet12a,
               sbet1, -cbet1, dn1, sbet2, cbet2, dn2,
-              cbet1, cbet2, &dummy, &m12b, &m0, FALSE,
-              &dummy, &dummy, C1a, C2a);
+              cbet1, cbet2, 0, &m12b, &m0, 0, 0, Ca);
       x = -1 + m12b / (cbet1 * cbet2 * m0 * pi);
       betscale = x < -(real)(0.01) ? sbet12a / x :
         -g->f * sq(cbet1) * pi;
@@ -1256,8 +1298,8 @@ real Lambda12(const struct geod_geodesic* g,
               real* pssig2, real* pcsig2,
               real* peps, real* pdomg12,
               boolx diffp, real* pdlam12,
-              /* Scratch areas of the right size */
-              real C1a[], real C2a[], real C3a[]) {
+              /* Scratch area of the right size */
+              real Ca[]) {
   real salp2 = 0, calp2 = 0, sig12 = 0,
     ssig1 = 0, csig1 = 0, ssig2 = 0, csig2 = 0, eps = 0, domg12 = 0, dlam12 = 0;
   real salp0, calp0;
@@ -1311,9 +1353,9 @@ real Lambda12(const struct geod_geodesic* g,
                 comg1 * comg2 + somg1 * somg2);
   k2 = sq(calp0) * g->ep2;
   eps = k2 / (2 * (1 + sqrt(1 + k2)) + k2);
-  C3f(g, eps, C3a);
-  B312 = (SinCosSeries(TRUE, ssig2, csig2, C3a, nC3-1) -
-          SinCosSeries(TRUE, ssig1, csig1, C3a, nC3-1));
+  C3f(g, eps, Ca);
+  B312 = (SinCosSeries(TRUE, ssig2, csig2, Ca, nC3-1) -
+          SinCosSeries(TRUE, ssig1, csig1, Ca, nC3-1));
   h0 = -g->f * A3f(g, eps);
   domg12 = salp0 * h0 * (sig12 + B312);
   lam12 = omg12 + domg12;
@@ -1322,10 +1364,8 @@ real Lambda12(const struct geod_geodesic* g,
     if (calp2 == 0)
       dlam12 = - 2 * g->f1 * dn1 / sbet1;
     else {
-      real dummy;
       Lengths(g, eps, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2,
-              cbet1, cbet2, &dummy, &dlam12, &dummy,
-              FALSE, &dummy, &dummy, C1a, C2a);
+              cbet1, cbet2, 0, &dlam12, 0, 0, 0, Ca);
       dlam12 *= g->f1 / (calp2 * cbet2);
     }
   }
@@ -1446,12 +1486,12 @@ void C1pf(real eps, real c[])  {
 /* The scale factor A2-1 = mean value of (d/dsigma)I2 - 1 */
 real A2m1f(real eps)  {
   static const real coeff[] = {
-    /* A2/(1-eps)-1, polynomial in eps2 of order 3 */
-    25, 36, 64, 0, 256,
+    /* (eps+1)*A2-1, polynomial in eps2 of order 3 */
+    -11, -28, -192, 0, 256,
   };
   int m = nA2/2;
   real t = polyval(m, coeff, sq(eps)) / coeff[m + 1];
-  return t * (1 - eps) - eps;
+  return (t - eps) / (1 + eps);
 }
 
 /* The coefficients C2[l] in the Fourier expansion of B2 */
diff --git a/legacy/C/geodesic.h b/legacy/C/geodesic.h
index 1a1892a..7bd8270 100644
--- a/legacy/C/geodesic.h
+++ b/legacy/C/geodesic.h
@@ -113,7 +113,7 @@
  * http://geographiclib.sourceforge.net/
  *
  * This library was distributed with
- * <a href="../index.html">GeographicLib</a> 1.43.
+ * <a href="../index.html">GeographicLib</a> 1.44.
  **********************************************************************/
 
 #if !defined(GEODESIC_H)
@@ -128,7 +128,7 @@
  * The minor version of the geodesic library.  (This tracks the version of
  * GeographicLib.)
  **********************************************************************/
-#define GEODESIC_VERSION_MINOR 43
+#define GEODESIC_VERSION_MINOR 44
 /**
  * The patch level of the geodesic library.  (This tracks the version of
  * GeographicLib.)
@@ -147,11 +147,11 @@
  * where MM is the major version, mmmm is the minor version, and pp is the
  * patch level.  Users should not rely on this particular packing of the
  * components of the version number.  Instead they should use a test such as
- * \code
+ * @code{.c}
    #if GEODESIC_VERSION >= GEODESIC_VERSION_NUM(1,40,0)
    ...
    #endif
- * \endcode
+ * @endcode
  **********************************************************************/
 #define GEODESIC_VERSION \
  GEODESIC_VERSION_NUM(GEODESIC_VERSION_MAJOR, \
@@ -237,8 +237,7 @@ extern "C" {
    *   geod_genposition().
    *
    * \e g must have been initialized with a call to geod_init().  \e lat1
-   * should be in the range [−90°, 90°]; \e lon1 and \e azi1
-   * should be in the range [−540°, 540°).
+   * should be in the range [−90°, 90°].
    *
    * The geod_mask values are [see geod_mask()]:
    * - \e caps |= GEOD_LATITUDE for the latitude \e lat2; this is
@@ -278,8 +277,7 @@ extern "C" {
    * @param[out] pazi2 pointer to the (forward) azimuth at point 2 (degrees).
    *
    * \e g must have been initialized with a call to geod_init().  \e lat1
-   * should be in the range [−90°, 90°]; \e lon1 and \e azi1
-   * should be in the range [−540°, 540°).  The values of \e lon2
+   * should be in the range [−90°, 90°].  The values of \e lon2
    * and \e azi2 returned are in the range [−180°, 180°).  Any of
    * the "return" arguments \e plat2, etc., may be replaced by 0, if you do not
    * need some quantities computed.
@@ -292,7 +290,7 @@ extern "C" {
    * longitudinal extent must not exceed of 180°.)
    *
    * Example, determine the point 10000 km NE of JFK:
-   @code
+   @code{.c}
    struct geod_geodesic g;
    double lat, lon;
    geod_init(&g, 6378137, 1/298.257223563);
@@ -318,11 +316,10 @@ extern "C" {
    * @param[out] pazi1 pointer to the azimuth at point 1 (degrees).
    * @param[out] pazi2 pointer to the (forward) azimuth at point 2 (degrees).
    *
-   * \e g must have been initialized with a call to geod_init().  \e lat1
-   * and \e lat2 should be in the range [−90°, 90°]; \e lon1 and
-   * \e lon2 should be in the range [−540°, 540°).  The values of
+   * \e g must have been initialized with a call to geod_init().  \e lat1 and
+   * \e lat2 should be in the range [−90°, 90°].  The values of
    * \e azi1 and \e azi2 returned are in the range [−180°, 180°).
-   * Any of the "return" arguments \e ps12, etc., may be replaced by 0, if you
+   * Any of the "return" arguments, \e ps12, etc., may be replaced by 0, if you
    * do not need some quantities computed.
    *
    * If either point is at a pole, the azimuth is defined by keeping the
@@ -335,7 +332,7 @@ extern "C" {
    * is used to refine the solution.
    *
    * Example, determine the distance between JFK and Singapore Changi Airport:
-   @code
+   @code{.c}
    struct geod_geodesic g;
    double s12;
    geod_init(&g, 6378137, 1/298.257223563);
@@ -367,7 +364,7 @@ extern "C" {
    *
    * Example, compute way points between JFK and Singapore Changi Airport
    * the "obvious" way using geod_direct():
-   @code
+   @code{.c}
    struct geod_geodesic g;
    double s12, azi1, lat[101],lon[101];
    int i;
@@ -379,7 +376,7 @@ extern "C" {
    }
    @endcode
    * A faster way using geod_position():
-   @code
+   @code{.c}
    struct geod_geodesic g;
    struct geod_geodesicline l;
    double s12, azi1, lat[101],lon[101];
@@ -425,18 +422,14 @@ extern "C" {
    * @return \e a12 arc length of between point 1 and point 2 (degrees).
    *
    * \e g must have been initialized with a call to geod_init().  \e lat1
-   * should be in the range [−90°, 90°]; \e lon1 and \e azi1
-   * should be in the range [−540°, 540°).  The function
-   * value \e a12 equals \e s12_a12 if \e flags & GEOD_ARCMODE.  Any of the
-   * "return" arguments \e plat2, etc., may be replaced by 0, if you do not
-   * need some quantities computed.
+   * should be in the range [−90°, 90°].  The function value \e
+   * a12 equals \e s12_a12 if \e flags & GEOD_ARCMODE.  Any of the "return"
+   * arguments, \e plat2, etc., may be replaced by 0, if you do not need some
+   * quantities computed.
    *
    * With \e flags & GEOD_LONG_UNROLL bit set, the longitude is "unrolled" so
    * that the quantity \e lon2 − \e lon1 indicates how many times and in
-   * what sense the geodesic encircles the ellipsoid.  Because \e lon2 might be
-   * outside the normal allowed range for longitudes, [−540°,
-   * 540°), be sure to normalize it, e.g., with fmod(\e lon2, 360.0) before
-   * using it in subsequent calculations
+   * what sense the geodesic encircles the ellipsoid.
    **********************************************************************/
   double geod_gendirect(const struct geod_geodesic* g,
                         double lat1, double lon1, double azi1,
@@ -467,9 +460,8 @@ extern "C" {
    *   (meters<sup>2</sup>).
    * @return \e a12 arc length of between point 1 and point 2 (degrees).
    *
-   * \e g must have been initialized with a call to geod_init().  \e lat1
-   * and \e lat2 should be in the range [−90°, 90°]; \e lon1 and
-   * \e lon2 should be in the range [−540°, 540°).  Any of the
+   * \e g must have been initialized with a call to geod_init().  \e lat1 and
+   * \e lat2 should be in the range [−90°, 90°].  Any of the
    * "return" arguments \e ps12, etc., may be replaced by 0, if you do not need
    * some quantities computed.
    **********************************************************************/
@@ -521,17 +513,14 @@ extern "C" {
    *
    * With \e flags & GEOD_LONG_UNROLL bit set, the longitude is "unrolled" so
    * that the quantity \e lon2 − \e lon1 indicates how many times and in
-   * what sense the geodesic encircles the ellipsoid.  Because \e lon2 might be
-   * outside the normal allowed range for longitudes, [−540°,
-   * 540°), be sure to normalize it, e.g., with fmod(\e lon2, 360.0) before
-   * using it in subsequent calculations
+   * what sense the geodesic encircles the ellipsoid.
    *
    * Example, compute way points between JFK and Singapore Changi Airport
    * using geod_genposition().  In this example, the points are evenly space in
    * arc length (and so only approximately equally space in distance).  This is
    * faster than using geod_position() would be appropriate if drawing the path
    * on a map.
-   @code
+   @code{.c}
    struct geod_geodesic g;
    struct geod_geodesicline l;
    double a12, azi1, lat[101], lon[101];
@@ -588,8 +577,7 @@ extern "C" {
    * \e g and \e p must have been initialized with calls to geod_init() and
    * geod_polygon_init(), respectively.  The same \e g must be used for all the
    * points and edges in a polygon.  \e lat should be in the range
-   * [−90°, 90°] and \e lon should be in the range
-   * [−540°, 540°).
+   * [−90°, 90°].
    *
    * An example of the use of this function is given in the documentation for
    * geod_polygon_compute().
@@ -610,10 +598,9 @@ extern "C" {
    *
    * \e g and \e p must have been initialized with calls to geod_init() and
    * geod_polygon_init(), respectively.  The same \e g must be used for all the
-   * points and edges in a polygon.  \e azi should be in the range
-   * [−540°, 540°).  This does nothing if no points have been
-   * added yet.  The \e lat and \e lon fields of \e p give the location of
-   * the new vertex.
+   * points and edges in a polygon.  This does nothing if no points have been
+   * added yet.  The \e lat and \e lon fields of \e p give the location of the
+   * new vertex.
    **********************************************************************/
   void geod_polygon_addedge(const struct geod_geodesic* g,
                             struct geod_polygon* p,
@@ -645,7 +632,7 @@ extern "C" {
    *
    * Example, compute the perimeter and area of the geodesic triangle with
    * vertices (0°N,0°E), (0°N,90°E), (90°N,0°E).
-   @code
+   @code{.c}
    double A, P;
    int n;
    struct geod_geodesic g;
@@ -689,8 +676,7 @@ extern "C" {
    *   polyline (meters).
    * @return the number of points.
    *
-   * \e lat should be in the range [−90°, 90°] and \e
-   * lon should be in the range [−540°, 540°).
+   * \e lat should be in the range [−90°, 90°].
    **********************************************************************/
   unsigned geod_polygon_testpoint(const struct geod_geodesic* g,
                                   const struct geod_polygon* p,
@@ -722,8 +708,6 @@ extern "C" {
    * @param[out] pP pointer to the perimeter of the polygon or length of the
    *   polyline (meters).
    * @return the number of points.
-   *
-   * \e azi should be in the range [−540°, 540°).
    **********************************************************************/
   unsigned geod_polygon_testedge(const struct geod_geodesic* g,
                                  const struct geod_polygon* p,
@@ -742,8 +726,7 @@ extern "C" {
    * @param[out] pA pointer to the area of the polygon (meters<sup>2</sup>).
    * @param[out] pP pointer to the perimeter of the polygon (meters).
    *
-   * \e lats should be in the range [−90°, 90°]; \e lons should
-   * be in the range [−540°, 540°).
+   * \e lats should be in the range [−90°, 90°].
    *
    * Only simple polygons (which are not self-intersecting) are allowed.
    * There's no need to "close" the polygon by repeating the first vertex.  The
@@ -751,7 +734,7 @@ extern "C" {
    * positive.
    *
    * Example, compute the area of Antarctica:
-   @code
+   @code{.c}
    double
      lats[] = {-72.9, -71.9, -74.9, -74.3, -77.5, -77.4, -71.7, -65.9, -65.7,
                -66.6, -66.9, -69.8, -70.0, -71.0, -77.3, -77.9, -74.7},
diff --git a/legacy/Fortran/geoddirect.for b/legacy/Fortran/geoddirect.for
index 85c6e60..c115891 100644
--- a/legacy/Fortran/geoddirect.for
+++ b/legacy/Fortran/geoddirect.for
@@ -24,12 +24,18 @@
 
  10   continue
       read(*, *, end=90, err=90) lat1, lon1, azi1, s12
+      if (abs(lat1) .gt. 90) then
+        print 15
+ 15     format(1x, 'lat1 must be in [-90,90]')
+        go to 10
+      end if
       call direct(a, f, lat1, lon1, azi1, s12, flags,
      +    lat2, lon2, azi2, omask,
      +    dummy1, dummy2, dummy3, dummy4, dummy5)
       print 20, lat2, lon2, azi2
- 20   format(f20.15, 1x, f20.15, 1x, f20.15)
+ 20   format(1x, f20.15, 1x, f20.15, 1x, f20.15)
       go to 10
  90   continue
+
       stop
       end
diff --git a/legacy/Fortran/geodesic.for b/legacy/Fortran/geodesic.for
index 0b12b36..242a301 100644
--- a/legacy/Fortran/geodesic.for
+++ b/legacy/Fortran/geodesic.for
@@ -117,7 +117,7 @@
 *! http://geographiclib.sourceforge.net/
 *!
 *! This library was distributed with
-*! <a href="../index.html">GeographicLib</a> 1.43.
+*! <a href="../index.html">GeographicLib</a> 1.44.
 
 *> Solve the direct geodesic problem
 *!
@@ -156,11 +156,8 @@
 *! a12; otherwise, \e s12a12 is \e a12 and \e a12s12 is \e s12.  It \e
 *! unroll is not set, the value \e lon2 returned is in the range
 *! [−180°, 180°); if unroll is set, the longitude variable
-*! is "unrolled" so that \e lon2 &minus \e lon1 indicates how many times
-*! and in what sense the geodesic encircles the ellipsoid.  Because \e
-*! lon2 might be outside the normal allowed range for longitudes,
-*! [−540°, 540°), be sure to reduces its range with mod(\e
-*! lon2, 360d0) before using it in other calls.
+*! is "unrolled" so that \e lon2 − \e lon1 indicates how many
+*! times and in what sense the geodesic encircles the ellipsoid.
 *!
 *! \e omask is an integer in [0, 16) whose binary bits are interpreted
 *! as follows
@@ -169,9 +166,8 @@
 *! - 4 return \e MM12 and \e MM21
 *! - 8 return \e SS12
 *!
-*! \e lat1 should be in the range [−90°, 90°]; \e lon1 and
-*! \e azi1 should be in the range [−540°, 540°).  The
-*! value \e azi2 returned is in the range [−180°, 180°).
+*! \e lat1 should be in the range [−90°, 90°].  The value
+*! \e azi2 returned is in the range [−180°, 180°).
 *!
 *! If either point is at a pole, the azimuth is defined by keeping the
 *! longitude fixed, writing \e lat = \e lat = ±(90° −
@@ -180,6 +176,9 @@
 *! path.  (For a prolate ellipsoid, an additional condition is necessary
 *! for a shortest path: the longitudinal extent must not exceed of
 *! 180°.)
+*!
+*! Example of use:
+*! \include geoddirect.for
 
       subroutine direct(a, f, lat1, lon1, azi1, s12a12, flags,
      +    lat2, lon2, azi2, omask, a12s12, m12, MM12, MM21, SS12)
@@ -200,14 +199,14 @@
      +    C1a(nC1), C1pa(nC1p), C2a(nC2), C3a(nC3-1), C4a(0:nC4-1)
 
       double precision csmgt, atanhx, hypotx,
-     +    AngNm, AngNm2, AngRnd, TrgSum, A1m1f, A2m1f, A3f
+     +    AngNm, AngRnd, TrgSum, A1m1f, A2m1f, A3f, atn2dx
       logical arcmod, unroll, arcp, redlp, scalp, areap
       double precision e2, f1, ep2, n, b, c2,
-     +    lon1x, azi1x, phi, alp1, salp0, calp0, k2, eps,
+     +    salp0, calp0, k2, eps,
      +    salp1, calp1, ssig1, csig1, cbet1, sbet1, dn1, somg1, comg1,
      +    salp2, calp2, ssig2, csig2, sbet2, cbet2, dn2, somg2, comg2,
      +    ssig12, csig12, salp12, calp12, omg12, lam12, lon12,
-     +    sig12, stau1, ctau1, tau12, s12a, t, s, c, serr, E,
+     +    sig12, stau1, ctau1, tau12, t, s, c, serr, E,
      +    A1m1, A2m1, A3c, A4, AB1, AB2,
      +    B11, B12, B21, B22, B31, B41, B42, J12
 
@@ -250,21 +249,13 @@
       if (areap) call C4cof(n, C4x)
 
 * Guard against underflow in salp0
-      azi1x = AngRnd(AngNm(azi1))
-      lon1x = AngNm(lon1)
-
-* alp1 is in [0, pi]
-      alp1 = azi1x * degree
-* Enforce sin(pi) == 0 and cos(pi/2) == 0.  Better to face the ensuing
-* problems directly than to skirt them.
-      salp1 = csmgt(0d0, sin(alp1), azi1x .eq. -180)
-      calp1 = csmgt(0d0, cos(alp1), abs(azi1x) .eq. 90)
+      call sncsdx(AngRnd(azi1), salp1, calp1)
 
-      phi = lat1 * degree
-* Ensure cbet1 = +dbleps at poles
-      sbet1 = f1 * sin(phi)
-      cbet1 = csmgt(tiny, cos(phi), abs(lat1) .eq. 90)
+      call sncsdx(AngRnd(lat1), sbet1, cbet1)
+      sbet1 = f1 * sbet1
       call norm2(sbet1, cbet1)
+* Ensure cbet1 = +dbleps at poles
+      cbet1 = max(tiny, cbet1)
       dn1 = sqrt(1 + ep2 * sbet1**2)
 
 * Evaluate alp0 from sin(alp1) * cos(bet1) = sin(alp0),
@@ -334,10 +325,7 @@
       if (arcmod) then
 * Interpret s12a12 as spherical arc length
         sig12 = s12a12 * degree
-        s12a = abs(s12a12)
-        s12a = s12a - 180 * aint(s12a / 180)
-        ssig12 =  csmgt(0d0, sin(sig12), s12a .eq.  0)
-        csig12 =  csmgt(0d0, cos(sig12), s12a .eq. 90)
+        call sncsdx(s12a12, ssig12, csig12)
 * Suppress bogus warnings about unitialized variables
         B12 = 0
       else
@@ -412,23 +400,27 @@
 * East or west going?
       E = sign(1d0, salp0)
 * omg12 = omg2 - omg1
-      omg12 = csmgt(E * (sig12
-     +    - (atan2(    ssig2, csig2) - atan2(    ssig1, csig1))
-     +    + (atan2(E * somg2, comg2) - atan2(E * somg1, comg1))),
-     +    atan2(somg2 * comg1 - comg2 * somg1,
-     +    comg2 * comg1 + somg2 * somg1),
-     +    unroll)
+      if (unroll) then
+        omg12 = E * (sig12
+     +      - (atan2(    ssig2, csig2) - atan2(    ssig1, csig1))
+     +      + (atan2(E * somg2, comg2) - atan2(E * somg1, comg1)))
+      else
+        omg12 = atan2(somg2 * comg1 - comg2 * somg1,
+     +      comg2 * comg1 + somg2 * somg1)
+      end if
 
       lam12 = omg12 + A3c *
      +    ( sig12 + (TrgSum(.true., ssig2, csig2, C3a, nC3-1)
      +    - B31))
       lon12 = lam12 / degree
-* Use Math::AngNm2 because longitude might have wrapped multiple
-* times.
-      lon2 = csmgt(lon1 + lon12, AngNm(lon1x + AngNm2(lon12)), unroll)
-      lat2 = atan2(sbet2, f1 * cbet2) / degree
+      if (unroll) then
+        lon2 = lon1 + lon12
+      else
+        lon2 = AngNm(AngNm(lon1) + AngNm(lon12))
+      end if
+      lat2 = atn2dx(sbet2, f1 * cbet2)
 * minus signs give range [-180, 180). 0- converts -0 to +0.
-      azi2 = 0 - atan2(-salp2, calp2) / degree
+      azi2 = atn2dx(salp2, calp2)
 
       if (redlp .or. scalp) then
         B22 = TrgSum(.true., ssig2, csig2, C2a, nC2)
@@ -511,10 +503,9 @@
 *! - 4 return \e MM12 and \e MM21
 *! - 8 return \e SS12
 *!
-*! \e lat1 and \e lat2 should be in the range [−90°, 90°];
-*! \e lon1 and \e lon2 should be in the range [−540°,
-*! 540°).  The values of \e azi1 and \e azi2 returned are in the
-*! range [−180°, 180°).
+*! \e lat1 and \e lat2 should be in the range [−90°, 90°].
+*! The values of \e azi1 and \e azi2 returned are in the range
+*! [−180°, 180°).
 *!
 *! If either point is at a pole, the azimuth is defined by keeping the
 *! longitude fixed, writing \e lat = ±(90° −
@@ -524,6 +515,9 @@
 *! If this fails to converge (this is very unlikely in geodetic
 *! applications but does occur for very eccentric ellipsoids), then the
 *! bisection method is used to refine the solution.
+*!
+*! Example of use:
+*! \include geodinverse.for
 
       subroutine invers(a, f, lat1, lon1, lat2, lon2,
      +    s12, azi1, azi2, omask, a12, m12, MM12, MM21, SS12)
@@ -535,20 +529,21 @@
 * optional output
       double precision a12, m12, MM12, MM21, SS12
 
-      integer ord, nC1, nC2, nA3, nA3x, nC3, nC3x, nC4, nC4x
-      parameter (ord = 6, nC1 = ord, nC2 = ord, nA3 = ord, nA3x = nA3,
+      integer ord, nA3, nA3x, nC3, nC3x, nC4, nC4x, nC
+      parameter (ord = 6, nA3 = ord, nA3x = nA3,
      +    nC3 = ord, nC3x = (nC3 * (nC3 - 1)) / 2,
-     +    nC4 = ord, nC4x = (nC4 * (nC4 + 1)) / 2)
+     +    nC4 = ord, nC4x = (nC4 * (nC4 + 1)) / 2,
+     +    nC = ord)
       double precision A3x(0:nA3x-1), C3x(0:nC3x-1), C4x(0:nC4x-1),
-     +    C1a(nC1), C2a(nC2), C3a(nC3-1), C4a(0:nC4-1)
+     +    Ca(nC)
 
       double precision csmgt, atanhx, hypotx,
-     +    AngNm, AngDif, AngRnd, TrgSum, Lam12f, InvSta
+     +    AngDif, AngRnd, TrgSum, Lam12f, InvSta, atn2dx
       integer latsgn, lonsgn, swapp, numit
       logical arcp, redlp, scalp, areap, merid, tripn, tripb
 
       double precision e2, f1, ep2, n, b, c2,
-     +    lat1x, lat2x, phi, salp0, calp0, k2, eps,
+     +    lat1x, lat2x, salp0, calp0, k2, eps,
      +    salp1, calp1, ssig1, csig1, cbet1, sbet1, dbet1, dn1,
      +    salp2, calp2, ssig2, csig2, sbet2, cbet2, dbet2, dn2,
      +    slam12, clam12, salp12, calp12, omg12, lam12, lon12,
@@ -559,7 +554,7 @@
 
       double precision dblmin, dbleps, pi, degree, tiny,
      +    tol0, tol1, tol2, tolb, xthrsh
-      integer digits, maxit1, maxit2
+      integer digits, maxit1, maxit2, lmask
       logical init
       common /geocom/ dblmin, dbleps, pi, degree, tiny,
      +    tol0, tol1, tol2, tolb, xthrsh, digits, maxit1, maxit2, init
@@ -577,6 +572,11 @@
       redlp = mod(omask/2, 2) == 1
       scalp = mod(omask/4, 2) == 1
       areap = mod(omask/8, 2) == 1
+      if (scalp) then
+        lmask = 16 + 2 + 4
+      else
+        lmask = 16 + 2
+      end if
 
       if (areap) then
         if (e2 .eq. 0) then
@@ -595,9 +595,8 @@
 * Compute longitude difference (AngDiff does this carefully).  Result is
 * in [-180, 180] but -180 is only for west-going geodesics.  180 is for
 * east-going and meridional geodesics.
-      lon12 = AngDif(AngNm(lon1), AngNm(lon2))
 * If very close to being on the same half-meridian, then make it so.
-      lon12 = AngRnd(lon12)
+      lon12 = AngRnd(AngDif(lon1, lon2))
 * Make longitude difference positive.
       if (lon12 .ge. 0) then
         lonsgn = 1
@@ -638,17 +637,17 @@
 * to check, e.g., on verifying quadrants in atan2.  In addition, this
 * enforces some symmetries in the results returned.
 
-      phi = lat1x * degree
-* Ensure cbet1 = +dbleps at poles
-      sbet1 = f1 * sin(phi)
-      cbet1 = csmgt(tiny, cos(phi), lat1x .eq. -90)
+      call sncsdx(lat1x, sbet1, cbet1)
+      sbet1 = f1 * sbet1
       call norm2(sbet1, cbet1)
+* Ensure cbet1 = +dbleps at poles
+      cbet1 = max(tiny, cbet1)
 
-      phi = lat2x * degree
-* Ensure cbet2 = +dbleps at poles
-      sbet2 = f1 * sin(phi)
-      cbet2 = csmgt(tiny, cos(phi), abs(lat2x) .eq. 90)
+      call sncsdx(lat2x, sbet2, cbet2)
+      sbet2 = f1 * sbet2
       call norm2(sbet2, cbet2)
+* Ensure cbet2 = +dbleps at poles
+      cbet2 = max(tiny, cbet2)
 
 * If cbet1 < -sbet1, then cbet2 - cbet1 is a sensitive measure of the
 * |bet1| - |bet2|.  Alternatively (cbet1 >= -sbet1), abs(sbet2) + sbet1
@@ -669,10 +668,7 @@
       dn2 = sqrt(1 + ep2 * sbet2**2)
 
       lam12 = lon12 * degree
-      slam12 = sin(lam12)
-      if (lon12 .eq. 180) slam12 = 0
-* lon12 == 90 isn't interesting
-      clam12 = cos(lam12)
+      call sncsdx(lon12, slam12, clam12)
 
 * Suppress bogus warnings about unitialized variables
       a12x = 0
@@ -700,8 +696,8 @@
         sig12 = atan2(max(csig1 * ssig2 - ssig1 * csig2, 0d0),
      +      csig1 * csig2 + ssig1 * ssig2)
         call Lengs(n, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2,
-     +      cbet1, cbet2, s12x, m12x, dummy,
-     +      scalp, MM12, MM21, ep2, C1a, C2a)
+     +      cbet1, cbet2, lmask,
+     +      s12x, m12x, dummy, MM12, MM21, ep2, Ca)
 
 * Add the check for sig12 since zero length geodesics might yield m12 <
 * 0.  Test case was
@@ -711,6 +707,11 @@
 * In fact, we will have sig12 > pi/2 for meridional geodesic which is
 * not a shortest path.
         if (sig12 .lt. 1 .or. m12x .ge. 0) then
+          if (sig12 .lt. 3 * tiny) then
+            sig12 = 0
+            m12x = 0
+            s12x = 0
+          end if
           m12x = m12x * b
           s12x = s12x * b
           a12x = sig12 / degree
@@ -744,7 +745,7 @@
 
 * Figure a starting point for Newton's method
         sig12 = InvSta(sbet1, cbet1, dn1, sbet2, cbet2, dn2, lam12,
-     +      f, A3x, salp1, calp1, salp2, calp2, dnm, C1a, C2a)
+     +      f, A3x, salp1, calp1, salp2, calp2, dnm, Ca)
 
         if (sig12 .ge. 0) then
 * Short lines (InvSta sets salp2, calp2, dnm)
@@ -784,7 +785,7 @@
      +          salp1, calp1, f, A3x, C3x, salp2, calp2, sig12,
      +          ssig1, csig1, ssig2, csig2,
      +          eps, omg12, numit .lt. maxit1, dv,
-     +          C1a, C2a, C3a) - lam12
+     +          Ca) - lam12
 * 2 * tol0 is approximately 1 ulp for a number in [0, pi].
 * Reversed test to allow escape with NaNs
             if (tripb .or.
@@ -832,9 +833,9 @@
      +          .or. abs(salp1 - salp1b) + (calp1 - calp1b) .lt. tolb
  10       continue
  20       continue
-          call Lengs(eps, sig12, ssig1, csig1, dn1,
-     +        ssig2, csig2, dn2, cbet1, cbet2, s12x, m12x, dummy,
-     +        scalp, MM12, MM21, ep2, C1a, C2a)
+          call Lengs(eps, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2,
+     +        cbet1, cbet2, lmask,
+     +        s12x, m12x, dummy, MM12, MM21, ep2, Ca)
           m12x = m12x * b
           s12x = s12x * b
           a12x = sig12 / degree
@@ -862,9 +863,9 @@
           A4 = a**2 * calp0 * salp0 * e2
           call norm2(ssig1, csig1)
           call norm2(ssig2, csig2)
-          call C4f(eps, C4x, C4a)
-          B41 = TrgSum(.false., ssig1, csig1, C4a, nC4)
-          B42 = TrgSum(.false., ssig2, csig2, C4a, nC4)
+          call C4f(eps, C4x, Ca)
+          B41 = TrgSum(.false., ssig1, csig1, Ca, nC4)
+          B42 = TrgSum(.false., ssig2, csig2, Ca, nC4)
           SS12 = A4 * (B42 - B41)
         else
 * Avoid problems with indeterminate sig1, sig2 on equator
@@ -915,8 +916,8 @@
       calp2 = calp2 * swapp * latsgn
 
 * minus signs give range [-180, 180). 0- converts -0 to +0.
-      azi1 = 0 - atan2(-salp1, calp1) / degree
-      azi2 = 0 - atan2(-salp2, calp2) / degree
+      azi1 = atn2dx(salp1, calp1)
+      azi2 = atn2dx(salp2, calp2)
 
       if (arcp) a12 = a12x
 
@@ -930,12 +931,11 @@
 *!   a sphere.  Negative \e f gives a prolate ellipsoid.
 *! @param[in] lats an array of the latitudes of the vertices (degrees).
 *! @param[in] lons an array of the longitudes of the vertices (degrees).
-*! @param[in] n the number of vertices
-*! @param[out] AA the (signed) area of the polygon (meters<sup>2</sup>)
-*! @param[out] PP the perimeter of the polygon
+*! @param[in] n the number of vertices.
+*! @param[out] AA the (signed) area of the polygon (meters<sup>2</sup>).
+*! @param[out] PP the perimeter of the polygon.
 *!
-*! \e lats should be in the range [−90°, 90°]; \e lons
-*! should be in the range [−540°, 540°).
+*! \e lats should be in the range [−90°, 90°].
 *!
 *! Only simple polygons (which are not self-intersecting) are allowed.
 *! There's no need to "close" the polygon by repeating the first vertex.
@@ -1000,6 +1000,25 @@
       return
       end
 
+*> Return the version numbers for this package.
+*!
+*! @param[out] major the major version number.
+*! @param[out] minor the minor version number.
+*! @param[out] patch the patch number.
+*!
+*! This subroutine was added with version 1.44.
+
+      subroutine geover(major, minor, patch)
+* output
+      integer major, minor, patch
+
+      major = 1
+      minor = 44
+      patch = 0
+
+      return
+      end
+
 *> @cond SKIP
 
       block data geodat
@@ -1044,47 +1063,75 @@
       return
       end
 
-      subroutine Lengs(eps, sig12,
-     +    ssig1, csig1, dn1, ssig2, csig2, dn2,
-     +    cbet1, cbet2, s12b, m12b, m0,
-     +    scalp, MM12, MM21, ep2, C1a, C2a)
+      subroutine Lengs(eps, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2,
+     +    cbet1, cbet2, omask,
+     +    s12b, m12b, m0, MM12, MM21, ep2, Ca)
 * input
       double precision eps, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2,
      +    cbet1, cbet2, ep2
-      logical scalp
-* output
-      double precision s12b, m12b, m0
+      integer omask
 * optional output
-      double precision MM12, MM21
+      double precision s12b, m12b, m0, MM12, MM21
 * temporary storage
-      double precision C1a(*), C2a(*)
+      double precision Ca(*)
 
       integer ord, nC1, nC2
       parameter (ord = 6, nC1 = ord, nC2 = ord)
 
       double precision A1m1f, A2m1f, TrgSum
-      double precision A1m1, AB1, A2m1, AB2, J12, csig12, t
+      double precision m0x, J12, A1, A2, B1, B2, csig12, t, Cb(nC2)
+      logical distp, redlp, scalp
+      integer l
 
 * Return m12b = (reduced length)/b; also calculate s12b = distance/b,
 * and m0 = coefficient of secular term in expression for reduced length.
-      call C1f(eps, C1a)
-      call C2f(eps, C2a)
 
-      A1m1 = A1m1f(eps)
-      AB1 = (1 + A1m1) * (TrgSum(.true., ssig2, csig2, C1a, nC1) -
-     +    TrgSum(.true., ssig1, csig1, C1a, nC1))
-      A2m1 = A2m1f(eps)
-      AB2 = (1 + A2m1) * (TrgSum(.true., ssig2, csig2, C2a, nC2) -
-     +    TrgSum(.true., ssig1, csig1, C2a, nC2))
-      m0 = A1m1 - A2m1
-      J12 = m0 * sig12 + (AB1 - AB2)
+      distp = mod(omask/16, 2) == 1
+      redlp = mod(omask/2, 2) == 1
+      scalp = mod(omask/4, 2) == 1
+
+* Suppress compiler warnings
+      m0x = 0
+      J12 = 0
+      A1 = 0
+      A2 = 0
+      if (distp .or. redlp .or. scalp) then
+        A1 = A1m1f(eps)
+        call C1f(eps, Ca)
+        if (redlp .or. scalp) then
+          A2 = A2m1f(eps)
+          call C2f(eps, Cb)
+          m0x = A1 - A2
+          A2 = 1 + A2
+        end if
+        A1 = 1 + A1
+      end if
+      if (distp) then
+        B1 = TrgSum(.true., ssig2, csig2, Ca, nC1) -
+     +      TrgSum(.true., ssig1, csig1, Ca, nC1)
+* Missing a factor of b
+        s12b = A1 * (sig12 + B1)
+        if (redlp .or. scalp) then
+          B2 = Trgsum(.true., ssig2, csig2, Cb, nC2) -
+     +        TrgSum(.true., ssig1, csig1, Cb, nC2)
+          J12 = m0x * sig12 + (A1 * B1 - A2 * B2)
+        end if
+      else if (redlp .or. scalp) then
+* Assume here that nC1 >= nC2
+        do 10 l = 1, nC2
+          Cb(l) = A1 * Ca(l) - A2 * Cb(l)
+ 10     continue
+        J12 = m0x * sig12 + (TrgSum(.true., ssig2, csig2, Cb, nC2) -
+     +      TrgSum(.true., ssig1, csig1, Cb, nC2))
+      end if
+      if (redlp) then
+        m0 = m0x
 * Missing a factor of b.
 * Add parens around (csig1 * ssig2) and (ssig1 * csig2) to ensure
 * accurate cancellation in the case of coincident points.
-      m12b = dn2 * (csig1 * ssig2) - dn1 * (ssig1 * csig2) -
-     +    csig1 * csig2 * J12
-* Missing a factor of b
-      s12b = (1 + A1m1) * sig12 + AB1
+        m12b = dn2 * (csig1 * ssig2) - dn1 * (ssig1 * csig2) -
+     +      csig1 * csig2 * J12
+      end if
       if (scalp) then
         csig12 = csig1 * csig2 + ssig1 * ssig2
         t = ep2 * (cbet1 - cbet2) * (cbet1 + cbet2) / (dn1 + dn2)
@@ -1115,7 +1162,7 @@
         S = p * q / 4
         r2 = r**2
         r3 = r * r2
-* The discrimant of the quadratic equation for T3.  This is zero on
+* The discriminant of the quadratic equation for T3.  This is zero on
 * the evolute curve p^(1/3)+q^(1/3) = 1
         disc = S * (S + 2 * r3)
         u = r
@@ -1163,7 +1210,7 @@
       double precision function InvSta(sbet1, cbet1, dn1,
      +    sbet2, cbet2, dn2, lam12, f, A3x,
      +    salp1, calp1, salp2, calp2, dnm,
-     +    C1a, C2a)
+     +    Ca)
 * Return a starting point for Newton's method in salp1 and calp1
 * (function value is -1).  If Newton's method doesn't need to be used,
 * return also salp2, calp2, and dnm and function value is sig12.
@@ -1173,7 +1220,7 @@
 * output
       double precision salp1, calp1, salp2, calp2, dnm
 * temporary
-      double precision C1a(*), C2a(*)
+      double precision Ca(*)
 
       double precision csmgt, hypotx, A3f, Astrd
       logical shortp
@@ -1266,9 +1313,8 @@
 * In the case of lon12 = 180, this repeats a calculation made in
 * Inverse.
           call Lengs(n, pi + bt12a,
-     +        sbet1, -cbet1, dn1, sbet2, cbet2, dn2,
-     +        cbet1, cbet2, dummy, m12b, m0, .false.,
-     +        dummy, dummy, ep2, C1a, C2a)
+     +        sbet1, -cbet1, dn1, sbet2, cbet2, dn2, cbet1, cbet2, 2,
+     +        dummy, m12b, m0, dummy, dummy, ep2, Ca)
           x = -1 + m12b / (cbet1 * cbet2 * m0 * pi)
           betscl = csmgt(sbt12a / x, -f * cbet1**2 * pi,
      +        x .lt. -0.01d0)
@@ -1345,7 +1391,7 @@
       double precision function Lam12f(sbet1, cbet1, dn1,
      +    sbet2, cbet2, dn2, salp1, calp1, f, A3x, C3x, salp2, calp2,
      +    sig12, ssig1, csig1, ssig2, csig2, eps, domg12, diffp, dlam12,
-     +    C1a, C2a, C3a)
+     +    Ca)
 * input
       double precision sbet1, cbet1, dn1, sbet2, cbet2, dn2,
      +    salp1, calp1, f, A3x(*), C3x(*)
@@ -1356,7 +1402,7 @@
 * optional output
       double precision dlam12
 * temporary
-      double precision C1a(*), C2a(*), C3a(*)
+      double precision Ca(*)
 
       integer ord, nC3
       parameter (ord = 6, nC3 = ord)
@@ -1426,9 +1472,9 @@
      +    comg1 * comg2 + somg1 * somg2)
       k2 = calp0**2 * ep2
       eps = k2 / (2 * (1 + sqrt(1 + k2)) + k2)
-      call C3f(eps, C3x, C3a)
-      B312 = (TrgSum(.true., ssig2, csig2, C3a, nC3-1) -
-     +    TrgSum(.true., ssig1, csig1, C3a, nC3-1))
+      call C3f(eps, C3x, Ca)
+      B312 = (TrgSum(.true., ssig2, csig2, Ca, nC3-1) -
+     +    TrgSum(.true., ssig1, csig1, Ca, nC3-1))
       h0 = -f * A3f(eps, A3x)
       domg12 = salp0 * h0 * (sig12 + B312)
       lam12 = omg12 + domg12
@@ -1438,8 +1484,8 @@
           dlam12 = - 2 * f1 * dn1 / sbet1
         else
           call Lengs(eps, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2,
-     +        cbet1, cbet2, dummy, dlam12, dummy,
-     +        .false., dummy, dummy, ep2, C1a, C2a)
+     +        cbet1, cbet2, 2,
+     +        dummy, dlam12, dummy, dummy, dummy, ep2, Ca)
           dlam12 = dlam12 * f1 / (calp2 * cbet2)
         end if
       end if
@@ -1612,12 +1658,12 @@
       integer ord, nA2, o, m
       parameter (ord = 6, nA2 = ord)
       double precision polval, coeff(nA2/2 + 2)
-      data coeff /25, 36, 64, 0, 256/
+      data coeff /-11, -28, -192, 0, 256/
 
       o = 1
       m = nA2/2
       t = polval(m, coeff(o), eps**2) / coeff(o + m + 1)
-      A2m1f = t * (1 - eps) - eps
+      A2m1f = (t - eps) / (1 + eps)
 
       return
       end
@@ -1793,28 +1839,16 @@
 * input
       double precision x
 
-      if (x .ge. 180) then
-        AngNm = x - 360
-      else if (x .lt. -180) then
-        AngNm = x + 360
-      else
-        AngNm = x
+      AngNm = mod(x, 360d0)
+      if (AngNm .lt. -180) then
+        AngNm = AngNm + 360
+      else if (AngNm .ge. 180) then
+        AngNm = AngNm - 360
       end if
 
       return
       end
 
-      double precision function AngNm2(x)
-* input
-      double precision x
-
-      double precision AngNm
-      AngNm2 = mod(x, 360d0)
-      AngNm2 = AngNm(AngNm2)
-
-      return
-      end
-
       double precision function AngDif(x, y)
 * Compute y - x.  x and y must both lie in [-180, 180].  The result is
 * equivalent to computing the difference exactly, reducing it to (-180,
@@ -1823,14 +1857,12 @@
 * input
       double precision x, y
 
-      double precision d, t, sumx
-      d = sumx(-x, y, t)
-      if ((d - 180d0) + t .gt. 0d0) then
-        d = d - 360d0
-      else if ((d + 180d0) + t .le. 0d0) then
-        d = d + 360d0
+      double precision d, t, sumx, AngNm
+      d = - AngNm(sumx(AngNm(x), AngNm(-y), t))
+      if (d .eq. 180 .and. t .lt. 0) then
+        d = -180
       end if
-      AngDif = d + t
+      AngDif = d - t
 
       return
       end
@@ -1876,14 +1908,14 @@
       return
       end
 
-      subroutine norm2(sinx, cosx)
+      subroutine norm2(x, y)
 * input/output
-      double precision sinx, cosx
+      double precision x, y
 
       double precision hypotx, r
-      r = hypotx(sinx, cosx)
-      sinx = sinx/r
-      cosx = cosx/r
+      r = hypotx(x, y)
+      x = x/r
+      y = y/r
 
       return
       end
@@ -2025,6 +2057,88 @@
       return
       end
 
+      subroutine sncsdx(x, sinx, cosx)
+* Compute sin(x) and cos(x) with x in degrees
+* input
+      double precision x
+* input/output
+      double precision sinx, cosx
+
+      double precision dblmin, dbleps, pi, degree, tiny,
+     +    tol0, tol1, tol2, tolb, xthrsh
+      integer digits, maxit1, maxit2
+      logical init
+      common /geocom/ dblmin, dbleps, pi, degree, tiny,
+     +    tol0, tol1, tol2, tolb, xthrsh, digits, maxit1, maxit2, init
+
+      double precision r, s, c
+      integer q
+      r = mod(x, 360d0)
+      q = nint(r / 90)
+      r = (r - 90 * q) * degree
+      s = sin(r)
+      c = cos(r)
+      q = mod(q + 4, 4)
+      if (q .eq. 0) then
+        sinx =     s
+        cosx =     c
+      else if (q .eq. 1) then
+        sinx =     c
+        cosx = 0 - s
+      else if (q .eq. 2) then
+        sinx = 0 - s
+        cosx = 0 - c
+      else
+* q.eq.3
+        sinx = 0 - c
+        cosx =     s
+      end if
+
+      return
+      end
+
+      double precision function atn2dx(y, x)
+* input
+      double precision x, y
+
+      double precision dblmin, dbleps, pi, degree, tiny,
+     +    tol0, tol1, tol2, tolb, xthrsh
+      integer digits, maxit1, maxit2
+      logical init
+      common /geocom/ dblmin, dbleps, pi, degree, tiny,
+     +    tol0, tol1, tol2, tolb, xthrsh, digits, maxit1, maxit2, init
+
+      double precision xx, yy
+      integer q
+      if (abs(y) .gt. abs(x)) then
+        xx = y
+        yy = x
+        q = 2
+      else
+        xx = x
+        yy = y
+        q = 0
+      end if
+      if (xx .lt. 0) then
+        xx = -xx
+        q = q + 1
+      end if
+      atn2dx = atan2(yy, xx) / degree
+      if (q .eq. 1) then
+        if (yy .gt. 0) then
+          atn2dx =  180 - atn2dx
+        else
+          atn2dx = -180 - atn2dx
+        end if
+      else if (q .eq. 2) then
+        atn2dx =  90 - atn2dx
+      else if (q .eq. 3) then
+        atn2dx = -90 + atn2dx
+      end if
+
+      return
+      end
+
       double precision function polval(N, p, x)
 * input
       integer N
@@ -2049,7 +2163,6 @@
 *    C3coeff       C3cof
 *    C4coeff       C4cof
 *    AngNormalize  AngNm
-*    AngNormalize2 AngNm2
 *    AngDiff       AngDif
 *    AngRound      AngRnd
 *    arcmode       arcmod
@@ -2076,4 +2189,6 @@
 *    transit       trnsit
 *    polyval       polval
 *    LONG_UNROLL   unroll
+*    sincosd       sncsdx
+*    atan2d        atn2dx
 *> @endcond SKIP
diff --git a/legacy/Fortran/geodesic.inc b/legacy/Fortran/geodesic.inc
index 0106b34..585066b 100644
--- a/legacy/Fortran/geodesic.inc
+++ b/legacy/Fortran/geodesic.inc
@@ -31,4 +31,8 @@
         double precision, intent(out) :: AA, PP
         end subroutine area
 
+        subroutine geover(major, minor, patch)
+        integer, intent(out) :: major, minor, patch
+        end subroutine geover
+
       end interface
diff --git a/legacy/Fortran/geodinverse.for b/legacy/Fortran/geodinverse.for
index aa562c3..60a347e 100644
--- a/legacy/Fortran/geodinverse.for
+++ b/legacy/Fortran/geodinverse.for
@@ -23,12 +23,18 @@
 
  10   continue
       read(*, *, end=90, err=90) lat1, lon1, lat2, lon2
+      if (abs(lat1) .gt. 90 .or. abs(lat2) .gt. 90) then
+        print 15
+ 15     format(1x,'lat1 and lat2 must be in [-90,90]')
+        go to 10
+      end if
       call invers(a, f, lat1, lon1, lat2, lon2,
      +    s12, azi1, azi2, omask,
      +    dummy1, dummy2, dummy3, dummy4 , dummy5)
       print 20, azi1, azi2, s12
- 20   format(f20.15, 1x, f20.15, 1x, f19.10)
+ 20   format(1x, f20.15, 1x, f20.15, 1x, f19.10)
       go to 10
  90   continue
+
       stop
       end
diff --git a/man/CartConvert.1 b/man/CartConvert.1
index 7eda5e6..1111f23 100644
--- a/man/CartConvert.1
+++ b/man/CartConvert.1
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "CARTCONVERT 1"
-.TH CARTCONVERT 1 "2015-05-22" "GeographicLib 1.43" "GeographicLib Utilities"
+.TH CARTCONVERT 1 "2015-08-14" "GeographicLib 1.44" "GeographicLib Utilities"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
@@ -142,7 +142,8 @@
 CartConvert \-\- convert geodetic coordinates to geocentric or local cartesian
 .SH "SYNOPSIS"
 .IX Header "SYNOPSIS"
-\&\fBCartConvert\fR [ \fB\-r\fR ] [ \fB\-l\fR \fIlat0\fR \fIlon0\fR \fIh0\fR ] [ \fB\-e\fR \fIa\fR \fIf\fR ]
+\&\fBCartConvert\fR [ \fB\-r\fR ] [ \fB\-l\fR \fIlat0\fR \fIlon0\fR \fIh0\fR ]
+[ \fB\-e\fR \fIa\fR \fIf\fR ] [ \fB\-w\fR ] [ \fB\-p\fR prec ]
 [ \fB\-\-comment\-delimiter\fR \fIcommentdelim\fR ]
 [ \fB\-\-version\fR | \fB\-h\fR | \fB\-\-help\fR ]
 [ \fB\-\-input\-file\fR \fIinfile\fR | \fB\-\-input\-string\fR \fIinstring\fR ]
@@ -162,9 +163,10 @@ origin at \fIlatitude\fR = \fIlat0\fR, \fIlongitude\fR = \fIlon0\fR, \fIheight\f
 Geodetic coordinates are provided on standard input as a set of lines
 containing (blank separated) \fIlatitude\fR, \fIlongitude\fR (decimal degrees
 or degrees, minutes and seconds), and \fIheight\fR above the ellipsoid
-(meters).  For each set of geodetic coordinates, the corresponding
-cartesian coordinates \fIx\fR, \fIy\fR, \fIz\fR (meters) are printed on standard
-output.
+(meters); for details on the allowed formats for latitude and longitude,
+see the \f(CW\*(C`GEOGRAPHIC COORDINATES\*(C'\fR section of \fIGeoConvert\fR\|(1).  For each
+set of geodetic coordinates, the corresponding cartesian coordinates
+\&\fIx\fR, \fIy\fR, \fIz\fR (meters) are printed on standard output.
 .SH "OPTIONS"
 .IX Header "OPTIONS"
 .IP "\fB\-r\fR" 4
@@ -172,6 +174,12 @@ output.
 perform the reverse projection.  \fIx\fR, \fIy\fR, \fIz\fR are given on standard
 input and each line of standard output gives \fIlatitude\fR, \fIlongitude\fR,
 \&\fIheight\fR.
+.IP "\fB\-l\fR" 4
+.IX Item "-l"
+specifies conversions to and from a local cartesion coordinate systems
+with origin \fIlat0\fR \fIlon0\fR \fIh0\fR, instead of a geocentric coordinate
+system.  The \fB\-w\fR flag can be used to swap the default order of the 2
+geographic coordinates, provided that it appears before \fB\-l\fR.
 .IP "\fB\-e\fR" 4
 .IX Item "-e"
 specify the ellipsoid via \fIa\fR \fIf\fR; the equatorial radius is \fIa\fR and
@@ -180,6 +188,18 @@ the flattening is \fIf\fR.  Setting \fIf\fR = 0 results in a sphere.  Specify
 is allowed for \fIf\fR.  (Also, if \fIf\fR > 1, the flattening is set to
 1/\fIf\fR.)  By default, the \s-1WGS84\s0 ellipsoid is used, \fIa\fR = 6378137 m,
 \&\fIf\fR = 1/298.257223563.
+.IP "\fB\-w\fR" 4
+.IX Item "-w"
+on input and output, longitude precedes latitude (except that, on input,
+this can be overridden by a hemisphere designator, \fIN\fR, \fIS\fR, \fIE\fR,
+\&\fIW\fR).
+.IP "\fB\-p\fR" 4
+.IX Item "-p"
+set the output precision to \fIprec\fR (default 6).  \fIprec\fR is the number
+of digits after the decimal point for geocentric and local cartesion
+coordinates and for the height (in meters).  For latitudes and
+longitudes (in degrees), the number of digits after the decimal point is
+\&\fIprec\fR + 5.
 .IP "\fB\-\-comment\-delimiter\fR" 4
 .IX Item "--comment-delimiter"
 set the comment delimiter to \fIcommentdelim\fR (e.g., \*(L"#\*(R" or \*(L"//\*(R").  If
diff --git a/man/CartConvert.1.html b/man/CartConvert.1.html
index 17ec775..d44a714 100644
--- a/man/CartConvert.1.html
+++ b/man/CartConvert.1.html
@@ -17,13 +17,13 @@
 
 <h1 id="SYNOPSIS">SYNOPSIS</h1>
 
-<p><b>CartConvert</b> [ <b>-r</b> ] [ <b>-l</b> <i>lat0</i> <i>lon0</i> <i>h0</i> ] [ <b>-e</b> <i>a</i> <i>f</i> ] [ <b>--comment-delimiter</b> <i>commentdelim</i> ] [ <b>--version</b> | <b>-h</b> | <b>--help</b> ] [ <b>--input-file</b> <i>infile</i> | <b>--input-string</b> <i>instring</i> ] [ <b>--line-separator</b> <i>linesep</i> ] [ <b>--output-file</b> <i>outfile</i> ]</p>
+<p><b>CartConvert</b> [ <b>-r</b> ] [ <b>-l</b> <i>lat0</i> <i>lon0</i> <i>h0</i> ] [ <b>-e</b> <i>a</i> <i>f</i> ] [ <b>-w</b> ] [ <b>-p</b> prec ] [ <b>--comment-delimiter</b> <i>commentdelim</i> ] [ <b>--version</b> | <b>-h</b> | <b>--help</b> ] [ <b>--input-file</b> <i>infile</i> | <b>--input-string</b> <i>instring</i> ] [ <b>--line-separator</b> <i>linesep</i> ] [ <b>--output-file</b> <i>outfile</i> ]</p>
 
 <h1 id="DESCRIPTION">DESCRIPTION</h1>
 
 <p>Convert geodetic coordinates to either geocentric or local cartesian coordinates. Geocentric coordinates have the origin at the center of the earth, with the <i>z</i> axis going thru the north pole, and the <i>x</i> axis thru <i>latitude</i> = 0, <i>longitude</i> = 0. By default, the conversion is to geocentric coordinates. Specifying <b>-l</b> <i>lat0</i> <i>lon0</i> <i>h0</i> causes a local coordinate system to be used with the origin at <i>latitude</i> = <i>lat0</i>, <i>longitude</ [...]
 
-<p>Geodetic coordinates are provided on standard input as a set of lines containing (blank separated) <i>latitude</i>, <i>longitude</i> (decimal degrees or degrees, minutes and seconds), and <i>height</i> above the ellipsoid (meters). For each set of geodetic coordinates, the corresponding cartesian coordinates <i>x</i>, <i>y</i>, <i>z</i> (meters) are printed on standard output.</p>
+<p>Geodetic coordinates are provided on standard input as a set of lines containing (blank separated) <i>latitude</i>, <i>longitude</i> (decimal degrees or degrees, minutes and seconds), and <i>height</i> above the ellipsoid (meters); for details on the allowed formats for latitude and longitude, see the <code>GEOGRAPHIC COORDINATES</code> section of GeoConvert(1). For each set of geodetic coordinates, the corresponding cartesian coordinates <i>x</i>, <i>y</i>, <i>z</i> (meters) are prin [...]
 
 <h1 id="OPTIONS">OPTIONS</h1>
 
@@ -35,12 +35,30 @@
 <p>perform the reverse projection. <i>x</i>, <i>y</i>, <i>z</i> are given on standard input and each line of standard output gives <i>latitude</i>, <i>longitude</i>, <i>height</i>.</p>
 
 </dd>
+<dt id="l"><b>-l</b></dt>
+<dd>
+
+<p>specifies conversions to and from a local cartesion coordinate systems with origin <i>lat0</i> <i>lon0</i> <i>h0</i>, instead of a geocentric coordinate system. The <b>-w</b> flag can be used to swap the default order of the 2 geographic coordinates, provided that it appears before <b>-l</b>.</p>
+
+</dd>
 <dt id="e"><b>-e</b></dt>
 <dd>
 
 <p>specify the ellipsoid via <i>a</i> <i>f</i>; the equatorial radius is <i>a</i> and the flattening is <i>f</i>. Setting <i>f</i> = 0 results in a sphere. Specify <i>f</i> < 0 for a prolate ellipsoid. A simple fraction, e.g., 1/297, is allowed for <i>f</i>. (Also, if <i>f</i> > 1, the flattening is set to 1/<i>f</i>.) By default, the WGS84 ellipsoid is used, <i>a</i> = 6378137 m, <i>f</i> = 1/298.257223563.</p>
 
 </dd>
+<dt id="w"><b>-w</b></dt>
+<dd>
+
+<p>on input and output, longitude precedes latitude (except that, on input, this can be overridden by a hemisphere designator, <i>N</i>, <i>S</i>, <i>E</i>, <i>W</i>).</p>
+
+</dd>
+<dt id="p"><b>-p</b></dt>
+<dd>
+
+<p>set the output precision to <i>prec</i> (default 6). <i>prec</i> is the number of digits after the decimal point for geocentric and local cartesion coordinates and for the height (in meters). For latitudes and longitudes (in degrees), the number of digits after the decimal point is <i>prec</i> + 5.</p>
+
+</dd>
 <dt id="comment-delimiter"><b>--comment-delimiter</b></dt>
 <dd>
 
diff --git a/man/CartConvert.pod b/man/CartConvert.pod
index d68f42a..79073b3 100644
--- a/man/CartConvert.pod
+++ b/man/CartConvert.pod
@@ -4,7 +4,8 @@ CartConvert -- convert geodetic coordinates to geocentric or local cartesian
 
 =head1 SYNOPSIS
 
-B<CartConvert> [ B<-r> ] [ B<-l> I<lat0> I<lon0> I<h0> ] [ B<-e> I<a> I<f> ]
+B<CartConvert> [ B<-r> ] [ B<-l> I<lat0> I<lon0> I<h0> ]
+[ B<-e> I<a> I<f> ] [ B<-w> ] [ B<-p> prec ]
 [ B<--comment-delimiter> I<commentdelim> ]
 [ B<--version> | B<-h> | B<--help> ]
 [ B<--input-file> I<infile> | B<--input-string> I<instring> ]
@@ -25,9 +26,10 @@ I<h0>, I<z> normal to the ellipsoid and I<y> due north.
 Geodetic coordinates are provided on standard input as a set of lines
 containing (blank separated) I<latitude>, I<longitude> (decimal degrees
 or degrees, minutes and seconds), and I<height> above the ellipsoid
-(meters).  For each set of geodetic coordinates, the corresponding
-cartesian coordinates I<x>, I<y>, I<z> (meters) are printed on standard
-output.
+(meters); for details on the allowed formats for latitude and longitude,
+see the C<GEOGRAPHIC COORDINATES> section of GeoConvert(1).  For each
+set of geodetic coordinates, the corresponding cartesian coordinates
+I<x>, I<y>, I<z> (meters) are printed on standard output.
 
 =head1 OPTIONS
 
@@ -39,6 +41,13 @@ perform the reverse projection.  I<x>, I<y>, I<z> are given on standard
 input and each line of standard output gives I<latitude>, I<longitude>,
 I<height>.
 
+=item B<-l>
+
+specifies conversions to and from a local cartesion coordinate systems
+with origin I<lat0> I<lon0> I<h0>, instead of a geocentric coordinate
+system.  The B<-w> flag can be used to swap the default order of the 2
+geographic coordinates, provided that it appears before B<-l>.
+
 =item B<-e>
 
 specify the ellipsoid via I<a> I<f>; the equatorial radius is I<a> and
@@ -48,6 +57,20 @@ is allowed for I<f>.  (Also, if I<f> E<gt> 1, the flattening is set to
 1/I<f>.)  By default, the WGS84 ellipsoid is used, I<a> = 6378137 m,
 I<f> = 1/298.257223563.
 
+=item B<-w>
+
+on input and output, longitude precedes latitude (except that, on input,
+this can be overridden by a hemisphere designator, I<N>, I<S>, I<E>,
+I<W>).
+
+=item B<-p>
+
+set the output precision to I<prec> (default 6).  I<prec> is the number
+of digits after the decimal point for geocentric and local cartesion
+coordinates and for the height (in meters).  For latitudes and
+longitudes (in degrees), the number of digits after the decimal point is
+I<prec> + 5.
+
 =item B<--comment-delimiter>
 
 set the comment delimiter to I<commentdelim> (e.g., "#" or "//").  If
diff --git a/man/CartConvert.usage b/man/CartConvert.usage
index e75d66b..d6723b2 100644
--- a/man/CartConvert.usage
+++ b/man/CartConvert.usage
@@ -1,15 +1,15 @@
 int usage(int retval, bool brief) {
   if (brief)
     ( retval ? std::cerr : std::cout ) << "Usage:\n"
-"    CartConvert [ -r ] [ -l lat0 lon0 h0 ] [ -e a f ] [ --comment-delimiter\n"
-"    commentdelim ] [ --version | -h | --help ] [ --input-file infile |\n"
-"    --input-string instring ] [ --line-separator linesep ] [ --output-file\n"
-"    outfile ]\n"
+"    CartConvert [ -r ] [ -l lat0 lon0 h0 ] [ -e a f ] [ -w ] [ -p prec ] [\n"
+"    --comment-delimiter commentdelim ] [ --version | -h | --help ] [\n"
+"    --input-file infile | --input-string instring ] [ --line-separator\n"
+"    linesep ] [ --output-file outfile ]\n"
 "\n"
 "For full documentation type:\n"
 "    CartConvert --help\n"
 "or visit:\n"
-"    http://geographiclib.sf.net/1.43/CartConvert.1.html\n";
+"    http://geographiclib.sf.net/1.44/CartConvert.1.html\n";
   else
     ( retval ? std::cerr : std::cout ) << "Man page:\n"
 "NAME\n"
@@ -17,10 +17,10 @@ int usage(int retval, bool brief) {
 "       cartesian\n"
 "\n"
 "SYNOPSIS\n"
-"       CartConvert [ -r ] [ -l lat0 lon0 h0 ] [ -e a f ] [ --comment-delimiter\n"
-"       commentdelim ] [ --version | -h | --help ] [ --input-file infile |\n"
-"       --input-string instring ] [ --line-separator linesep ] [ --output-file\n"
-"       outfile ]\n"
+"       CartConvert [ -r ] [ -l lat0 lon0 h0 ] [ -e a f ] [ -w ] [ -p prec ] [\n"
+"       --comment-delimiter commentdelim ] [ --version | -h | --help ] [\n"
+"       --input-file infile | --input-string instring ] [ --line-separator\n"
+"       linesep ] [ --output-file outfile ]\n"
 "\n"
 "DESCRIPTION\n"
 "       Convert geodetic coordinates to either geocentric or local cartesian\n"
@@ -34,15 +34,23 @@ int usage(int retval, bool brief) {
 "\n"
 "       Geodetic coordinates are provided on standard input as a set of lines\n"
 "       containing (blank separated) latitude, longitude (decimal degrees or\n"
-"       degrees, minutes and seconds), and height above the ellipsoid (meters).\n"
-"       For each set of geodetic coordinates, the corresponding cartesian\n"
-"       coordinates x, y, z (meters) are printed on standard output.\n"
+"       degrees, minutes and seconds), and height above the ellipsoid (meters);\n"
+"       for details on the allowed formats for latitude and longitude, see the\n"
+"       \"GEOGRAPHIC COORDINATES\" section of GeoConvert(1).  For each set of\n"
+"       geodetic coordinates, the corresponding cartesian coordinates x, y, z\n"
+"       (meters) are printed on standard output.\n"
 "\n"
 "OPTIONS\n"
 "       -r  perform the reverse projection.  x, y, z are given on standard\n"
 "           input and each line of standard output gives latitude, longitude,\n"
 "           height.\n"
 "\n"
+"       -l  specifies conversions to and from a local cartesion coordinate\n"
+"           systems with origin lat0 lon0 h0, instead of a geocentric\n"
+"           coordinate system.  The -w flag can be used to swap the default\n"
+"           order of the 2 geographic coordinates, provided that it appears\n"
+"           before -l.\n"
+"\n"
 "       -e  specify the ellipsoid via a f; the equatorial radius is a and the\n"
 "           flattening is f.  Setting f = 0 results in a sphere.  Specify f < 0\n"
 "           for a prolate ellipsoid.  A simple fraction, e.g., 1/297, is\n"
@@ -50,6 +58,16 @@ int usage(int retval, bool brief) {
 "           default, the WGS84 ellipsoid is used, a = 6378137 m, f =\n"
 "           1/298.257223563.\n"
 "\n"
+"       -w  on input and output, longitude precedes latitude (except that, on\n"
+"           input, this can be overridden by a hemisphere designator, N, S, E,\n"
+"           W).\n"
+"\n"
+"       -p  set the output precision to prec (default 6).  prec is the number\n"
+"           of digits after the decimal point for geocentric and local\n"
+"           cartesion coordinates and for the height (in meters).  For\n"
+"           latitudes and longitudes (in degrees), the number of digits after\n"
+"           the decimal point is prec + 5.\n"
+"\n"
 "       --comment-delimiter\n"
 "           set the comment delimiter to commentdelim (e.g., \"#\" or \"//\").  If\n"
 "           set, the input lines will be scanned for this delimiter and, if\n"
diff --git a/man/ConicProj.1 b/man/ConicProj.1
index 56f498c..252778a 100644
--- a/man/ConicProj.1
+++ b/man/ConicProj.1
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "CONICPROJ 1"
-.TH CONICPROJ 1 "2015-05-22" "GeographicLib 1.43" "GeographicLib Utilities"
+.TH CONICPROJ 1 "2015-08-14" "GeographicLib 1.44" "GeographicLib Utilities"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
@@ -144,7 +144,7 @@ ConicProj \-\- perform conic projections
 .IX Header "SYNOPSIS"
 \&\fBConicProj\fR ( \fB\-c\fR | \fB\-a\fR ) \fIlat1\fR \fIlat2\fR
 [ \fB\-l\fR \fIlon0\fR ] [ \fB\-k\fR \fIk1\fR ] [ \fB\-r\fR ]
-[ \fB\-e\fR \fIa\fR \fIf\fR ] [ \fB\-p\fR \fIprec\fR ]
+[ \fB\-e\fR \fIa\fR \fIf\fR ] [ \fB\-w\fR ] [ \fB\-p\fR \fIprec\fR ]
 [ \fB\-\-comment\-delimiter\fR \fIcommentdelim\fR ]
 [ \fB\-\-version\fR | \fB\-h\fR | \fB\-\-help\fR ]
 [ \fB\-\-input\-file\fR \fIinfile\fR | \fB\-\-input\-string\fR \fIinstring\fR ]
@@ -165,12 +165,14 @@ area).  The (azimuthal) scale on the standard parallels is \fIk1\fR.
 .PP
 Geodetic coordinates are provided on standard input as a set of lines
 containing (blank separated) \fIlatitude\fR and \fIlongitude\fR (decimal
-degrees or degrees, minutes, seconds).  For each set of geodetic
-coordinates, the corresponding projected easting, \fIx\fR, and northing,
-\&\fIy\fR, (meters) are printed on standard output together with the meridian
-convergence \fIgamma\fR (degrees) and (azimuthal) scale \fIk\fR.  For Albers
-equal area, the radial scale is 1/\fIk\fR.  The meridian convergence is the
-bearing of the \fIy\fR axis measured clockwise from true north.
+degrees or degrees, minutes, seconds);  for details on the allowed
+formats for latitude and longitude, see the \f(CW\*(C`GEOGRAPHIC COORDINATES\*(C'\fR
+section of \fIGeoConvert\fR\|(1).  For each set of geodetic coordinates, the
+corresponding projected easting, \fIx\fR, and northing, \fIy\fR, (meters) are
+printed on standard output together with the meridian convergence
+\&\fIgamma\fR (degrees) and (azimuthal) scale \fIk\fR.  For Albers equal area,
+the radial scale is 1/\fIk\fR.  The meridian convergence is the bearing of
+the \fIy\fR axis measured clockwise from true north.
 .PP
 Special cases of the Lambert conformal projection are the Mercator
 projection (the standard latitudes equal and opposite) and the polar
@@ -210,6 +212,11 @@ the flattening is \fIf\fR.  Setting \fIf\fR = 0 results in a sphere.  Specify
 is allowed for \fIf\fR.  (Also, if \fIf\fR > 1, the flattening is set to
 1/\fIf\fR.)  By default, the \s-1WGS84\s0 ellipsoid is used, \fIa\fR = 6378137 m,
 \&\fIf\fR = 1/298.257223563.
+.IP "\fB\-w\fR" 4
+.IX Item "-w"
+on input and output, longitude precedes latitude (except that, on input,
+this can be overridden by a hemisphere designator, \fIN\fR, \fIS\fR, \fIE\fR,
+\&\fIW\fR).
 .IP "\fB\-p\fR" 4
 .IX Item "-p"
 set the output precision to \fIprec\fR (default 6).  \fIprec\fR is the number
diff --git a/man/ConicProj.1.html b/man/ConicProj.1.html
index 6b6e53f..0ef4bb9 100644
--- a/man/ConicProj.1.html
+++ b/man/ConicProj.1.html
@@ -17,13 +17,13 @@
 
 <h1 id="SYNOPSIS">SYNOPSIS</h1>
 
-<p><b>ConicProj</b> ( <b>-c</b> | <b>-a</b> ) <i>lat1</i> <i>lat2</i> [ <b>-l</b> <i>lon0</i> ] [ <b>-k</b> <i>k1</i> ] [ <b>-r</b> ] [ <b>-e</b> <i>a</i> <i>f</i> ] [ <b>-p</b> <i>prec</i> ] [ <b>--comment-delimiter</b> <i>commentdelim</i> ] [ <b>--version</b> | <b>-h</b> | <b>--help</b> ] [ <b>--input-file</b> <i>infile</i> | <b>--input-string</b> <i>instring</i> ] [ <b>--line-separator</b> <i>linesep</i> ] [ <b>--output-file</b> <i>outfile</i> ]</p>
+<p><b>ConicProj</b> ( <b>-c</b> | <b>-a</b> ) <i>lat1</i> <i>lat2</i> [ <b>-l</b> <i>lon0</i> ] [ <b>-k</b> <i>k1</i> ] [ <b>-r</b> ] [ <b>-e</b> <i>a</i> <i>f</i> ] [ <b>-w</b> ] [ <b>-p</b> <i>prec</i> ] [ <b>--comment-delimiter</b> <i>commentdelim</i> ] [ <b>--version</b> | <b>-h</b> | <b>--help</b> ] [ <b>--input-file</b> <i>infile</i> | <b>--input-string</b> <i>instring</i> ] [ <b>--line-separator</b> <i>linesep</i> ] [ <b>--output-file</b> <i>outfile</i> ]</p>
 
 <h1 id="DESCRIPTION">DESCRIPTION</h1>
 
 <p>Perform one of two conic projections geodesics. Convert geodetic coordinates to either Lambert conformal conic or Albers equal area coordinates. The standard latitudes <i>lat1</i> and <i>lat2</i> are specified by that the <b>-c</b> option (for Lambert conformal conic) or the <b>-a</b> option (for Albers equal area). At least one of these options must be given (the last one given is used). Specify <i>lat1</i> = <i>lat2</i>, to obtain the case with a single standard parallel. The centra [...]
 
-<p>Geodetic coordinates are provided on standard input as a set of lines containing (blank separated) <i>latitude</i> and <i>longitude</i> (decimal degrees or degrees, minutes, seconds). For each set of geodetic coordinates, the corresponding projected easting, <i>x</i>, and northing, <i>y</i>, (meters) are printed on standard output together with the meridian convergence <i>gamma</i> (degrees) and (azimuthal) scale <i>k</i>. For Albers equal area, the radial scale is 1/<i>k</i>. The mer [...]
+<p>Geodetic coordinates are provided on standard input as a set of lines containing (blank separated) <i>latitude</i> and <i>longitude</i> (decimal degrees or degrees, minutes, seconds); for details on the allowed formats for latitude and longitude, see the <code>GEOGRAPHIC COORDINATES</code> section of GeoConvert(1). For each set of geodetic coordinates, the corresponding projected easting, <i>x</i>, and northing, <i>y</i>, (meters) are printed on standard output together with the merid [...]
 
 <p>Special cases of the Lambert conformal projection are the Mercator projection (the standard latitudes equal and opposite) and the polar stereographic projection (both standard latitudes correspond to the same pole). Special cases of the Albers equal area projection are the cylindrical equal area projection (the standard latitudes equal and opposite), the Lambert azimuthal equal area projection (both standard latitude corresponds to the same pole), and the Lambert equal area conic proj [...]
 
@@ -67,6 +67,12 @@
 <p>specify the ellipsoid via <i>a</i> <i>f</i>; the equatorial radius is <i>a</i> and the flattening is <i>f</i>. Setting <i>f</i> = 0 results in a sphere. Specify <i>f</i> < 0 for a prolate ellipsoid. A simple fraction, e.g., 1/297, is allowed for <i>f</i>. (Also, if <i>f</i> > 1, the flattening is set to 1/<i>f</i>.) By default, the WGS84 ellipsoid is used, <i>a</i> = 6378137 m, <i>f</i> = 1/298.257223563.</p>
 
 </dd>
+<dt id="w"><b>-w</b></dt>
+<dd>
+
+<p>on input and output, longitude precedes latitude (except that, on input, this can be overridden by a hemisphere designator, <i>N</i>, <i>S</i>, <i>E</i>, <i>W</i>).</p>
+
+</dd>
 <dt id="p"><b>-p</b></dt>
 <dd>
 
diff --git a/man/ConicProj.pod b/man/ConicProj.pod
index 20f39cb..a6d54de 100644
--- a/man/ConicProj.pod
+++ b/man/ConicProj.pod
@@ -6,7 +6,7 @@ ConicProj -- perform conic projections
 
 B<ConicProj> ( B<-c> | B<-a> ) I<lat1> I<lat2>
 [ B<-l> I<lon0> ] [ B<-k> I<k1> ] [ B<-r> ]
-[ B<-e> I<a> I<f> ] [ B<-p> I<prec> ]
+[ B<-e> I<a> I<f> ] [ B<-w> ] [ B<-p> I<prec> ]
 [ B<--comment-delimiter> I<commentdelim> ]
 [ B<--version> | B<-h> | B<--help> ]
 [ B<--input-file> I<infile> | B<--input-string> I<instring> ]
@@ -28,12 +28,14 @@ area).  The (azimuthal) scale on the standard parallels is I<k1>.
 
 Geodetic coordinates are provided on standard input as a set of lines
 containing (blank separated) I<latitude> and I<longitude> (decimal
-degrees or degrees, minutes, seconds).  For each set of geodetic
-coordinates, the corresponding projected easting, I<x>, and northing,
-I<y>, (meters) are printed on standard output together with the meridian
-convergence I<gamma> (degrees) and (azimuthal) scale I<k>.  For Albers
-equal area, the radial scale is 1/I<k>.  The meridian convergence is the
-bearing of the I<y> axis measured clockwise from true north.
+degrees or degrees, minutes, seconds);  for details on the allowed
+formats for latitude and longitude, see the C<GEOGRAPHIC COORDINATES>
+section of GeoConvert(1).  For each set of geodetic coordinates, the
+corresponding projected easting, I<x>, and northing, I<y>, (meters) are
+printed on standard output together with the meridian convergence
+I<gamma> (degrees) and (azimuthal) scale I<k>.  For Albers equal area,
+the radial scale is 1/I<k>.  The meridian convergence is the bearing of
+the I<y> axis measured clockwise from true north.
 
 Special cases of the Lambert conformal projection are the Mercator
 projection (the standard latitudes equal and opposite) and the polar
@@ -82,6 +84,12 @@ is allowed for I<f>.  (Also, if I<f> E<gt> 1, the flattening is set to
 1/I<f>.)  By default, the WGS84 ellipsoid is used, I<a> = 6378137 m,
 I<f> = 1/298.257223563.
 
+=item B<-w>
+
+on input and output, longitude precedes latitude (except that, on input,
+this can be overridden by a hemisphere designator, I<N>, I<S>, I<E>,
+I<W>).
+
 =item B<-p>
 
 set the output precision to I<prec> (default 6).  I<prec> is the number
diff --git a/man/ConicProj.usage b/man/ConicProj.usage
index e8edee6..487ee22 100644
--- a/man/ConicProj.usage
+++ b/man/ConicProj.usage
@@ -2,14 +2,14 @@ int usage(int retval, bool brief) {
   if (brief)
     ( retval ? std::cerr : std::cout ) << "Usage:\n"
 "    ConicProj ( -c | -a ) lat1 lat2 [ -l lon0 ] [ -k k1 ] [ -r ] [ -e a f ]\n"
-"    [ -p prec ] [ --comment-delimiter commentdelim ] [ --version | -h |\n"
-"    --help ] [ --input-file infile | --input-string instring ] [\n"
+"    [ -w ] [ -p prec ] [ --comment-delimiter commentdelim ] [ --version |\n"
+"    -h | --help ] [ --input-file infile | --input-string instring ] [\n"
 "    --line-separator linesep ] [ --output-file outfile ]\n"
 "\n"
 "For full documentation type:\n"
 "    ConicProj --help\n"
 "or visit:\n"
-"    http://geographiclib.sf.net/1.43/ConicProj.1.html\n";
+"    http://geographiclib.sf.net/1.44/ConicProj.1.html\n";
   else
     ( retval ? std::cerr : std::cout ) << "Man page:\n"
 "NAME\n"
@@ -17,8 +17,8 @@ int usage(int retval, bool brief) {
 "\n"
 "SYNOPSIS\n"
 "       ConicProj ( -c | -a ) lat1 lat2 [ -l lon0 ] [ -k k1 ] [ -r ] [ -e a f ]\n"
-"       [ -p prec ] [ --comment-delimiter commentdelim ] [ --version | -h |\n"
-"       --help ] [ --input-file infile | --input-string instring ] [\n"
+"       [ -w ] [ -p prec ] [ --comment-delimiter commentdelim ] [ --version |\n"
+"       -h | --help ] [ --input-file infile | --input-string instring ] [\n"
 "       --line-separator linesep ] [ --output-file outfile ]\n"
 "\n"
 "DESCRIPTION\n"
@@ -35,12 +35,14 @@ int usage(int retval, bool brief) {
 "\n"
 "       Geodetic coordinates are provided on standard input as a set of lines\n"
 "       containing (blank separated) latitude and longitude (decimal degrees or\n"
-"       degrees, minutes, seconds).  For each set of geodetic coordinates, the\n"
-"       corresponding projected easting, x, and northing, y, (meters) are\n"
-"       printed on standard output together with the meridian convergence gamma\n"
-"       (degrees) and (azimuthal) scale k.  For Albers equal area, the radial\n"
-"       scale is 1/k.  The meridian convergence is the bearing of the y axis\n"
-"       measured clockwise from true north.\n"
+"       degrees, minutes, seconds);  for details on the allowed formats for\n"
+"       latitude and longitude, see the \"GEOGRAPHIC COORDINATES\" section of\n"
+"       GeoConvert(1).  For each set of geodetic coordinates, the corresponding\n"
+"       projected easting, x, and northing, y, (meters) are printed on standard\n"
+"       output together with the meridian convergence gamma (degrees) and\n"
+"       (azimuthal) scale k.  For Albers equal area, the radial scale is 1/k.\n"
+"       The meridian convergence is the bearing of the y axis measured\n"
+"       clockwise from true north.\n"
 "\n"
 "       Special cases of the Lambert conformal projection are the Mercator\n"
 "       projection (the standard latitudes equal and opposite) and the polar\n"
@@ -74,6 +76,10 @@ int usage(int retval, bool brief) {
 "           default, the WGS84 ellipsoid is used, a = 6378137 m, f =\n"
 "           1/298.257223563.\n"
 "\n"
+"       -w  on input and output, longitude precedes latitude (except that, on\n"
+"           input, this can be overridden by a hemisphere designator, N, S, E,\n"
+"           W).\n"
+"\n"
 "       -p  set the output precision to prec (default 6).  prec is the number\n"
 "           of digits after the decimal point for lengths (in meters).  For\n"
 "           latitudes and longitudes (in degrees), the number of digits after\n"
diff --git a/man/GeoConvert.1 b/man/GeoConvert.1
index abce2d8..367e678 100644
--- a/man/GeoConvert.1
+++ b/man/GeoConvert.1
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "GEOCONVERT 1"
-.TH GEOCONVERT 1 "2015-05-22" "GeographicLib 1.43" "GeographicLib Utilities"
+.TH GEOCONVERT 1 "2015-08-14" "GeographicLib 1.44" "GeographicLib Utilities"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
@@ -143,8 +143,8 @@ GeoConvert \-\- convert geographic coordinates
 .SH "SYNOPSIS"
 .IX Header "SYNOPSIS"
 \&\fBGeoConvert\fR [ \fB\-g\fR | \fB\-d\fR | \fB\-:\fR | \fB\-u\fR | \fB\-m\fR | \fB\-c\fR ]
-[ \fB\-p\fR \fIprec\fR ] [ \fB\-z\fR \fIzone\fR | \fB\-s\fR | \fB\-t\fR ] [ \fB\-n\fR ] [ \fB\-w\fR ]
-[ \fB\-l\fR | \fB\-a\fR ]
+[ \fB\-z\fR \fIzone\fR | \fB\-s\fR | \fB\-t\fR ] [ \fB\-n\fR ]
+[ \fB\-w\fR ] [ \fB\-p\fR \fIprec\fR ] [ \fB\-l\fR | \fB\-a\fR ]
 [ \fB\-\-comment\-delimiter\fR \fIcommentdelim\fR ]
 [ \fB\-\-version\fR | \fB\-h\fR | \fB\-\-help\fR ]
 [ \fB\-\-input\-file\fR \fIinfile\fR | \fB\-\-input\-string\fR \fIinstring\fR ]
@@ -162,32 +162,17 @@ is used (\fIa\fR = 6378137 m, \fIf\fR = 1/298.257223563).
 .IP "\fBgeographic\fR" 4
 .IX Item "geographic"
 2 tokens (output options \fB\-g\fR, \fB\-d\fR, or \fB\-:\fR) given as \fIlatitude\fR
-\&\fIlongitude\fR using decimal degrees or degrees minutes seconds.  d, ',
-and " are used to denote degrees, minutes, and seconds, with the least
-significant designator optional.  (See \*(L"\s-1QUOTING\*(R"\s0 for how to quote
-the characters ' and \*(L" when entering coordinates on the command line.)
-Various unicode characters (encoded with \s-1UTF\-8\s0) may also be used to
-denote degrees, minutes, and seconds, e.g., the degree, prime, and
-double prime symbols; in addition two single quotes can be used to
-represent \*(R".  Alternatively, : (colon) may be used to separate the
-various components.  Latitude is given first (unless the \fB\-w\fR option
-is given); however, on input, either may be given first by appending
-or prepending \fIN\fR or \fIS\fR to the latitude and \fIE\fR or \fIW\fR to the
-longitude.  For example, the following are all equivalent
+\&\fIlongitude\fR using decimal degrees or degrees, minutes, and seconds.
+Latitude is given first (unless the \fB\-w\fR option is given).  See
+\&\*(L"\s-1GEOGRAPHIC COORDINATES\*(R"\s0 for a description of the format.  For
+example, the following are all equivalent
 .Sp
 .Vb 5
 \&    33.3 44.4
 \&    E44.4 N33.3
 \&    33d18\*(AqN 44d24\*(AqE
 \&    44d24 33d18N
-\&    33:18 44:24
-.Ve
-.Sp
-It is also possible to carry out addition or subtraction operations in
-geographic coordinates.  For example the point 15" east of 39N 70W is
-.Sp
-.Vb 1
-\&    39N 70W+0:0:15E
+\&    33:18 +44:24
 .Ve
 .IP "\fB\s-1UTM/UPS\s0\fR" 4
 .IX Item "UTM/UPS"
@@ -234,10 +219,6 @@ output \s-1MGRS.\s0
 output meridian convergence and scale for the corresponding \s-1UTM\s0 or
 \&\s-1UPS\s0 projection.  Convergence is the bearing of grid north given as
 degrees clockwise from true north.
-.IP "\fB\-p\fR" 4
-.IX Item "-p"
-set the output precision to \fIprec\fR (default 0); \fIprec\fR is the
-precision relative to 1 m.  See \*(L"\s-1PRECISION\*(R"\s0.
 .IP "\fB\-z\fR" 4
 .IX Item "-z"
 set the zone to \fIzone\fR for output.  Use either 0 < \fIzone\fR <=
@@ -255,9 +236,13 @@ on input, \s-1MGRS\s0 coordinates refer to the south-west corner of the \s-1MGRS
 square instead of the center; see \*(L"\s-1MGRS\*(R"\s0.
 .IP "\fB\-w\fR" 4
 .IX Item "-w"
-on input and output, longitude precedes latitude (except that on input
+on input and output, longitude precedes latitude (except that, on input,
 this can be overridden by a hemisphere designator, \fIN\fR, \fIS\fR, \fIE\fR,
 \&\fIW\fR).
+.IP "\fB\-p\fR" 4
+.IX Item "-p"
+set the output precision to \fIprec\fR (default 0); \fIprec\fR is the
+precision relative to 1 m.  See \*(L"\s-1PRECISION\*(R"\s0.
 .IP "\fB\-l\fR" 4
 .IX Item "-l"
 on output, \s-1UTM/UPS\s0 uses the long forms \fInorth\fR and \fIsouth\fR to
@@ -314,61 +299,47 @@ component.  Print convergence, resp. scale, with 5 + \fIprec\fR, resp. 7 +
 \&\fIprec\fR, digits after the decimal point.  The minimum value of \fIprec\fR is
 \&\-5 and the maximum is 9 for \s-1UTM/UPS, 9\s0 for decimal degrees, 10 for \s-1DMS,
 6\s0 for \s-1MGRS,\s0 and 8 for convergence and scale.
-.SH "MGRS"
-.IX Header "MGRS"
-\&\s-1MGRS\s0 coordinates represent a square patch of the earth, thus \f(CW\*(C`38SMB4488\*(C'\fR
-is in zone \f(CW\*(C`38n\*(C'\fR with 444km <= \fIeasting\fR < 445km and 3688km <=
-\&\fInorthing\fR < 3689km.  Consistent with this representation,
-coordinates are \fItruncated\fR (instead of \fIrounded\fR) to the requested
-precision.  Similarly, on input an \s-1MGRS\s0 coordinate represents the
-\&\fIcenter\fR of the square (\f(CW\*(C`38n 444500 3688500\*(C'\fR in the example above).
-However, if the \fB\-n\fR option is given then the south-west corner of the
-square is returned instead (\f(CW\*(C`38n 444000 3688000\*(C'\fR in the example above).
-.SH "ZONE"
-.IX Header "ZONE"
-If the input is \fBgeographic\fR, \fBGeoConvert\fR uses the standard rules of
-selecting \s-1UTM\s0 vs \s-1UPS\s0 and for assigning the \s-1UTM\s0 zone (with the Norway and
-Svalbard exceptions).  If the input is \fB\s-1UTM/UPS\s0\fR or \fB\s-1MGRS\s0\fR, then the
-choice between \s-1UTM\s0 and \s-1UPS\s0 and the \s-1UTM\s0 zone mirrors the input.  The \fB\-z\fR
-\&\fIzone\fR, \fB\-s\fR, and \fB\-t\fR options allow these rules to be overridden
-with \fIzone\fR = 0 being used to indicate \s-1UPS. \s0 For example, the point
-.PP
-.Vb 1
-\&   79.9S 6.1E
-.Ve
-.PP
-corresponds to possible \s-1MGRS\s0 coordinates
-.PP
-.Vb 3
-\&   32CMS4324728161 (standard UTM zone = 32)
-\&   31CEM6066227959 (neighboring UTM zone = 31)
-\&     BBZ1945517770 (neighboring UPS zone)
-.Ve
+.SH "GEOGRAPHIC COORDINATES"
+.IX Header "GEOGRAPHIC COORDINATES"
+The utility accepts geographic coordinates, latitude and longitude, in a
+number of common formats.  Latitude precedes longitude, unless the \fB\-w\fR
+option is given which switches this convention.  On input, either
+coordinate may be given first by appending or prepending \fIN\fR or \fIS\fR to
+the latitude and \fIE\fR or \fIW\fR to the longitude.  These hemisphere
+designators carry an implied sign, positive for \fIN\fR and \fIE\fR and
+negative for \fIS\fR and \fIW\fR.  This sign multiplies any +/\- sign prefixing
+the coordinate.  The coordinates may be given as decimal degree or as
+degrees, minutes, and seconds.  d, ', and " are used to denote degrees,
+minutes, and seconds, with the least significant designator optional.
+(See \*(L"\s-1QUOTING\*(R"\s0 for how to quote the characters ' and " when entering
+coordinates on the command line.)  Alternatively, : (colon) may be used
+to separate the various components.  Only the final component of
+coordinate can include a decimal point, and the minutes and seconds
+components must be less than 60.
 .PP
-then
+It is also possible to carry out addition or subtraction operations in
+geographic coordinates.  If the coordinate includes interior signs
+(i.e., not at the beginning or immediately after an initial hemisphere
+designator), then the coordinate is split before such signs; the pieces
+are parsed separately and the results summed.  For example the point 15"
+east of 39N 70W is
 .PP
-.Vb 4
-\&   echo 79.9S 6.1E      | GeoConvert \-p \-3 \-m       => 32CMS4328
-\&   echo 31CEM6066227959 | GeoConvert \-p \-3 \-m       => 31CEM6027
-\&   echo 31CEM6066227959 | GeoConvert \-p \-3 \-m \-s    => 32CMS4328
-\&   echo 31CEM6066227959 | GeoConvert \-p \-3 \-m \-z 0  =>   BBZ1917
+.Vb 1
+\&    39N 70W+0:0:15E
 .Ve
 .PP
-Is \fIzone\fR is specified with a hemisphere, then this is honored when
-printing \s-1UTM\s0 coordinates:
+\&\fB\s-1WARNING:\s0\fR \*(L"Exponential\*(R" notation is not recognized for geographic
+coordinates; instead 7.0E+1 is parsed as (7.0E) + (+1), yielding the
+same result as 8.0E.
 .PP
-.Vb 4
-\&   echo \-1 3 | GeoConvert \-u         => 31s 500000 9889470
-\&   echo \-1 3 | GeoConvert \-u \-z 31   => 31s 500000 9889470
-\&   echo \-1 3 | GeoConvert \-u \-z 31s  => 31s 500000 9889470
-\&   echo \-1 3 | GeoConvert \-u \-z 31n  => 31n 500000 \-110530
-.Ve
+Various unicode characters (encoded with \s-1UTF\-8\s0) may also be used to
+denote degrees, minutes, and seconds, e.g., the degree, prime, and
+double prime symbols; in addition two single quotes can be used to
+represent ".
 .PP
-\&\fB\s-1NOTE\s0\fR: the letter in the zone specification for \s-1UTM\s0 is a hemisphere
-designator \fIn\fR or \fIs\fR and \fInot\fR an \s-1MGRS\s0 latitude band letter.
-Convert the \s-1MGRS\s0 latitude band letter to a hemisphere as follows:
-replace \fIC\fR thru \fIM\fR by \fIs\fR (or \fIsouth\fR); replace \fIN\fR thru \fIX\fR by
-\&\fIn\fR (or \fInorth\fR).
+The other GeographicLib utilities use the same rules for interpreting
+geographic coordinates; in addition, azimuths and arc lengths are
+interpreted the same way.
 .SH "QUOTING"
 .IX Header "QUOTING"
 Unfortunately the characters ' and \*(L" have special meanings in many
@@ -419,6 +390,61 @@ file \f(CW\*(C`input.txt\*(C'\fR should just contain the plain coordinates.
 .Vb 1
 \&  GeoConvert \-d \-p \-1 < input.txt
 .Ve
+.SH "MGRS"
+.IX Header "MGRS"
+\&\s-1MGRS\s0 coordinates represent a square patch of the earth, thus \f(CW\*(C`38SMB4488\*(C'\fR
+is in zone \f(CW\*(C`38n\*(C'\fR with 444km <= \fIeasting\fR < 445km and 3688km <=
+\&\fInorthing\fR < 3689km.  Consistent with this representation,
+coordinates are \fItruncated\fR (instead of \fIrounded\fR) to the requested
+precision.  Similarly, on input an \s-1MGRS\s0 coordinate represents the
+\&\fIcenter\fR of the square (\f(CW\*(C`38n 444500 3688500\*(C'\fR in the example above).
+However, if the \fB\-n\fR option is given then the south-west corner of the
+square is returned instead (\f(CW\*(C`38n 444000 3688000\*(C'\fR in the example above).
+.SH "ZONE"
+.IX Header "ZONE"
+If the input is \fBgeographic\fR, \fBGeoConvert\fR uses the standard rules of
+selecting \s-1UTM\s0 vs \s-1UPS\s0 and for assigning the \s-1UTM\s0 zone (with the Norway and
+Svalbard exceptions).  If the input is \fB\s-1UTM/UPS\s0\fR or \fB\s-1MGRS\s0\fR, then the
+choice between \s-1UTM\s0 and \s-1UPS\s0 and the \s-1UTM\s0 zone mirrors the input.  The \fB\-z\fR
+\&\fIzone\fR, \fB\-s\fR, and \fB\-t\fR options allow these rules to be overridden
+with \fIzone\fR = 0 being used to indicate \s-1UPS. \s0 For example, the point
+.PP
+.Vb 1
+\&   79.9S 6.1E
+.Ve
+.PP
+corresponds to possible \s-1MGRS\s0 coordinates
+.PP
+.Vb 3
+\&   32CMS4324728161 (standard UTM zone = 32)
+\&   31CEM6066227959 (neighboring UTM zone = 31)
+\&     BBZ1945517770 (neighboring UPS zone)
+.Ve
+.PP
+then
+.PP
+.Vb 4
+\&   echo 79.9S 6.1E      | GeoConvert \-p \-3 \-m       => 32CMS4328
+\&   echo 31CEM6066227959 | GeoConvert \-p \-3 \-m       => 31CEM6027
+\&   echo 31CEM6066227959 | GeoConvert \-p \-3 \-m \-s    => 32CMS4328
+\&   echo 31CEM6066227959 | GeoConvert \-p \-3 \-m \-z 0  =>   BBZ1917
+.Ve
+.PP
+Is \fIzone\fR is specified with a hemisphere, then this is honored when
+printing \s-1UTM\s0 coordinates:
+.PP
+.Vb 4
+\&   echo \-1 3 | GeoConvert \-u         => 31s 500000 9889470
+\&   echo \-1 3 | GeoConvert \-u \-z 31   => 31s 500000 9889470
+\&   echo \-1 3 | GeoConvert \-u \-z 31s  => 31s 500000 9889470
+\&   echo \-1 3 | GeoConvert \-u \-z 31n  => 31n 500000 \-110530
+.Ve
+.PP
+\&\fB\s-1NOTE\s0\fR: the letter in the zone specification for \s-1UTM\s0 is a hemisphere
+designator \fIn\fR or \fIs\fR and \fInot\fR an \s-1MGRS\s0 latitude band letter.
+Convert the \s-1MGRS\s0 latitude band letter to a hemisphere as follows:
+replace \fIC\fR thru \fIM\fR by \fIs\fR (or \fIsouth\fR); replace \fIN\fR thru \fIX\fR by
+\&\fIn\fR (or \fInorth\fR).
 .SH "EXAMPLES"
 .IX Header "EXAMPLES"
 .Vb 4
diff --git a/man/GeoConvert.1.html b/man/GeoConvert.1.html
index 236a780..7f3357a 100644
--- a/man/GeoConvert.1.html
+++ b/man/GeoConvert.1.html
@@ -17,7 +17,7 @@
 
 <h1 id="SYNOPSIS">SYNOPSIS</h1>
 
-<p><b>GeoConvert</b> [ <b>-g</b> | <b>-d</b> | <b>-:</b> | <b>-u</b> | <b>-m</b> | <b>-c</b> ] [ <b>-p</b> <i>prec</i> ] [ <b>-z</b> <i>zone</i> | <b>-s</b> | <b>-t</b> ] [ <b>-n</b> ] [ <b>-w</b> ] [ <b>-l</b> | <b>-a</b> ] [ <b>--comment-delimiter</b> <i>commentdelim</i> ] [ <b>--version</b> | <b>-h</b> | <b>--help</b> ] [ <b>--input-file</b> <i>infile</i> | <b>--input-string</b> <i>instring</i> ] [ <b>--line-separator</b> <i>linesep</i> ] [ <b>--output-file</b> <i>outfile</i> ]</p>
+<p><b>GeoConvert</b> [ <b>-g</b> | <b>-d</b> | <b>-:</b> | <b>-u</b> | <b>-m</b> | <b>-c</b> ] [ <b>-z</b> <i>zone</i> | <b>-s</b> | <b>-t</b> ] [ <b>-n</b> ] [ <b>-w</b> ] [ <b>-p</b> <i>prec</i> ] [ <b>-l</b> | <b>-a</b> ] [ <b>--comment-delimiter</b> <i>commentdelim</i> ] [ <b>--version</b> | <b>-h</b> | <b>--help</b> ] [ <b>--input-file</b> <i>infile</i> | <b>--input-string</b> <i>instring</i> ] [ <b>--line-separator</b> <i>linesep</i> ] [ <b>--output-file</b> <i>outfile</i> ]</p>
 
 <h1 id="DESCRIPTION">DESCRIPTION</h1>
 
@@ -28,17 +28,13 @@
 <dt id="geographic"><b>geographic</b></dt>
 <dd>
 
-<p>2 tokens (output options <b>-g</b>, <b>-d</b>, or <b>-:</b>) given as <i>latitude</i> <i>longitude</i> using decimal degrees or degrees minutes seconds. d, ', and " are used to denote degrees, minutes, and seconds, with the least significant designator optional. (See <a href="#QUOTING">"QUOTING"</a> for how to quote the characters ' and " when entering coordinates on the command line.) Various unicode characters (encoded with UTF-8) may also be used to deno [...]
+<p>2 tokens (output options <b>-g</b>, <b>-d</b>, or <b>-:</b>) given as <i>latitude</i> <i>longitude</i> using decimal degrees or degrees, minutes, and seconds. Latitude is given first (unless the <b>-w</b> option is given). See <a href="#GEOGRAPHIC-COORDINATES">"GEOGRAPHIC COORDINATES"</a> for a description of the format. For example, the following are all equivalent</p>
 
 <pre><code>    33.3 44.4
     E44.4 N33.3
     33d18'N 44d24'E
     44d24 33d18N
-    33:18 44:24</code></pre>
-
-<p>It is also possible to carry out addition or subtraction operations in geographic coordinates. For example the point 15" east of 39N 70W is</p>
-
-<pre><code>    39N 70W+0:0:15E</code></pre>
+    33:18 +44:24</code></pre>
 
 </dd>
 <dt id="UTM-UPS"><b>UTM/UPS</b></dt>
@@ -103,12 +99,6 @@
 <p>output meridian convergence and scale for the corresponding UTM or UPS projection. Convergence is the bearing of grid north given as degrees clockwise from true north.</p>
 
 </dd>
-<dt id="p"><b>-p</b></dt>
-<dd>
-
-<p>set the output precision to <i>prec</i> (default 0); <i>prec</i> is the precision relative to 1 m. See <a href="#PRECISION">"PRECISION"</a>.</p>
-
-</dd>
 <dt id="z"><b>-z</b></dt>
 <dd>
 
@@ -136,7 +126,13 @@
 <dt id="w"><b>-w</b></dt>
 <dd>
 
-<p>on input and output, longitude precedes latitude (except that on input this can be overridden by a hemisphere designator, <i>N</i>, <i>S</i>, <i>E</i>, <i>W</i>).</p>
+<p>on input and output, longitude precedes latitude (except that, on input, this can be overridden by a hemisphere designator, <i>N</i>, <i>S</i>, <i>E</i>, <i>W</i>).</p>
+
+</dd>
+<dt id="p"><b>-p</b></dt>
+<dd>
+
+<p>set the output precision to <i>prec</i> (default 0); <i>prec</i> is the precision relative to 1 m. See <a href="#PRECISION">"PRECISION"</a>.</p>
 
 </dd>
 <dt id="l"><b>-l</b></dt>
@@ -205,37 +201,19 @@
 
 <p><i>prec</i> gives precision of the output with <i>prec</i> = 0 giving 1 m precision, <i>prec</i> = 3 giving 1 mm precision, etc. <i>prec</i> is the number of digits after the decimal point for UTM/UPS. The number of digits per coordinate for MGRS is 5 + <i>prec</i>. For decimal degrees, the number of digits after the decimal point is 5 + <i>prec</i>. For DMS (degree, minute, seconds) output, the number of digits after the decimal point in the seconds components is 1 + <i>prec</i>; if  [...]
 
-<h1 id="MGRS">MGRS</h1>
+<h1 id="GEOGRAPHIC-COORDINATES">GEOGRAPHIC COORDINATES</h1>
 
-<p>MGRS coordinates represent a square patch of the earth, thus <code>38SMB4488</code> is in zone <code>38n</code> with 444km <= <i>easting</i> < 445km and 3688km <= <i>northing</i> < 3689km. Consistent with this representation, coordinates are <i>truncated</i> (instead of <i>rounded</i>) to the requested precision. Similarly, on input an MGRS coordinate represents the <i>center</i> of the square (<code>38n 444500 3688500</code> in the example above). However, if the <b>-n</b [...]
+<p>The utility accepts geographic coordinates, latitude and longitude, in a number of common formats. Latitude precedes longitude, unless the <b>-w</b> option is given which switches this convention. On input, either coordinate may be given first by appending or prepending <i>N</i> or <i>S</i> to the latitude and <i>E</i> or <i>W</i> to the longitude. These hemisphere designators carry an implied sign, positive for <i>N</i> and <i>E</i> and negative for <i>S</i> and <i>W</i>. This sign m [...]
 
-<h1 id="ZONE">ZONE</h1>
+<p>It is also possible to carry out addition or subtraction operations in geographic coordinates. If the coordinate includes interior signs (i.e., not at the beginning or immediately after an initial hemisphere designator), then the coordinate is split before such signs; the pieces are parsed separately and the results summed. For example the point 15" east of 39N 70W is</p>
 
-<p>If the input is <b>geographic</b>, <b>GeoConvert</b> uses the standard rules of selecting UTM vs UPS and for assigning the UTM zone (with the Norway and Svalbard exceptions). If the input is <b>UTM/UPS</b> or <b>MGRS</b>, then the choice between UTM and UPS and the UTM zone mirrors the input. The <b>-z</b> <i>zone</i>, <b>-s</b>, and <b>-t</b> options allow these rules to be overridden with <i>zone</i> = 0 being used to indicate UPS. For example, the point</p>
-
-<pre><code>   79.9S 6.1E</code></pre>
-
-<p>corresponds to possible MGRS coordinates</p>
-
-<pre><code>   32CMS4324728161 (standard UTM zone = 32)
-   31CEM6066227959 (neighboring UTM zone = 31)
-     BBZ1945517770 (neighboring UPS zone)</code></pre>
+<pre><code>    39N 70W+0:0:15E</code></pre>
 
-<p>then</p>
+<p><b>WARNING:</b> "Exponential" notation is not recognized for geographic coordinates; instead 7.0E+1 is parsed as (7.0E) + (+1), yielding the same result as 8.0E.</p>
 
-<pre><code>   echo 79.9S 6.1E      | GeoConvert -p -3 -m       => 32CMS4328
-   echo 31CEM6066227959 | GeoConvert -p -3 -m       => 31CEM6027
-   echo 31CEM6066227959 | GeoConvert -p -3 -m -s    => 32CMS4328
-   echo 31CEM6066227959 | GeoConvert -p -3 -m -z 0  =>   BBZ1917</code></pre>
+<p>Various unicode characters (encoded with UTF-8) may also be used to denote degrees, minutes, and seconds, e.g., the degree, prime, and double prime symbols; in addition two single quotes can be used to represent ".</p>
 
-<p>Is <i>zone</i> is specified with a hemisphere, then this is honored when printing UTM coordinates:</p>
-
-<pre><code>   echo -1 3 | GeoConvert -u         => 31s 500000 9889470
-   echo -1 3 | GeoConvert -u -z 31   => 31s 500000 9889470
-   echo -1 3 | GeoConvert -u -z 31s  => 31s 500000 9889470
-   echo -1 3 | GeoConvert -u -z 31n  => 31n 500000 -110530</code></pre>
-
-<p><b>NOTE</b>: the letter in the zone specification for UTM is a hemisphere designator <i>n</i> or <i>s</i> and <i>not</i> an MGRS latitude band letter. Convert the MGRS latitude band letter to a hemisphere as follows: replace <i>C</i> thru <i>M</i> by <i>s</i> (or <i>south</i>); replace <i>N</i> thru <i>X</i> by <i>n</i> (or <i>north</i>).</p>
+<p>The other GeographicLib utilities use the same rules for interpreting geographic coordinates; in addition, azimuths and arc lengths are interpreted the same way.</p>
 
 <h1 id="QUOTING">QUOTING</h1>
 
@@ -281,6 +259,38 @@
 </dd>
 </dl>
 
+<h1 id="MGRS">MGRS</h1>
+
+<p>MGRS coordinates represent a square patch of the earth, thus <code>38SMB4488</code> is in zone <code>38n</code> with 444km <= <i>easting</i> < 445km and 3688km <= <i>northing</i> < 3689km. Consistent with this representation, coordinates are <i>truncated</i> (instead of <i>rounded</i>) to the requested precision. Similarly, on input an MGRS coordinate represents the <i>center</i> of the square (<code>38n 444500 3688500</code> in the example above). However, if the <b>-n</b [...]
+
+<h1 id="ZONE">ZONE</h1>
+
+<p>If the input is <b>geographic</b>, <b>GeoConvert</b> uses the standard rules of selecting UTM vs UPS and for assigning the UTM zone (with the Norway and Svalbard exceptions). If the input is <b>UTM/UPS</b> or <b>MGRS</b>, then the choice between UTM and UPS and the UTM zone mirrors the input. The <b>-z</b> <i>zone</i>, <b>-s</b>, and <b>-t</b> options allow these rules to be overridden with <i>zone</i> = 0 being used to indicate UPS. For example, the point</p>
+
+<pre><code>   79.9S 6.1E</code></pre>
+
+<p>corresponds to possible MGRS coordinates</p>
+
+<pre><code>   32CMS4324728161 (standard UTM zone = 32)
+   31CEM6066227959 (neighboring UTM zone = 31)
+     BBZ1945517770 (neighboring UPS zone)</code></pre>
+
+<p>then</p>
+
+<pre><code>   echo 79.9S 6.1E      | GeoConvert -p -3 -m       => 32CMS4328
+   echo 31CEM6066227959 | GeoConvert -p -3 -m       => 31CEM6027
+   echo 31CEM6066227959 | GeoConvert -p -3 -m -s    => 32CMS4328
+   echo 31CEM6066227959 | GeoConvert -p -3 -m -z 0  =>   BBZ1917</code></pre>
+
+<p>Is <i>zone</i> is specified with a hemisphere, then this is honored when printing UTM coordinates:</p>
+
+<pre><code>   echo -1 3 | GeoConvert -u         => 31s 500000 9889470
+   echo -1 3 | GeoConvert -u -z 31   => 31s 500000 9889470
+   echo -1 3 | GeoConvert -u -z 31s  => 31s 500000 9889470
+   echo -1 3 | GeoConvert -u -z 31n  => 31n 500000 -110530</code></pre>
+
+<p><b>NOTE</b>: the letter in the zone specification for UTM is a hemisphere designator <i>n</i> or <i>s</i> and <i>not</i> an MGRS latitude band letter. Convert the MGRS latitude band letter to a hemisphere as follows: replace <i>C</i> thru <i>M</i> by <i>s</i> (or <i>south</i>); replace <i>N</i> thru <i>X</i> by <i>n</i> (or <i>north</i>).</p>
+
 <h1 id="EXAMPLES">EXAMPLES</h1>
 
 <pre><code>   echo 38SMB4488 | GeoConvert         => 33.33424 44.40363
diff --git a/man/GeoConvert.pod b/man/GeoConvert.pod
index 5ab3004..e49d001 100644
--- a/man/GeoConvert.pod
+++ b/man/GeoConvert.pod
@@ -5,8 +5,8 @@ GeoConvert -- convert geographic coordinates
 =head1 SYNOPSIS
 
 B<GeoConvert> [ B<-g> | B<-d> | B<-:> | B<-u> | B<-m> | B<-c> ]
-[ B<-p> I<prec> ] [ B<-z> I<zone> | B<-s> | B<-t> ] [ B<-n> ] [ B<-w> ]
-[ B<-l> | B<-a> ]
+[ B<-z> I<zone> | B<-s> | B<-t> ] [ B<-n> ]
+[ B<-w> ] [ B<-p> I<prec> ] [ B<-l> | B<-a> ]
 [ B<--comment-delimiter> I<commentdelim> ]
 [ B<--version> | B<-h> | B<--help> ]
 [ B<--input-file> I<infile> | B<--input-string> I<instring> ]
@@ -28,29 +28,16 @@ is used (I<a> = 6378137 m, I<f> = 1/298.257223563).
 =item B<geographic>
 
 2 tokens (output options B<-g>, B<-d>, or B<-:>) given as I<latitude>
-I<longitude> using decimal degrees or degrees minutes seconds.  d, ',
-and " are used to denote degrees, minutes, and seconds, with the least
-significant designator optional.  (See L</QUOTING> for how to quote
-the characters ' and " when entering coordinates on the command line.)
-Various unicode characters (encoded with UTF-8) may also be used to
-denote degrees, minutes, and seconds, e.g., the degree, prime, and
-double prime symbols; in addition two single quotes can be used to
-represent ".  Alternatively, : (colon) may be used to separate the
-various components.  Latitude is given first (unless the B<-w> option
-is given); however, on input, either may be given first by appending
-or prepending I<N> or I<S> to the latitude and I<E> or I<W> to the
-longitude.  For example, the following are all equivalent
+I<longitude> using decimal degrees or degrees, minutes, and seconds.
+Latitude is given first (unless the B<-w> option is given).  See
+L</GEOGRAPHIC COORDINATES> for a description of the format.  For
+example, the following are all equivalent
 
     33.3 44.4
     E44.4 N33.3
     33d18'N 44d24'E
     44d24 33d18N
-    33:18 44:24
-
-It is also possible to carry out addition or subtraction operations in
-geographic coordinates.  For example the point 15" east of 39N 70W is
-
-    39N 70W+0:0:15E
+    33:18 +44:24
 
 =item B<UTM/UPS>
 
@@ -105,11 +92,6 @@ output meridian convergence and scale for the corresponding UTM or
 UPS projection.  Convergence is the bearing of grid north given as
 degrees clockwise from true north.
 
-=item B<-p>
-
-set the output precision to I<prec> (default 0); I<prec> is the
-precision relative to 1 m.  See L</PRECISION>.
-
 =item B<-z>
 
 set the zone to I<zone> for output.  Use either 0 E<lt> I<zone> E<lt>=
@@ -131,10 +113,15 @@ square instead of the center; see L</MGRS>.
 
 =item B<-w>
 
-on input and output, longitude precedes latitude (except that on input
+on input and output, longitude precedes latitude (except that, on input,
 this can be overridden by a hemisphere designator, I<N>, I<S>, I<E>,
 I<W>).
 
+=item B<-p>
+
+set the output precision to I<prec> (default 0); I<prec> is the
+precision relative to 1 m.  See L</PRECISION>.
+
 =item B<-l>
 
 on output, UTM/UPS uses the long forms I<north> and I<south> to
@@ -204,54 +191,45 @@ I<prec>, digits after the decimal point.  The minimum value of I<prec> is
 -5 and the maximum is 9 for UTM/UPS, 9 for decimal degrees, 10 for DMS,
 6 for MGRS, and 8 for convergence and scale.
 
-=head1 MGRS
-
-MGRS coordinates represent a square patch of the earth, thus C<38SMB4488>
-is in zone C<38n> with 444km E<lt>= I<easting> E<lt> 445km and 3688km E<lt>=
-I<northing> E<lt> 3689km.  Consistent with this representation,
-coordinates are I<truncated> (instead of I<rounded>) to the requested
-precision.  Similarly, on input an MGRS coordinate represents the
-I<center> of the square (C<38n 444500 3688500> in the example above).
-However, if the B<-n> option is given then the south-west corner of the
-square is returned instead (C<38n 444000 3688000> in the example above).
-
-=head1 ZONE
+=head1 GEOGRAPHIC COORDINATES
+
+The utility accepts geographic coordinates, latitude and longitude, in a
+number of common formats.  Latitude precedes longitude, unless the B<-w>
+option is given which switches this convention.  On input, either
+coordinate may be given first by appending or prepending I<N> or I<S> to
+the latitude and I<E> or I<W> to the longitude.  These hemisphere
+designators carry an implied sign, positive for I<N> and I<E> and
+negative for I<S> and I<W>.  This sign multiplies any +/- sign prefixing
+the coordinate.  The coordinates may be given as decimal degree or as
+degrees, minutes, and seconds.  d, ', and " are used to denote degrees,
+minutes, and seconds, with the least significant designator optional.
+(See L</QUOTING> for how to quote the characters ' and " when entering
+coordinates on the command line.)  Alternatively, : (colon) may be used
+to separate the various components.  Only the final component of
+coordinate can include a decimal point, and the minutes and seconds
+components must be less than 60.
 
-If the input is B<geographic>, B<GeoConvert> uses the standard rules of
-selecting UTM vs UPS and for assigning the UTM zone (with the Norway and
-Svalbard exceptions).  If the input is B<UTM/UPS> or B<MGRS>, then the
-choice between UTM and UPS and the UTM zone mirrors the input.  The B<-z>
-I<zone>, B<-s>, and B<-t> options allow these rules to be overridden
-with I<zone> = 0 being used to indicate UPS.  For example, the point
-
-   79.9S 6.1E
-
-corresponds to possible MGRS coordinates
-
-   32CMS4324728161 (standard UTM zone = 32)
-   31CEM6066227959 (neighboring UTM zone = 31)
-     BBZ1945517770 (neighboring UPS zone)
-
-then
+It is also possible to carry out addition or subtraction operations in
+geographic coordinates.  If the coordinate includes interior signs
+(i.e., not at the beginning or immediately after an initial hemisphere
+designator), then the coordinate is split before such signs; the pieces
+are parsed separately and the results summed.  For example the point 15"
+east of 39N 70W is
 
-   echo 79.9S 6.1E      | GeoConvert -p -3 -m       => 32CMS4328
-   echo 31CEM6066227959 | GeoConvert -p -3 -m       => 31CEM6027
-   echo 31CEM6066227959 | GeoConvert -p -3 -m -s    => 32CMS4328
-   echo 31CEM6066227959 | GeoConvert -p -3 -m -z 0  =>   BBZ1917
+    39N 70W+0:0:15E
 
-Is I<zone> is specified with a hemisphere, then this is honored when
-printing UTM coordinates:
+B<WARNING:> "Exponential" notation is not recognized for geographic
+coordinates; instead 7.0E+1 is parsed as (7.0E) + (+1), yielding the
+same result as 8.0E.
 
-   echo -1 3 | GeoConvert -u         => 31s 500000 9889470
-   echo -1 3 | GeoConvert -u -z 31   => 31s 500000 9889470
-   echo -1 3 | GeoConvert -u -z 31s  => 31s 500000 9889470
-   echo -1 3 | GeoConvert -u -z 31n  => 31n 500000 -110530
+Various unicode characters (encoded with UTF-8) may also be used to
+denote degrees, minutes, and seconds, e.g., the degree, prime, and
+double prime symbols; in addition two single quotes can be used to
+represent ".
 
-B<NOTE>: the letter in the zone specification for UTM is a hemisphere
-designator I<n> or I<s> and I<not> an MGRS latitude band letter.
-Convert the MGRS latitude band letter to a hemisphere as follows:
-replace I<C> thru I<M> by I<s> (or I<south>); replace I<N> thru I<X> by
-I<n> (or I<north>).
+The other GeographicLib utilities use the same rules for interpreting
+geographic coordinates; in addition, azimuths and arc lengths are
+interpreted the same way.
 
 =head1 QUOTING
 
@@ -301,6 +279,55 @@ file C<input.txt> should just contain the plain coordinates.
 
 =back
 
+=head1 MGRS
+
+MGRS coordinates represent a square patch of the earth, thus C<38SMB4488>
+is in zone C<38n> with 444km E<lt>= I<easting> E<lt> 445km and 3688km E<lt>=
+I<northing> E<lt> 3689km.  Consistent with this representation,
+coordinates are I<truncated> (instead of I<rounded>) to the requested
+precision.  Similarly, on input an MGRS coordinate represents the
+I<center> of the square (C<38n 444500 3688500> in the example above).
+However, if the B<-n> option is given then the south-west corner of the
+square is returned instead (C<38n 444000 3688000> in the example above).
+
+=head1 ZONE
+
+If the input is B<geographic>, B<GeoConvert> uses the standard rules of
+selecting UTM vs UPS and for assigning the UTM zone (with the Norway and
+Svalbard exceptions).  If the input is B<UTM/UPS> or B<MGRS>, then the
+choice between UTM and UPS and the UTM zone mirrors the input.  The B<-z>
+I<zone>, B<-s>, and B<-t> options allow these rules to be overridden
+with I<zone> = 0 being used to indicate UPS.  For example, the point
+
+   79.9S 6.1E
+
+corresponds to possible MGRS coordinates
+
+   32CMS4324728161 (standard UTM zone = 32)
+   31CEM6066227959 (neighboring UTM zone = 31)
+     BBZ1945517770 (neighboring UPS zone)
+
+then
+
+   echo 79.9S 6.1E      | GeoConvert -p -3 -m       => 32CMS4328
+   echo 31CEM6066227959 | GeoConvert -p -3 -m       => 31CEM6027
+   echo 31CEM6066227959 | GeoConvert -p -3 -m -s    => 32CMS4328
+   echo 31CEM6066227959 | GeoConvert -p -3 -m -z 0  =>   BBZ1917
+
+Is I<zone> is specified with a hemisphere, then this is honored when
+printing UTM coordinates:
+
+   echo -1 3 | GeoConvert -u         => 31s 500000 9889470
+   echo -1 3 | GeoConvert -u -z 31   => 31s 500000 9889470
+   echo -1 3 | GeoConvert -u -z 31s  => 31s 500000 9889470
+   echo -1 3 | GeoConvert -u -z 31n  => 31n 500000 -110530
+
+B<NOTE>: the letter in the zone specification for UTM is a hemisphere
+designator I<n> or I<s> and I<not> an MGRS latitude band letter.
+Convert the MGRS latitude band letter to a hemisphere as follows:
+replace I<C> thru I<M> by I<s> (or I<south>); replace I<N> thru I<X> by
+I<n> (or I<north>).
+
 =head1 EXAMPLES
 
    echo 38SMB4488 | GeoConvert         => 33.33424 44.40363
diff --git a/man/GeoConvert.usage b/man/GeoConvert.usage
index c317e79..67c8b6f 100644
--- a/man/GeoConvert.usage
+++ b/man/GeoConvert.usage
@@ -1,23 +1,23 @@
 int usage(int retval, bool brief) {
   if (brief)
     ( retval ? std::cerr : std::cout ) << "Usage:\n"
-"    GeoConvert [ -g | -d | -: | -u | -m | -c ] [ -p prec ] [ -z zone | -s |\n"
-"    -t ] [ -n ] [ -w ] [ -l | -a ] [ --comment-delimiter commentdelim ] [\n"
+"    GeoConvert [ -g | -d | -: | -u | -m | -c ] [ -z zone | -s | -t ] [ -n ]\n"
+"    [ -w ] [ -p prec ] [ -l | -a ] [ --comment-delimiter commentdelim ] [\n"
 "    --version | -h | --help ] [ --input-file infile | --input-string\n"
 "    instring ] [ --line-separator linesep ] [ --output-file outfile ]\n"
 "\n"
 "For full documentation type:\n"
 "    GeoConvert --help\n"
 "or visit:\n"
-"    http://geographiclib.sf.net/1.43/GeoConvert.1.html\n";
+"    http://geographiclib.sf.net/1.44/GeoConvert.1.html\n";
   else
     ( retval ? std::cerr : std::cout ) << "Man page:\n"
 "NAME\n"
 "       GeoConvert -- convert geographic coordinates\n"
 "\n"
 "SYNOPSIS\n"
-"       GeoConvert [ -g | -d | -: | -u | -m | -c ] [ -p prec ] [ -z zone | -s |\n"
-"       -t ] [ -n ] [ -w ] [ -l | -a ] [ --comment-delimiter commentdelim ] [\n"
+"       GeoConvert [ -g | -d | -: | -u | -m | -c ] [ -z zone | -s | -t ] [ -n ]\n"
+"       [ -w ] [ -p prec ] [ -l | -a ] [ --comment-delimiter commentdelim ] [\n"
 "       --version | -h | --help ] [ --input-file infile | --input-string\n"
 "       instring ] [ --line-separator linesep ] [ --output-file outfile ]\n"
 "\n"
@@ -32,30 +32,16 @@ int usage(int retval, bool brief) {
 "\n"
 "       geographic\n"
 "           2 tokens (output options -g, -d, or -:) given as latitude longitude\n"
-"           using decimal degrees or degrees minutes seconds.  d, ', and \" are\n"
-"           used to denote degrees, minutes, and seconds, with the least\n"
-"           significant designator optional.  (See \"QUOTING\" for how to quote\n"
-"           the characters ' and \" when entering coordinates on the command\n"
-"           line.)  Various unicode characters (encoded with UTF-8) may also be\n"
-"           used to denote degrees, minutes, and seconds, e.g., the degree,\n"
-"           prime, and double prime symbols; in addition two single quotes can\n"
-"           be used to represent \".  Alternatively, : (colon) may be used to\n"
-"           separate the various components.  Latitude is given first (unless\n"
-"           the -w option is given); however, on input, either may be given\n"
-"           first by appending or prepending N or S to the latitude and E or W\n"
-"           to the longitude.  For example, the following are all equivalent\n"
+"           using decimal degrees or degrees, minutes, and seconds.  Latitude\n"
+"           is given first (unless the -w option is given).  See \"GEOGRAPHIC\n"
+"           COORDINATES\" for a description of the format.  For example, the\n"
+"           following are all equivalent\n"
 "\n"
 "               33.3 44.4\n"
 "               E44.4 N33.3\n"
 "               33d18'N 44d24'E\n"
 "               44d24 33d18N\n"
-"               33:18 44:24\n"
-"\n"
-"           It is also possible to carry out addition or subtraction operations\n"
-"           in geographic coordinates.  For example the point 15\" east of 39N\n"
-"           70W is\n"
-"\n"
-"               39N 70W+0:0:15E\n"
+"               33:18 +44:24\n"
 "\n"
 "       UTM/UPS\n"
 "           3 tokens (output option -u) given as zone+hemisphere easting\n"
@@ -93,9 +79,6 @@ int usage(int retval, bool brief) {
 "           UPS projection.  Convergence is the bearing of grid north given as\n"
 "           degrees clockwise from true north.\n"
 "\n"
-"       -p  set the output precision to prec (default 0); prec is the precision\n"
-"           relative to 1 m.  See \"PRECISION\".\n"
-"\n"
 "       -z  set the zone to zone for output.  Use either 0 < zone <= 60 for a\n"
 "           UTM zone or zone = 0 for UPS.  Alternatively use a zone+hemisphere\n"
 "           designation, e.g., 38n.  See \"ZONE\".\n"
@@ -107,10 +90,13 @@ int usage(int retval, bool brief) {
 "       -n  on input, MGRS coordinates refer to the south-west corner of the\n"
 "           MGRS square instead of the center; see \"MGRS\".\n"
 "\n"
-"       -w  on input and output, longitude precedes latitude (except that on\n"
-"           input this can be overridden by a hemisphere designator, N, S, E,\n"
+"       -w  on input and output, longitude precedes latitude (except that, on\n"
+"           input, this can be overridden by a hemisphere designator, N, S, E,\n"
 "           W).\n"
 "\n"
+"       -p  set the output precision to prec (default 0); prec is the precision\n"
+"           relative to 1 m.  See \"PRECISION\".\n"
+"\n"
 "       -l  on output, UTM/UPS uses the long forms north and south to designate\n"
 "           the hemisphere instead of n or s.\n"
 "\n"
@@ -165,6 +151,85 @@ int usage(int retval, bool brief) {
 "       and the maximum is 9 for UTM/UPS, 9 for decimal degrees, 10 for DMS, 6\n"
 "       for MGRS, and 8 for convergence and scale.\n"
 "\n"
+"GEOGRAPHIC COORDINATES\n"
+"       The utility accepts geographic coordinates, latitude and longitude, in\n"
+"       a number of common formats.  Latitude precedes longitude, unless the -w\n"
+"       option is given which switches this convention.  On input, either\n"
+"       coordinate may be given first by appending or prepending N or S to the\n"
+"       latitude and E or W to the longitude.  These hemisphere designators\n"
+"       carry an implied sign, positive for N and E and negative for S and W.\n"
+"       This sign multiplies any +/- sign prefixing the coordinate.  The\n"
+"       coordinates may be given as decimal degree or as degrees, minutes, and\n"
+"       seconds.  d, ', and \" are used to denote degrees, minutes, and seconds,\n"
+"       with the least significant designator optional.  (See \"QUOTING\" for how\n"
+"       to quote the characters ' and \" when entering coordinates on the\n"
+"       command line.)  Alternatively, : (colon) may be used to separate the\n"
+"       various components.  Only the final component of coordinate can include\n"
+"       a decimal point, and the minutes and seconds components must be less\n"
+"       than 60.\n"
+"\n"
+"       It is also possible to carry out addition or subtraction operations in\n"
+"       geographic coordinates.  If the coordinate includes interior signs\n"
+"       (i.e., not at the beginning or immediately after an initial hemisphere\n"
+"       designator), then the coordinate is split before such signs; the pieces\n"
+"       are parsed separately and the results summed.  For example the point\n"
+"       15\" east of 39N 70W is\n"
+"\n"
+"           39N 70W+0:0:15E\n"
+"\n"
+"       WARNING: \"Exponential\" notation is not recognized for geographic\n"
+"       coordinates; instead 7.0E+1 is parsed as (7.0E) + (+1), yielding the\n"
+"       same result as 8.0E.\n"
+"\n"
+"       Various unicode characters (encoded with UTF-8) may also be used to\n"
+"       denote degrees, minutes, and seconds, e.g., the degree, prime, and\n"
+"       double prime symbols; in addition two single quotes can be used to\n"
+"       represent \".\n"
+"\n"
+"       The other GeographicLib utilities use the same rules for interpreting\n"
+"       geographic coordinates; in addition, azimuths and arc lengths are\n"
+"       interpreted the same way.\n"
+"\n"
+"QUOTING\n"
+"       Unfortunately the characters ' and \" have special meanings in many\n"
+"       shells and have to be entered with care.  However note (1) that the\n"
+"       trailing designator is optional and that (2) you can use colons as a\n"
+"       separator character.  Thus 10d20' can be entered as 10d20 or 10:20 and\n"
+"       10d20'30\" can be entered as 10:20:30.\n"
+"\n"
+"       Unix shells (sh, bash, tsch)\n"
+"           The characters ' and \" can be quoted by preceding them with a \\\n"
+"           (backslash); or you can quote a string containing ' with a pair of\n"
+"           \"s.  The two alternatives are illustrated by\n"
+"\n"
+"              echo 10d20\\'30\\\" \"20d30'40\" | GeoConvert -d -p -1\n"
+"              => 10d20'30\"N 020d30'40\"E\n"
+"\n"
+"           Quoting of command line arguments is similar\n"
+"\n"
+"              GeoConvert -d -p -1 --input-string \"10d20'30\\\" 20d30'40\"\n"
+"              => 10d20'30\"N 020d30'40\"E\n"
+"\n"
+"       Windows command shell (cmd)\n"
+"           The ' character needs no quoting; the \" character can either be\n"
+"           quoted by a ^ or can be represented by typing ' twice.  (This\n"
+"           quoting is usually unnecessary because the trailing designator can\n"
+"           be omitted.)  Thus\n"
+"\n"
+"              echo 10d20'30'' 20d30'40 | GeoConvert -d -p -1\n"
+"              => 10d20'30\"N 020d30'40\"E\n"
+"\n"
+"           Use \\ to quote the \" character in a command line argument\n"
+"\n"
+"              GeoConvert -d -p -1 --input-string \"10d20'30\\\" 20d30'40\"\n"
+"              => 10d20'30\"N 020d30'40\"E\n"
+"\n"
+"       Input from a file\n"
+"           No quoting need be done if the input from a file.  Thus each line\n"
+"           of the file \"input.txt\" should just contain the plain coordinates.\n"
+"\n"
+"             GeoConvert -d -p -1 < input.txt\n"
+"\n"
 "MGRS\n"
 "       MGRS coordinates represent a square patch of the earth, thus\n"
 "       \"38SMB4488\" is in zone \"38n\" with 444km <= easting < 445km and 3688km\n"
@@ -211,46 +276,6 @@ int usage(int retval, bool brief) {
 "       MGRS latitude band letter to a hemisphere as follows: replace C thru M\n"
 "       by s (or south); replace N thru X by n (or north).\n"
 "\n"
-"QUOTING\n"
-"       Unfortunately the characters ' and \" have special meanings in many\n"
-"       shells and have to be entered with care.  However note (1) that the\n"
-"       trailing designator is optional and that (2) you can use colons as a\n"
-"       separator character.  Thus 10d20' can be entered as 10d20 or 10:20 and\n"
-"       10d20'30\" can be entered as 10:20:30.\n"
-"\n"
-"       Unix shells (sh, bash, tsch)\n"
-"           The characters ' and \" can be quoted by preceding them with a \\\n"
-"           (backslash); or you can quote a string containing ' with a pair of\n"
-"           \"s.  The two alternatives are illustrated by\n"
-"\n"
-"              echo 10d20\\'30\\\" \"20d30'40\" | GeoConvert -d -p -1\n"
-"              => 10d20'30\"N 020d30'40\"E\n"
-"\n"
-"           Quoting of command line arguments is similar\n"
-"\n"
-"              GeoConvert -d -p -1 --input-string \"10d20'30\\\" 20d30'40\"\n"
-"              => 10d20'30\"N 020d30'40\"E\n"
-"\n"
-"       Windows command shell (cmd)\n"
-"           The ' character needs no quoting; the \" character can either be\n"
-"           quoted by a ^ or can be represented by typing ' twice.  (This\n"
-"           quoting is usually unnecessary because the trailing designator can\n"
-"           be omitted.)  Thus\n"
-"\n"
-"              echo 10d20'30'' 20d30'40 | GeoConvert -d -p -1\n"
-"              => 10d20'30\"N 020d30'40\"E\n"
-"\n"
-"           Use \\ to quote the \" character in a command line argument\n"
-"\n"
-"              GeoConvert -d -p -1 --input-string \"10d20'30\\\" 20d30'40\"\n"
-"              => 10d20'30\"N 020d30'40\"E\n"
-"\n"
-"       Input from a file\n"
-"           No quoting need be done if the input from a file.  Thus each line\n"
-"           of the file \"input.txt\" should just contain the plain coordinates.\n"
-"\n"
-"             GeoConvert -d -p -1 < input.txt\n"
-"\n"
 "EXAMPLES\n"
 "          echo 38SMB4488 | GeoConvert         => 33.33424 44.40363\n"
 "          echo 38SMB4488 | GeoConvert -: -p 1 => 33:20:03.25N 044:2413.06E\n"
diff --git a/man/GeodSolve.1 b/man/GeodSolve.1
index 667eb95..5bf7fb2 100644
--- a/man/GeodSolve.1
+++ b/man/GeodSolve.1
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "GEODSOLVE 1"
-.TH GEODSOLVE 1 "2015-05-22" "GeographicLib 1.43" "GeographicLib Utilities"
+.TH GEODSOLVE 1 "2015-08-14" "GeographicLib 1.44" "GeographicLib Utilities"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
@@ -144,7 +144,7 @@ GeodSolve \-\- perform geodesic calculations
 .IX Header "SYNOPSIS"
 \&\fBGeodSolve\fR [ \fB\-i\fR | \fB\-l\fR \fIlat1\fR \fIlon1\fR \fIazi1\fR ] [ \fB\-a\fR ]
 [ \fB\-e\fR \fIa\fR \fIf\fR ] \fB\-u\fR ]
-[ \fB\-d\fR | \fB\-:\fR ] [ \fB\-b\fR ] [ \fB\-f\fR ] [ \fB\-p\fR \fIprec\fR ] [ \fB\-E\fR ]
+[ \fB\-d\fR | \fB\-:\fR ] [ \fB\-w\fR ] [ \fB\-b\fR ] [ \fB\-f\fR ] [ \fB\-p\fR \fIprec\fR ] [ \fB\-E\fR ]
 [ \fB\-\-comment\-delimiter\fR \fIcommentdelim\fR ]
 [ \fB\-\-version\fR | \fB\-h\fR | \fB\-\-help\fR ]
 [ \fB\-\-input\-file\fR \fIinfile\fR | \fB\-\-input\-string\fR \fIinstring\fR ]
@@ -179,7 +179,9 @@ perform an inverse geodesic calculation (see 3 above).
 .IP "\fB\-l\fR" 4
 .IX Item "-l"
 line mode (see 2 above); generate a sequence of points along the
-geodesic specified by \fIlat1\fR \fIlon1\fR \fIazi1\fR.
+geodesic specified by \fIlat1\fR \fIlon1\fR \fIazi1\fR.  The \fB\-w\fR flag can be
+used to swap the default order of the 2 geographic coordinates, provided
+that it appears before \fB\-l\fR.
 .IP "\fB\-a\fR" 4
 .IX Item "-a"
 arc mode; on input \fIand\fR output \fIs12\fR is replaced by \fIa12\fR the arc
@@ -194,11 +196,11 @@ is allowed for \fIf\fR.  (Also, if \fIf\fR > 1, the flattening is set to
 \&\fIf\fR = 1/298.257223563.
 .IP "\fB\-u\fR" 4
 .IX Item "-u"
-unroll the longitude.  On input longitudes must lie in [\-540deg,540deg)
-and, normally, on output longitudes are reduced to lie in
-[\-180deg,180deg).  However with this option, the returned longitude
+unroll the longitude.  Normally, on output longitudes are reduced to lie
+in [\-180deg,180deg).  However with this option, the returned longitude
 \&\fIlon2\fR is \*(L"unrolled\*(R" so that \fIlon2\fR \- \fIlon1\fR indicates how often and
-in what sense the geodesic has encircled the earth.
+in what sense the geodesic has encircled the earth.  Use the \fB\-f\fR
+option, to get both longitudes printed.
 .IP "\fB\-d\fR" 4
 .IX Item "-d"
 output angles as degrees, minutes, seconds instead of decimal degrees.
@@ -206,6 +208,11 @@ output angles as degrees, minutes, seconds instead of decimal degrees.
 .IX Item "-:"
 like \fB\-d\fR, except use : as a separator instead of the d, ', and "
 delimiters.
+.IP "\fB\-w\fR" 4
+.IX Item "-w"
+on input and output, longitude precedes latitude (except that, on input,
+this can be overridden by a hemisphere designator, \fIN\fR, \fIS\fR, \fIE\fR,
+\&\fIW\fR).
 .IP "\fB\-b\fR" 4
 .IX Item "-b"
 report the \fIback\fR azimuth at point 2 instead of the forward azimuth.
@@ -261,18 +268,18 @@ file name of \*(L"\-\*(R" stands for standard output.
 .SH "INPUT"
 .IX Header "INPUT"
 \&\fBGeodSolve\fR measures all angles in degrees and all lengths (\fIs12\fR) in
-meters.  On input angles (latitude, longitude, azimuth, arc length) can
-be as decimal degrees or degrees (d), minutes ('), seconds (\*(L").  A
-decimal point can only appear in the least significant component and the
-designator (d, ', or \*(R") for this component is optional; thus \f(CW\*(C`40d30\*(C'\fR,
-\&\f(CW\*(C`40d30\*(Aq\*(C'\fR, \f(CW\*(C`40.5d\*(C'\fR, and \f(CW40.5\fR are all equivalent.  By default,
-latitude precedes longitude for each point; however on input either may
-be given first by appending (or prepending) \fIN\fR or \fIS\fR to the latitude
-and \fIE\fR or \fIW\fR to the longitude.  Azimuths are measured clockwise from
-north; however this may be overridden with \fIE\fR or \fIW\fR.
+meters, and all areas (\fIS12\fR) in meters^2.  On input angles (latitude,
+longitude, azimuth, arc length) can be as decimal degrees or degrees,
+minutes, seconds.  For example, \f(CW\*(C`40d30\*(C'\fR, \f(CW\*(C`40d30\*(Aq\*(C'\fR, \f(CW\*(C`40:30\*(C'\fR, \f(CW\*(C`40.5d\*(C'\fR,
+and \f(CW40.5\fR are all equivalent.  By default, latitude precedes longitude
+for each point (the \fB\-w\fR flag switches this convention); however on
+input either may be given first by appending (or prepending) \fIN\fR or
+\&\fIS\fR to the latitude and \fIE\fR or \fIW\fR to the longitude.  Azimuths are
+measured clockwise from north; however this may be overridden with \fIE\fR
+or \fIW\fR.
 .PP
-See the \f(CW\*(C`QUOTING\*(C'\fR section of \fIGeoConvert\fR\|(1) for how to quote the \s-1DMS\s0
-designators ' and ".
+For details on the allowed formats for angles, see the \f(CW\*(C`GEOGRAPHIC
+COORDINATES\*(C'\fR section of \fIGeoConvert\fR\|(1).
 .SH "AUXILIARY SPHERE"
 .IX Header "AUXILIARY SPHERE"
 Geodesics on the ellipsoid can be transferred to the \fIauxiliary sphere\fR
@@ -303,13 +310,16 @@ and \fIM21\fR are dimensionless quantities.  On a flat surface, we have
 \&\fIM12\fR = \fIM21\fR = 1.
 .PP
 If points 1, 2, and 3 lie on a single geodesic, then the following
-addition rules hold,
-\&\fIs13\fR = \fIs12\fR + \fIs23\fR,
-\&\fIa13\fR = \fIa12\fR + \fIa23\fR,
-\&\fIS13\fR = \fIS12\fR + \fIS23\fR,
-\&\fIm13\fR = \fIm12\fR \fIM23\fR + \fIm23\fR \fIM21\fR,
-\&\fIM13\fR = \fIM12\fR \fIM23\fR \- (1 \- \fIM12\fR \fIM21\fR) \fIm23\fR / \fIm12\fR, and
-\&\fIM31\fR = \fIM32\fR \fIM21\fR \- (1 \- \fIM23\fR \fIM32\fR) \fIm12\fR / \fIm23\fR.
+addition rules hold:
+.PP
+.Vb 6
+\&   s13 = s12 + s23,
+\&   a13 = a12 + a23,
+\&   S13 = S12 + S23,
+\&   m13 = m12 M23 + m23 M21,
+\&   M13 = M12 M23 \- (1 \- M12 M21) m23 / m12,
+\&   M31 = M32 M21 \- (1 \- M23 M32) m12 / m23.
+.Ve
 .PP
 Finally, \fIS12\fR is the area between the geodesic from point 1 to point 2
 and the equator; i.e., it is the area, measured counter-clockwise, of
diff --git a/man/GeodSolve.1.html b/man/GeodSolve.1.html
index e148468..f03a446 100644
--- a/man/GeodSolve.1.html
+++ b/man/GeodSolve.1.html
@@ -17,7 +17,7 @@
 
 <h1 id="SYNOPSIS">SYNOPSIS</h1>
 
-<p><b>GeodSolve</b> [ <b>-i</b> | <b>-l</b> <i>lat1</i> <i>lon1</i> <i>azi1</i> ] [ <b>-a</b> ] [ <b>-e</b> <i>a</i> <i>f</i> ] <b>-u</b> ] [ <b>-d</b> | <b>-:</b> ] [ <b>-b</b> ] [ <b>-f</b> ] [ <b>-p</b> <i>prec</i> ] [ <b>-E</b> ] [ <b>--comment-delimiter</b> <i>commentdelim</i> ] [ <b>--version</b> | <b>-h</b> | <b>--help</b> ] [ <b>--input-file</b> <i>infile</i> | <b>--input-string</b> <i>instring</i> ] [ <b>--line-separator</b> <i>linesep</i> ] [ <b>--output-file</b> <i>outfile</i> ]</p>
+<p><b>GeodSolve</b> [ <b>-i</b> | <b>-l</b> <i>lat1</i> <i>lon1</i> <i>azi1</i> ] [ <b>-a</b> ] [ <b>-e</b> <i>a</i> <i>f</i> ] <b>-u</b> ] [ <b>-d</b> | <b>-:</b> ] [ <b>-w</b> ] [ <b>-b</b> ] [ <b>-f</b> ] [ <b>-p</b> <i>prec</i> ] [ <b>-E</b> ] [ <b>--comment-delimiter</b> <i>commentdelim</i> ] [ <b>--version</b> | <b>-h</b> | <b>--help</b> ] [ <b>--input-file</b> <i>infile</i> | <b>--input-string</b> <i>instring</i> ] [ <b>--line-separator</b> <i>linesep</i> ] [ <b>--output-file</b>  [...]
 
 <h1 id="DESCRIPTION">DESCRIPTION</h1>
 
@@ -51,7 +51,7 @@
 <dt id="l"><b>-l</b></dt>
 <dd>
 
-<p>line mode (see 2 above); generate a sequence of points along the geodesic specified by <i>lat1</i> <i>lon1</i> <i>azi1</i>.</p>
+<p>line mode (see 2 above); generate a sequence of points along the geodesic specified by <i>lat1</i> <i>lon1</i> <i>azi1</i>. The <b>-w</b> flag can be used to swap the default order of the 2 geographic coordinates, provided that it appears before <b>-l</b>.</p>
 
 </dd>
 <dt id="a"><b>-a</b></dt>
@@ -69,7 +69,7 @@
 <dt id="u"><b>-u</b></dt>
 <dd>
 
-<p>unroll the longitude. On input longitudes must lie in [-540deg,540deg) and, normally, on output longitudes are reduced to lie in [-180deg,180deg). However with this option, the returned longitude <i>lon2</i> is "unrolled" so that <i>lon2</i> - <i>lon1</i> indicates how often and in what sense the geodesic has encircled the earth.</p>
+<p>unroll the longitude. Normally, on output longitudes are reduced to lie in [-180deg,180deg). However with this option, the returned longitude <i>lon2</i> is "unrolled" so that <i>lon2</i> - <i>lon1</i> indicates how often and in what sense the geodesic has encircled the earth. Use the <b>-f</b> option, to get both longitudes printed.</p>
 
 </dd>
 <dt id="d"><b>-d</b></dt>
@@ -84,6 +84,12 @@
 <p>like <b>-d</b>, except use : as a separator instead of the d, ', and " delimiters.</p>
 
 </dd>
+<dt id="w"><b>-w</b></dt>
+<dd>
+
+<p>on input and output, longitude precedes latitude (except that, on input, this can be overridden by a hemisphere designator, <i>N</i>, <i>S</i>, <i>E</i>, <i>W</i>).</p>
+
+</dd>
 <dt id="b"><b>-b</b></dt>
 <dd>
 
@@ -160,9 +166,9 @@
 
 <h1 id="INPUT">INPUT</h1>
 
-<p><b>GeodSolve</b> measures all angles in degrees and all lengths (<i>s12</i>) in meters. On input angles (latitude, longitude, azimuth, arc length) can be as decimal degrees or degrees (d), minutes ('), seconds ("). A decimal point can only appear in the least significant component and the designator (d, ', or ") for this component is optional; thus <code>40d30</code>, <code>40d30'</code>, <code>40.5d</code>, and <code>40.5</code> are all equivalent. By default, l [...]
+<p><b>GeodSolve</b> measures all angles in degrees and all lengths (<i>s12</i>) in meters, and all areas (<i>S12</i>) in meters^2. On input angles (latitude, longitude, azimuth, arc length) can be as decimal degrees or degrees, minutes, seconds. For example, <code>40d30</code>, <code>40d30'</code>, <code>40:30</code>, <code>40.5d</code>, and <code>40.5</code> are all equivalent. By default, latitude precedes longitude for each point (the <b>-w</b> flag switches this convention); howe [...]
 
-<p>See the <code>QUOTING</code> section of GeoConvert(1) for how to quote the DMS designators ' and ".</p>
+<p>For details on the allowed formats for angles, see the <code>GEOGRAPHIC COORDINATES</code> section of GeoConvert(1).</p>
 
 <h1 id="AUXILIARY-SPHERE">AUXILIARY SPHERE</h1>
 
@@ -176,7 +182,14 @@
 
 <p><i>M12</i> and <i>M21</i> are geodesic scales. If two geodesics are parallel at point 1 and separated by a small distance <i>dt</i>, then they are separated by a distance <i>M12</i> <i>dt</i> at point 2. <i>M21</i> is defined similarly (with the geodesics being parallel to one another at point 2). <i>M12</i> and <i>M21</i> are dimensionless quantities. On a flat surface, we have <i>M12</i> = <i>M21</i> = 1.</p>
 
-<p>If points 1, 2, and 3 lie on a single geodesic, then the following addition rules hold, <i>s13</i> = <i>s12</i> + <i>s23</i>, <i>a13</i> = <i>a12</i> + <i>a23</i>, <i>S13</i> = <i>S12</i> + <i>S23</i>, <i>m13</i> = <i>m12</i> <i>M23</i> + <i>m23</i> <i>M21</i>, <i>M13</i> = <i>M12</i> <i>M23</i> - (1 - <i>M12</i> <i>M21</i>) <i>m23</i> / <i>m12</i>, and <i>M31</i> = <i>M32</i> <i>M21</i> - (1 - <i>M23</i> <i>M32</i>) <i>m12</i> / <i>m23</i>.</p>
+<p>If points 1, 2, and 3 lie on a single geodesic, then the following addition rules hold:</p>
+
+<pre><code>   s13 = s12 + s23,
+   a13 = a12 + a23,
+   S13 = S12 + S23,
+   m13 = m12 M23 + m23 M21,
+   M13 = M12 M23 - (1 - M12 M21) m23 / m12,
+   M31 = M32 M21 - (1 - M23 M32) m12 / m23.</code></pre>
 
 <p>Finally, <i>S12</i> is the area between the geodesic from point 1 to point 2 and the equator; i.e., it is the area, measured counter-clockwise, of the geodesic quadrilateral with corners (<i>lat1</i>,<i>lon1</i>), (0,<i>lon1</i>), (0,<i>lon2</i>), and (<i>lat2</i>,<i>lon2</i>). It is given in meters^2.</p>
 
diff --git a/man/GeodSolve.pod b/man/GeodSolve.pod
index 87b9d5a..e4d561b 100644
--- a/man/GeodSolve.pod
+++ b/man/GeodSolve.pod
@@ -6,7 +6,7 @@ GeodSolve -- perform geodesic calculations
 
 B<GeodSolve> [ B<-i> | B<-l> I<lat1> I<lon1> I<azi1> ] [ B<-a> ]
 [ B<-e> I<a> I<f> ] B<-u> ]
-[ B<-d> | B<-:> ] [ B<-b> ] [ B<-f> ] [ B<-p> I<prec> ] [ B<-E> ]
+[ B<-d> | B<-:> ] [ B<-w> ] [ B<-b> ] [ B<-f> ] [ B<-p> I<prec> ] [ B<-E> ]
 [ B<--comment-delimiter> I<commentdelim> ]
 [ B<--version> | B<-h> | B<--help> ]
 [ B<--input-file> I<infile> | B<--input-string> I<instring> ]
@@ -56,7 +56,9 @@ perform an inverse geodesic calculation (see 3 above).
 =item B<-l>
 
 line mode (see 2 above); generate a sequence of points along the
-geodesic specified by I<lat1> I<lon1> I<azi1>.
+geodesic specified by I<lat1> I<lon1> I<azi1>.  The B<-w> flag can be
+used to swap the default order of the 2 geographic coordinates, provided
+that it appears before B<-l>.
 
 =item B<-a>
 
@@ -74,11 +76,11 @@ I<f> = 1/298.257223563.
 
 =item B<-u>
 
-unroll the longitude.  On input longitudes must lie in [-540deg,540deg)
-and, normally, on output longitudes are reduced to lie in
-[-180deg,180deg).  However with this option, the returned longitude
+unroll the longitude.  Normally, on output longitudes are reduced to lie
+in [-180deg,180deg).  However with this option, the returned longitude
 I<lon2> is "unrolled" so that I<lon2> - I<lon1> indicates how often and
-in what sense the geodesic has encircled the earth.
+in what sense the geodesic has encircled the earth.  Use the B<-f>
+option, to get both longitudes printed.
 
 =item B<-d>
 
@@ -89,6 +91,12 @@ output angles as degrees, minutes, seconds instead of decimal degrees.
 like B<-d>, except use : as a separator instead of the d, ', and "
 delimiters.
 
+=item B<-w>
+
+on input and output, longitude precedes latitude (except that, on input,
+this can be overridden by a hemisphere designator, I<N>, I<S>, I<E>,
+I<W>).
+
 =item B<-b>
 
 report the I<back> azimuth at point 2 instead of the forward azimuth.
@@ -158,18 +166,18 @@ file name of "-" stands for standard output.
 =head1 INPUT
 
 B<GeodSolve> measures all angles in degrees and all lengths (I<s12>) in
-meters.  On input angles (latitude, longitude, azimuth, arc length) can
-be as decimal degrees or degrees (d), minutes ('), seconds (").  A
-decimal point can only appear in the least significant component and the
-designator (d, ', or ") for this component is optional; thus C<40d30>,
-C<40d30'>, C<40.5d>, and C<40.5> are all equivalent.  By default,
-latitude precedes longitude for each point; however on input either may
-be given first by appending (or prepending) I<N> or I<S> to the latitude
-and I<E> or I<W> to the longitude.  Azimuths are measured clockwise from
-north; however this may be overridden with I<E> or I<W>.
-
-See the C<QUOTING> section of GeoConvert(1) for how to quote the DMS
-designators ' and ".
+meters, and all areas (I<S12>) in meters^2.  On input angles (latitude,
+longitude, azimuth, arc length) can be as decimal degrees or degrees,
+minutes, seconds.  For example, C<40d30>, C<40d30'>, C<40:30>, C<40.5d>,
+and C<40.5> are all equivalent.  By default, latitude precedes longitude
+for each point (the B<-w> flag switches this convention); however on
+input either may be given first by appending (or prepending) I<N> or
+I<S> to the latitude and I<E> or I<W> to the longitude.  Azimuths are
+measured clockwise from north; however this may be overridden with I<E>
+or I<W>.
+
+For details on the allowed formats for angles, see the C<GEOGRAPHIC
+COORDINATES> section of GeoConvert(1).
 
 =head1 AUXILIARY SPHERE
 
@@ -202,13 +210,14 @@ and I<M21> are dimensionless quantities.  On a flat surface, we have
 I<M12> = I<M21> = 1.
 
 If points 1, 2, and 3 lie on a single geodesic, then the following
-addition rules hold,
-I<s13> = I<s12> + I<s23>,
-I<a13> = I<a12> + I<a23>,
-I<S13> = I<S12> + I<S23>,
-I<m13> = I<m12> I<M23> + I<m23> I<M21>,
-I<M13> = I<M12> I<M23> - (1 - I<M12> I<M21>) I<m23> / I<m12>, and
-I<M31> = I<M32> I<M21> - (1 - I<M23> I<M32>) I<m12> / I<m23>.
+addition rules hold:
+
+   s13 = s12 + s23,
+   a13 = a12 + a23,
+   S13 = S12 + S23,
+   m13 = m12 M23 + m23 M21,
+   M13 = M12 M23 - (1 - M12 M21) m23 / m12,
+   M31 = M32 M21 - (1 - M23 M32) m12 / m23.
 
 Finally, I<S12> is the area between the geodesic from point 1 to point 2
 and the equator; i.e., it is the area, measured counter-clockwise, of
diff --git a/man/GeodSolve.usage b/man/GeodSolve.usage
index 161f8d0..f856ced 100644
--- a/man/GeodSolve.usage
+++ b/man/GeodSolve.usage
@@ -2,14 +2,15 @@ int usage(int retval, bool brief) {
   if (brief)
     ( retval ? std::cerr : std::cout ) << "Usage:\n"
 "    GeodSolve [ -i | -l lat1 lon1 azi1 ] [ -a ] [ -e a f ] -u ] [ -d | -: ]\n"
-"    [ -b ] [ -f ] [ -p prec ] [ -E ] [ --comment-delimiter commentdelim ] [\n"
-"    --version | -h | --help ] [ --input-file infile | --input-string\n"
-"    instring ] [ --line-separator linesep ] [ --output-file outfile ]\n"
+"    [ -w ] [ -b ] [ -f ] [ -p prec ] [ -E ] [ --comment-delimiter\n"
+"    commentdelim ] [ --version | -h | --help ] [ --input-file infile |\n"
+"    --input-string instring ] [ --line-separator linesep ] [ --output-file\n"
+"    outfile ]\n"
 "\n"
 "For full documentation type:\n"
 "    GeodSolve --help\n"
 "or visit:\n"
-"    http://geographiclib.sf.net/1.43/GeodSolve.1.html\n";
+"    http://geographiclib.sf.net/1.44/GeodSolve.1.html\n";
   else
     ( retval ? std::cerr : std::cout ) << "Man page:\n"
 "NAME\n"
@@ -17,9 +18,10 @@ int usage(int retval, bool brief) {
 "\n"
 "SYNOPSIS\n"
 "       GeodSolve [ -i | -l lat1 lon1 azi1 ] [ -a ] [ -e a f ] -u ] [ -d | -: ]\n"
-"       [ -b ] [ -f ] [ -p prec ] [ -E ] [ --comment-delimiter commentdelim ] [\n"
-"       --version | -h | --help ] [ --input-file infile | --input-string\n"
-"       instring ] [ --line-separator linesep ] [ --output-file outfile ]\n"
+"       [ -w ] [ -b ] [ -f ] [ -p prec ] [ -E ] [ --comment-delimiter\n"
+"       commentdelim ] [ --version | -h | --help ] [ --input-file infile |\n"
+"       --input-string instring ] [ --line-separator linesep ] [ --output-file\n"
+"       outfile ]\n"
 "\n"
 "DESCRIPTION\n"
 "       The shortest path between two points on the ellipsoid at (lat1, lon1)\n"
@@ -46,7 +48,9 @@ int usage(int retval, bool brief) {
 "       -i  perform an inverse geodesic calculation (see 3 above).\n"
 "\n"
 "       -l  line mode (see 2 above); generate a sequence of points along the\n"
-"           geodesic specified by lat1 lon1 azi1.\n"
+"           geodesic specified by lat1 lon1 azi1.  The -w flag can be used to\n"
+"           swap the default order of the 2 geographic coordinates, provided\n"
+"           that it appears before -l.\n"
 "\n"
 "       -a  arc mode; on input and output s12 is replaced by a12 the arc length\n"
 "           (in degrees) on the auxiliary sphere.  See \"AUXILIARY SPHERE\".\n"
@@ -58,11 +62,11 @@ int usage(int retval, bool brief) {
 "           default, the WGS84 ellipsoid is used, a = 6378137 m, f =\n"
 "           1/298.257223563.\n"
 "\n"
-"       -u  unroll the longitude.  On input longitudes must lie in\n"
-"           [-540deg,540deg) and, normally, on output longitudes are reduced to\n"
-"           lie in [-180deg,180deg).  However with this option, the returned\n"
+"       -u  unroll the longitude.  Normally, on output longitudes are reduced\n"
+"           to lie in [-180deg,180deg).  However with this option, the returned\n"
 "           longitude lon2 is \"unrolled\" so that lon2 - lon1 indicates how\n"
-"           often and in what sense the geodesic has encircled the earth.\n"
+"           often and in what sense the geodesic has encircled the earth.  Use\n"
+"           the -f option, to get both longitudes printed.\n"
 "\n"
 "       -d  output angles as degrees, minutes, seconds instead of decimal\n"
 "           degrees.\n"
@@ -70,6 +74,10 @@ int usage(int retval, bool brief) {
 "       -:  like -d, except use : as a separator instead of the d, ', and \"\n"
 "           delimiters.\n"
 "\n"
+"       -w  on input and output, longitude precedes latitude (except that, on\n"
+"           input, this can be overridden by a hemisphere designator, N, S, E,\n"
+"           W).\n"
+"\n"
 "       -b  report the back azimuth at point 2 instead of the forward azimuth.\n"
 "\n"
 "       -f  full output; each line of output consists of 12 quantities: lat1\n"
@@ -119,18 +127,17 @@ int usage(int retval, bool brief) {
 "\n"
 "INPUT\n"
 "       GeodSolve measures all angles in degrees and all lengths (s12) in\n"
-"       meters.  On input angles (latitude, longitude, azimuth, arc length) can\n"
-"       be as decimal degrees or degrees (d), minutes ('), seconds (\").  A\n"
-"       decimal point can only appear in the least significant component and\n"
-"       the designator (d, ', or \") for this component is optional; thus\n"
-"       \"40d30\", \"40d30'\", \"40.5d\", and 40.5 are all equivalent.  By default,\n"
-"       latitude precedes longitude for each point; however on input either may\n"
-"       be given first by appending (or prepending) N or S to the latitude and\n"
-"       E or W to the longitude.  Azimuths are measured clockwise from north;\n"
-"       however this may be overridden with E or W.\n"
-"\n"
-"       See the \"QUOTING\" section of GeoConvert(1) for how to quote the DMS\n"
-"       designators ' and \".\n"
+"       meters, and all areas (S12) in meters^2.  On input angles (latitude,\n"
+"       longitude, azimuth, arc length) can be as decimal degrees or degrees,\n"
+"       minutes, seconds.  For example, \"40d30\", \"40d30'\", \"40:30\", \"40.5d\",\n"
+"       and 40.5 are all equivalent.  By default, latitude precedes longitude\n"
+"       for each point (the -w flag switches this convention); however on input\n"
+"       either may be given first by appending (or prepending) N or S to the\n"
+"       latitude and E or W to the longitude.  Azimuths are measured clockwise\n"
+"       from north; however this may be overridden with E or W.\n"
+"\n"
+"       For details on the allowed formats for angles, see the \"GEOGRAPHIC\n"
+"       COORDINATES\" section of GeoConvert(1).\n"
 "\n"
 "AUXILIARY SPHERE\n"
 "       Geodesics on the ellipsoid can be transferred to the auxiliary sphere\n"
@@ -159,9 +166,14 @@ int usage(int retval, bool brief) {
 "       dimensionless quantities.  On a flat surface, we have M12 = M21 = 1.\n"
 "\n"
 "       If points 1, 2, and 3 lie on a single geodesic, then the following\n"
-"       addition rules hold, s13 = s12 + s23, a13 = a12 + a23, S13 = S12 + S23,\n"
-"       m13 = m12 M23 + m23 M21, M13 = M12 M23 - (1 - M12 M21) m23 / m12, and\n"
-"       M31 = M32 M21 - (1 - M23 M32) m12 / m23.\n"
+"       addition rules hold:\n"
+"\n"
+"          s13 = s12 + s23,\n"
+"          a13 = a12 + a23,\n"
+"          S13 = S12 + S23,\n"
+"          m13 = m12 M23 + m23 M21,\n"
+"          M13 = M12 M23 - (1 - M12 M21) m23 / m12,\n"
+"          M31 = M32 M21 - (1 - M23 M32) m12 / m23.\n"
 "\n"
 "       Finally, S12 is the area between the geodesic from point 1 to point 2\n"
 "       and the equator; i.e., it is the area, measured counter-clockwise, of\n"
diff --git a/man/GeodesicProj.1 b/man/GeodesicProj.1
index 523e268..c36ad97 100644
--- a/man/GeodesicProj.1
+++ b/man/GeodesicProj.1
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "GEODESICPROJ 1"
-.TH GEODESICPROJ 1 "2015-05-22" "GeographicLib 1.43" "GeographicLib Utilities"
+.TH GEODESICPROJ 1 "2015-08-14" "GeographicLib 1.44" "GeographicLib Utilities"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
@@ -143,7 +143,7 @@ GeodesicProj \-\- perform projections based on geodesics
 .SH "SYNOPSIS"
 .IX Header "SYNOPSIS"
 \&\fBGeodesicProj\fR ( \fB\-z\fR | \fB\-c\fR | \fB\-g\fR ) \fIlat0\fR \fIlon0\fR [ \fB\-r\fR ]
-[ \fB\-e\fR \fIa\fR \fIf\fR ] [ \fB\-p\fR \fIprec\fR ]
+[ \fB\-e\fR \fIa\fR \fIf\fR ] [ \fB\-w\fR ] [ \fB\-p\fR \fIprec\fR ]
 [ \fB\-\-comment\-delimiter\fR \fIcommentdelim\fR ]
 [ \fB\-\-version\fR | \fB\-h\fR | \fB\-\-help\fR ]
 [ \fB\-\-input\-file\fR \fIinfile\fR | \fB\-\-input\-string\fR \fIinstring\fR ]
@@ -160,30 +160,35 @@ options must be given (the last one given is used).
 .PP
 Geodetic coordinates are provided on standard input as a set of lines
 containing (blank separated) \fIlatitude\fR and \fIlongitude\fR (decimal
-degrees or degrees, minutes, seconds).  For each set of geodetic
-coordinates, the corresponding projected coordinates \fIx\fR, \fIy\fR (meters)
-are printed on standard output together with the azimuth \fIazi\fR
-(degrees) and reciprocal scale \fIrk\fR.  For Cassini-Soldner, \fIazi\fR is
-the bearing of the easting direction and the scale in the easting
-direction is 1 and the scale in the northing direction is 1/\fIrk\fR.  For
-azimuthal equidistant and gnomonic, \fIazi\fR is the bearing of the radial
-direction and the scale in the azimuthal direction is 1/\fIrk\fR.  For
-azimuthal equidistant and gnomonic, the scales in the radial direction
-are 1 and 1/\fIrk\fR^2, respectively.
+degrees or degrees, minutes, seconds); for details on the allowed
+formats for latitude and longitude, see the \f(CW\*(C`GEOGRAPHIC COORDINATES\*(C'\fR
+section of \fIGeoConvert\fR\|(1).  For each set of geodetic coordinates, the
+corresponding projected coordinates \fIx\fR, \fIy\fR (meters) are printed on
+standard output together with the azimuth \fIazi\fR (degrees) and
+reciprocal scale \fIrk\fR.  For Cassini-Soldner, \fIazi\fR is the bearing of
+the easting direction and the scale in the easting direction is 1 and
+the scale in the northing direction is 1/\fIrk\fR.  For azimuthal
+equidistant and gnomonic, \fIazi\fR is the bearing of the radial direction
+and the scale in the azimuthal direction is 1/\fIrk\fR.  For azimuthal
+equidistant and gnomonic, the scales in the radial direction are 1 and
+1/\fIrk\fR^2, respectively.
 .SH "OPTIONS"
 .IX Header "OPTIONS"
 .IP "\fB\-z\fR" 4
 .IX Item "-z"
 use the azimuthal equidistant projection centered at latitude = \fIlat0\fR,
-longitude = \fIlon0\fR.
+longitude = \fIlon0\fR.  The \fB\-w\fR flag can be used to swap the default
+order of the 2 coordinates, provided that it appears before \fB\-z\fR.
 .IP "\fB\-c\fR" 4
 .IX Item "-c"
 use the Cassini-Soldner projection centered at latitude = \fIlat0\fR,
-longitude = \fIlon0\fR.
+longitude = \fIlon0\fR.  The \fB\-w\fR flag can be used to swap the default
+order of the 2 coordinates, provided that it appears before \fB\-c\fR.
 .IP "\fB\-g\fR" 4
 .IX Item "-g"
 use the ellipsoidal gnomonic projection centered at latitude = \fIlat0\fR,
-longitude = \fIlon0\fR.
+longitude = \fIlon0\fR.  The \fB\-w\fR flag can be used to swap the default
+order of the 2 coordinates, provided that it appears before \fB\-g\fR.
 .IP "\fB\-r\fR" 4
 .IX Item "-r"
 perform the reverse projection.  \fIx\fR and \fIy\fR are given on standard
@@ -197,6 +202,11 @@ the flattening is \fIf\fR.  Setting \fIf\fR = 0 results in a sphere.  Specify
 is allowed for \fIf\fR.  (Also, if \fIf\fR > 1, the flattening is set to
 1/\fIf\fR.)  By default, the \s-1WGS84\s0 ellipsoid is used, \fIa\fR = 6378137 m,
 \&\fIf\fR = 1/298.257223563.
+.IP "\fB\-w\fR" 4
+.IX Item "-w"
+on input and output, longitude precedes latitude (except that, on input,
+this can be overridden by a hemisphere designator, \fIN\fR, \fIS\fR, \fIE\fR,
+\&\fIW\fR).
 .IP "\fB\-p\fR" 4
 .IX Item "-p"
 set the output precision to \fIprec\fR (default 6).  \fIprec\fR is the number
diff --git a/man/GeodesicProj.1.html b/man/GeodesicProj.1.html
index ac0068c..febd151 100644
--- a/man/GeodesicProj.1.html
+++ b/man/GeodesicProj.1.html
@@ -17,13 +17,13 @@
 
 <h1 id="SYNOPSIS">SYNOPSIS</h1>
 
-<p><b>GeodesicProj</b> ( <b>-z</b> | <b>-c</b> | <b>-g</b> ) <i>lat0</i> <i>lon0</i> [ <b>-r</b> ] [ <b>-e</b> <i>a</i> <i>f</i> ] [ <b>-p</b> <i>prec</i> ] [ <b>--comment-delimiter</b> <i>commentdelim</i> ] [ <b>--version</b> | <b>-h</b> | <b>--help</b> ] [ <b>--input-file</b> <i>infile</i> | <b>--input-string</b> <i>instring</i> ] [ <b>--line-separator</b> <i>linesep</i> ] [ <b>--output-file</b> <i>outfile</i> ]</p>
+<p><b>GeodesicProj</b> ( <b>-z</b> | <b>-c</b> | <b>-g</b> ) <i>lat0</i> <i>lon0</i> [ <b>-r</b> ] [ <b>-e</b> <i>a</i> <i>f</i> ] [ <b>-w</b> ] [ <b>-p</b> <i>prec</i> ] [ <b>--comment-delimiter</b> <i>commentdelim</i> ] [ <b>--version</b> | <b>-h</b> | <b>--help</b> ] [ <b>--input-file</b> <i>infile</i> | <b>--input-string</b> <i>instring</i> ] [ <b>--line-separator</b> <i>linesep</i> ] [ <b>--output-file</b> <i>outfile</i> ]</p>
 
 <h1 id="DESCRIPTION">DESCRIPTION</h1>
 
 <p>Perform projections based on geodesics. Convert geodetic coordinates to either azimuthal equidistant, Cassini-Soldner, or gnomonic coordinates. The center of the projection (<i>lat0</i>, <i>lon0</i>) is specified by either the <b>-c</b> option (for Cassini-Soldner), the <b>-z</b> option (for azimuthal equidistant), or the <b>-g</b> option (for gnomonic). At least one of these options must be given (the last one given is used).</p>
 
-<p>Geodetic coordinates are provided on standard input as a set of lines containing (blank separated) <i>latitude</i> and <i>longitude</i> (decimal degrees or degrees, minutes, seconds). For each set of geodetic coordinates, the corresponding projected coordinates <i>x</i>, <i>y</i> (meters) are printed on standard output together with the azimuth <i>azi</i> (degrees) and reciprocal scale <i>rk</i>. For Cassini-Soldner, <i>azi</i> is the bearing of the easting direction and the scale in  [...]
+<p>Geodetic coordinates are provided on standard input as a set of lines containing (blank separated) <i>latitude</i> and <i>longitude</i> (decimal degrees or degrees, minutes, seconds); for details on the allowed formats for latitude and longitude, see the <code>GEOGRAPHIC COORDINATES</code> section of GeoConvert(1). For each set of geodetic coordinates, the corresponding projected coordinates <i>x</i>, <i>y</i> (meters) are printed on standard output together with the azimuth <i>azi</i [...]
 
 <h1 id="OPTIONS">OPTIONS</h1>
 
@@ -32,19 +32,19 @@
 <dt id="z"><b>-z</b></dt>
 <dd>
 
-<p>use the azimuthal equidistant projection centered at latitude = <i>lat0</i>, longitude = <i>lon0</i>.</p>
+<p>use the azimuthal equidistant projection centered at latitude = <i>lat0</i>, longitude = <i>lon0</i>. The <b>-w</b> flag can be used to swap the default order of the 2 coordinates, provided that it appears before <b>-z</b>.</p>
 
 </dd>
 <dt id="c"><b>-c</b></dt>
 <dd>
 
-<p>use the Cassini-Soldner projection centered at latitude = <i>lat0</i>, longitude = <i>lon0</i>.</p>
+<p>use the Cassini-Soldner projection centered at latitude = <i>lat0</i>, longitude = <i>lon0</i>. The <b>-w</b> flag can be used to swap the default order of the 2 coordinates, provided that it appears before <b>-c</b>.</p>
 
 </dd>
 <dt id="g"><b>-g</b></dt>
 <dd>
 
-<p>use the ellipsoidal gnomonic projection centered at latitude = <i>lat0</i>, longitude = <i>lon0</i>.</p>
+<p>use the ellipsoidal gnomonic projection centered at latitude = <i>lat0</i>, longitude = <i>lon0</i>. The <b>-w</b> flag can be used to swap the default order of the 2 coordinates, provided that it appears before <b>-g</b>.</p>
 
 </dd>
 <dt id="r"><b>-r</b></dt>
@@ -59,6 +59,12 @@
 <p>specify the ellipsoid via <i>a</i> <i>f</i>; the equatorial radius is <i>a</i> and the flattening is <i>f</i>. Setting <i>f</i> = 0 results in a sphere. Specify <i>f</i> < 0 for a prolate ellipsoid. A simple fraction, e.g., 1/297, is allowed for <i>f</i>. (Also, if <i>f</i> > 1, the flattening is set to 1/<i>f</i>.) By default, the WGS84 ellipsoid is used, <i>a</i> = 6378137 m, <i>f</i> = 1/298.257223563.</p>
 
 </dd>
+<dt id="w"><b>-w</b></dt>
+<dd>
+
+<p>on input and output, longitude precedes latitude (except that, on input, this can be overridden by a hemisphere designator, <i>N</i>, <i>S</i>, <i>E</i>, <i>W</i>).</p>
+
+</dd>
 <dt id="p"><b>-p</b></dt>
 <dd>
 
diff --git a/man/GeodesicProj.pod b/man/GeodesicProj.pod
index 6414a24..addfef4 100644
--- a/man/GeodesicProj.pod
+++ b/man/GeodesicProj.pod
@@ -5,7 +5,7 @@ GeodesicProj -- perform projections based on geodesics
 =head1 SYNOPSIS
 
 B<GeodesicProj> ( B<-z> | B<-c> | B<-g> ) I<lat0> I<lon0> [ B<-r> ]
-[ B<-e> I<a> I<f> ] [ B<-p> I<prec> ]
+[ B<-e> I<a> I<f> ] [ B<-w> ] [ B<-p> I<prec> ]
 [ B<--comment-delimiter> I<commentdelim> ]
 [ B<--version> | B<-h> | B<--help> ]
 [ B<--input-file> I<infile> | B<--input-string> I<instring> ]
@@ -23,16 +23,18 @@ options must be given (the last one given is used).
 
 Geodetic coordinates are provided on standard input as a set of lines
 containing (blank separated) I<latitude> and I<longitude> (decimal
-degrees or degrees, minutes, seconds).  For each set of geodetic
-coordinates, the corresponding projected coordinates I<x>, I<y> (meters)
-are printed on standard output together with the azimuth I<azi>
-(degrees) and reciprocal scale I<rk>.  For Cassini-Soldner, I<azi> is
-the bearing of the easting direction and the scale in the easting
-direction is 1 and the scale in the northing direction is 1/I<rk>.  For
-azimuthal equidistant and gnomonic, I<azi> is the bearing of the radial
-direction and the scale in the azimuthal direction is 1/I<rk>.  For
-azimuthal equidistant and gnomonic, the scales in the radial direction
-are 1 and 1/I<rk>^2, respectively.
+degrees or degrees, minutes, seconds); for details on the allowed
+formats for latitude and longitude, see the C<GEOGRAPHIC COORDINATES>
+section of GeoConvert(1).  For each set of geodetic coordinates, the
+corresponding projected coordinates I<x>, I<y> (meters) are printed on
+standard output together with the azimuth I<azi> (degrees) and
+reciprocal scale I<rk>.  For Cassini-Soldner, I<azi> is the bearing of
+the easting direction and the scale in the easting direction is 1 and
+the scale in the northing direction is 1/I<rk>.  For azimuthal
+equidistant and gnomonic, I<azi> is the bearing of the radial direction
+and the scale in the azimuthal direction is 1/I<rk>.  For azimuthal
+equidistant and gnomonic, the scales in the radial direction are 1 and
+1/I<rk>^2, respectively.
 
 =head1 OPTIONS
 
@@ -41,17 +43,20 @@ are 1 and 1/I<rk>^2, respectively.
 =item B<-z>
 
 use the azimuthal equidistant projection centered at latitude = I<lat0>,
-longitude = I<lon0>.
+longitude = I<lon0>.  The B<-w> flag can be used to swap the default
+order of the 2 coordinates, provided that it appears before B<-z>.
 
 =item B<-c>
 
 use the Cassini-Soldner projection centered at latitude = I<lat0>,
-longitude = I<lon0>.
+longitude = I<lon0>.  The B<-w> flag can be used to swap the default
+order of the 2 coordinates, provided that it appears before B<-c>.
 
 =item B<-g>
 
 use the ellipsoidal gnomonic projection centered at latitude = I<lat0>,
-longitude = I<lon0>.
+longitude = I<lon0>.  The B<-w> flag can be used to swap the default
+order of the 2 coordinates, provided that it appears before B<-g>.
 
 =item B<-r>
 
@@ -68,6 +73,12 @@ is allowed for I<f>.  (Also, if I<f> E<gt> 1, the flattening is set to
 1/I<f>.)  By default, the WGS84 ellipsoid is used, I<a> = 6378137 m,
 I<f> = 1/298.257223563.
 
+=item B<-w>
+
+on input and output, longitude precedes latitude (except that, on input,
+this can be overridden by a hemisphere designator, I<N>, I<S>, I<E>,
+I<W>).
+
 =item B<-p>
 
 set the output precision to I<prec> (default 6).  I<prec> is the number
diff --git a/man/GeodesicProj.usage b/man/GeodesicProj.usage
index a6a3457..1d1e2ec 100644
--- a/man/GeodesicProj.usage
+++ b/man/GeodesicProj.usage
@@ -1,24 +1,24 @@
 int usage(int retval, bool brief) {
   if (brief)
     ( retval ? std::cerr : std::cout ) << "Usage:\n"
-"    GeodesicProj ( -z | -c | -g ) lat0 lon0 [ -r ] [ -e a f ] [ -p prec ] [\n"
-"    --comment-delimiter commentdelim ] [ --version | -h | --help ] [\n"
-"    --input-file infile | --input-string instring ] [ --line-separator\n"
+"    GeodesicProj ( -z | -c | -g ) lat0 lon0 [ -r ] [ -e a f ] [ -w ] [ -p\n"
+"    prec ] [ --comment-delimiter commentdelim ] [ --version | -h | --help ]\n"
+"    [ --input-file infile | --input-string instring ] [ --line-separator\n"
 "    linesep ] [ --output-file outfile ]\n"
 "\n"
 "For full documentation type:\n"
 "    GeodesicProj --help\n"
 "or visit:\n"
-"    http://geographiclib.sf.net/1.43/GeodesicProj.1.html\n";
+"    http://geographiclib.sf.net/1.44/GeodesicProj.1.html\n";
   else
     ( retval ? std::cerr : std::cout ) << "Man page:\n"
 "NAME\n"
 "       GeodesicProj -- perform projections based on geodesics\n"
 "\n"
 "SYNOPSIS\n"
-"       GeodesicProj ( -z | -c | -g ) lat0 lon0 [ -r ] [ -e a f ] [ -p prec ] [\n"
-"       --comment-delimiter commentdelim ] [ --version | -h | --help ] [\n"
-"       --input-file infile | --input-string instring ] [ --line-separator\n"
+"       GeodesicProj ( -z | -c | -g ) lat0 lon0 [ -r ] [ -e a f ] [ -w ] [ -p\n"
+"       prec ] [ --comment-delimiter commentdelim ] [ --version | -h | --help ]\n"
+"       [ --input-file infile | --input-string instring ] [ --line-separator\n"
 "       linesep ] [ --output-file outfile ]\n"
 "\n"
 "DESCRIPTION\n"
@@ -31,26 +31,32 @@ int usage(int retval, bool brief) {
 "\n"
 "       Geodetic coordinates are provided on standard input as a set of lines\n"
 "       containing (blank separated) latitude and longitude (decimal degrees or\n"
-"       degrees, minutes, seconds).  For each set of geodetic coordinates, the\n"
-"       corresponding projected coordinates x, y (meters) are printed on\n"
-"       standard output together with the azimuth azi (degrees) and reciprocal\n"
-"       scale rk.  For Cassini-Soldner, azi is the bearing of the easting\n"
-"       direction and the scale in the easting direction is 1 and the scale in\n"
-"       the northing direction is 1/rk.  For azimuthal equidistant and\n"
-"       gnomonic, azi is the bearing of the radial direction and the scale in\n"
-"       the azimuthal direction is 1/rk.  For azimuthal equidistant and\n"
-"       gnomonic, the scales in the radial direction are 1 and 1/rk^2,\n"
-"       respectively.\n"
+"       degrees, minutes, seconds); for details on the allowed formats for\n"
+"       latitude and longitude, see the \"GEOGRAPHIC COORDINATES\" section of\n"
+"       GeoConvert(1).  For each set of geodetic coordinates, the corresponding\n"
+"       projected coordinates x, y (meters) are printed on standard output\n"
+"       together with the azimuth azi (degrees) and reciprocal scale rk.  For\n"
+"       Cassini-Soldner, azi is the bearing of the easting direction and the\n"
+"       scale in the easting direction is 1 and the scale in the northing\n"
+"       direction is 1/rk.  For azimuthal equidistant and gnomonic, azi is the\n"
+"       bearing of the radial direction and the scale in the azimuthal\n"
+"       direction is 1/rk.  For azimuthal equidistant and gnomonic, the scales\n"
+"       in the radial direction are 1 and 1/rk^2, respectively.\n"
 "\n"
 "OPTIONS\n"
 "       -z  use the azimuthal equidistant projection centered at latitude =\n"
-"           lat0, longitude = lon0.\n"
+"           lat0, longitude = lon0.  The -w flag can be used to swap the\n"
+"           default order of the 2 coordinates, provided that it appears before\n"
+"           -z.\n"
 "\n"
 "       -c  use the Cassini-Soldner projection centered at latitude = lat0,\n"
-"           longitude = lon0.\n"
+"           longitude = lon0.  The -w flag can be used to swap the default\n"
+"           order of the 2 coordinates, provided that it appears before -c.\n"
 "\n"
 "       -g  use the ellipsoidal gnomonic projection centered at latitude =\n"
-"           lat0, longitude = lon0.\n"
+"           lat0, longitude = lon0.  The -w flag can be used to swap the\n"
+"           default order of the 2 coordinates, provided that it appears before\n"
+"           -g.\n"
 "\n"
 "       -r  perform the reverse projection.  x and y are given on standard\n"
 "           input and each line of standard output gives latitude, longitude,\n"
@@ -63,6 +69,10 @@ int usage(int retval, bool brief) {
 "           default, the WGS84 ellipsoid is used, a = 6378137 m, f =\n"
 "           1/298.257223563.\n"
 "\n"
+"       -w  on input and output, longitude precedes latitude (except that, on\n"
+"           input, this can be overridden by a hemisphere designator, N, S, E,\n"
+"           W).\n"
+"\n"
 "       -p  set the output precision to prec (default 6).  prec is the number\n"
 "           of digits after the decimal point for lengths (in meters).  For\n"
 "           latitudes, longitudes, and azimuths (in degrees), the number of\n"
diff --git a/man/GeoidEval.1 b/man/GeoidEval.1
index f15a12e..b7358f9 100644
--- a/man/GeoidEval.1
+++ b/man/GeoidEval.1
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "GEOIDEVAL 1"
-.TH GEOIDEVAL 1 "2015-05-22" "GeographicLib 1.43" "GeographicLib Utilities"
+.TH GEOIDEVAL 1 "2015-08-14" "GeographicLib 1.44" "GeographicLib Utilities"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
@@ -143,7 +143,7 @@ GeoidEval \-\- look up geoid heights
 .SH "SYNOPSIS"
 .IX Header "SYNOPSIS"
 \&\fBGeoidEval\fR [ \fB\-n\fR \fIname\fR ] [ \fB\-d\fR \fIdir\fR ] [ \fB\-l\fR ]
-[ \fB\-a\fR | \fB\-c\fR \fIsouth\fR \fIwest\fR \fInorth\fR \fIeast\fR ] [ \fB\-g\fR ]
+[ \fB\-a\fR | \fB\-c\fR \fIsouth\fR \fIwest\fR \fInorth\fR \fIeast\fR ] [ \fB\-w\fR ]
 [ \fB\-z\fR \fIzone\fR ] [ \fB\-\-msltohae\fR ] [ \fB\-\-haetomsl\fR ]
 [ \fB\-v\fR ]
 [ \fB\-\-comment\-delimiter\fR \fIcommentdelim\fR ]
@@ -196,16 +196,14 @@ cache the entire data set in memory.  See \*(L"\s-1CACHE\*(R"\s0.
 .IP "\fB\-c\fR" 4
 .IX Item "-c"
 cache the data bounded by \fIsouth\fR \fIwest\fR \fInorth\fR \fIeast\fR in memory.
-See \*(L"\s-1CACHE\*(R"\s0.
-.IP "\fB\-g\fR" 4
-.IX Item "-g"
-print the northerly and easterly gradients after the geoid height (i.e.,
-the rate at which the geoid height changes per unit distance along the
-\&\s-1WGS84\s0 ellipsoid in the specified directions).  As a result of the way
-that the geoid data is stored, the calculation of gradients can result
-in large quantization errors.  This is particularly acute at high
-latitudes and for the easterly gradient.  For this reason, the use of
-this option is \fB\s-1DEPRECATED\s0\fR.
+The first two arguments specify the \s-1SW\s0 corner of the cache and the last
+two arguments specify the \s-1NE\s0 corner.  The \fB\-w\fR flag specifies that
+longitude precedes latitude for these corners, provided that it appears
+before \fB\-c\fR.  See \*(L"\s-1CACHE\*(R"\s0.
+.IP "\fB\-w\fR" 4
+.IX Item "-w"
+when reading geographic coordinates, longitude precedes latitude (this
+can be overridden by a hemisphere designator, \fIN\fR, \fIS\fR, \fIE\fR, \fIW\fR).
 .IP "\fB\-z\fR" 4
 .IX Item "-z"
 prefix each line of input by \fIzone\fR, e.g., \f(CW\*(C`38n\*(C'\fR.  This should be used
diff --git a/man/GeoidEval.1.html b/man/GeoidEval.1.html
index 2331824..070e16c 100644
--- a/man/GeoidEval.1.html
+++ b/man/GeoidEval.1.html
@@ -17,7 +17,7 @@
 
 <h1 id="SYNOPSIS">SYNOPSIS</h1>
 
-<p><b>GeoidEval</b> [ <b>-n</b> <i>name</i> ] [ <b>-d</b> <i>dir</i> ] [ <b>-l</b> ] [ <b>-a</b> | <b>-c</b> <i>south</i> <i>west</i> <i>north</i> <i>east</i> ] [ <b>-g</b> ] [ <b>-z</b> <i>zone</i> ] [ <b>--msltohae</b> ] [ <b>--haetomsl</b> ] [ <b>-v</b> ] [ <b>--comment-delimiter</b> <i>commentdelim</i> ] [ <b>--version</b> | <b>-h</b> | <b>--help</b> ] [ <b>--input-file</b> <i>infile</i> | <b>--input-string</b> <i>instring</i> ] [ <b>--line-separator</b> <i>linesep</i> ] [ <b>--outpu [...]
+<p><b>GeoidEval</b> [ <b>-n</b> <i>name</i> ] [ <b>-d</b> <i>dir</i> ] [ <b>-l</b> ] [ <b>-a</b> | <b>-c</b> <i>south</i> <i>west</i> <i>north</i> <i>east</i> ] [ <b>-w</b> ] [ <b>-z</b> <i>zone</i> ] [ <b>--msltohae</b> ] [ <b>--haetomsl</b> ] [ <b>-v</b> ] [ <b>--comment-delimiter</b> <i>commentdelim</i> ] [ <b>--version</b> | <b>-h</b> | <b>--help</b> ] [ <b>--input-file</b> <i>infile</i> | <b>--input-string</b> <i>instring</i> ] [ <b>--line-separator</b> <i>linesep</i> ] [ <b>--outpu [...]
 
 <h1 id="DESCRIPTION">DESCRIPTION</h1>
 
@@ -66,13 +66,13 @@
 <dt id="c"><b>-c</b></dt>
 <dd>
 
-<p>cache the data bounded by <i>south</i> <i>west</i> <i>north</i> <i>east</i> in memory. See <a href="#CACHE">"CACHE"</a>.</p>
+<p>cache the data bounded by <i>south</i> <i>west</i> <i>north</i> <i>east</i> in memory. The first two arguments specify the SW corner of the cache and the last two arguments specify the NE corner. The <b>-w</b> flag specifies that longitude precedes latitude for these corners, provided that it appears before <b>-c</b>. See <a href="#CACHE">"CACHE"</a>.</p>
 
 </dd>
-<dt id="g"><b>-g</b></dt>
+<dt id="w"><b>-w</b></dt>
 <dd>
 
-<p>print the northerly and easterly gradients after the geoid height (i.e., the rate at which the geoid height changes per unit distance along the WGS84 ellipsoid in the specified directions). As a result of the way that the geoid data is stored, the calculation of gradients can result in large quantization errors. This is particularly acute at high latitudes and for the easterly gradient. For this reason, the use of this option is <b>DEPRECATED</b>.</p>
+<p>when reading geographic coordinates, longitude precedes latitude (this can be overridden by a hemisphere designator, <i>N</i>, <i>S</i>, <i>E</i>, <i>W</i>).</p>
 
 </dd>
 <dt id="z"><b>-z</b></dt>
diff --git a/man/GeoidEval.pod b/man/GeoidEval.pod
index 8af5a22..911307b 100644
--- a/man/GeoidEval.pod
+++ b/man/GeoidEval.pod
@@ -5,7 +5,7 @@ GeoidEval -- look up geoid heights
 =head1 SYNOPSIS
 
 B<GeoidEval> [ B<-n> I<name> ] [ B<-d> I<dir> ] [ B<-l> ]
-[ B<-a> | B<-c> I<south> I<west> I<north> I<east> ] [ B<-g> ]
+[ B<-a> | B<-c> I<south> I<west> I<north> I<east> ] [ B<-w> ]
 [ B<-z> I<zone> ] [ B<--msltohae> ] [ B<--haetomsl> ]
 [ B<-v> ]
 [ B<--comment-delimiter> I<commentdelim> ]
@@ -68,17 +68,15 @@ cache the entire data set in memory.  See L</CACHE>.
 =item B<-c>
 
 cache the data bounded by I<south> I<west> I<north> I<east> in memory.
-See L</CACHE>.
+The first two arguments specify the SW corner of the cache and the last
+two arguments specify the NE corner.  The B<-w> flag specifies that
+longitude precedes latitude for these corners, provided that it appears
+before B<-c>.  See L</CACHE>.
 
-=item B<-g>
+=item B<-w>
 
-print the northerly and easterly gradients after the geoid height (i.e.,
-the rate at which the geoid height changes per unit distance along the
-WGS84 ellipsoid in the specified directions).  As a result of the way
-that the geoid data is stored, the calculation of gradients can result
-in large quantization errors.  This is particularly acute at high
-latitudes and for the easterly gradient.  For this reason, the use of
-this option is B<DEPRECATED>.
+when reading geographic coordinates, longitude precedes latitude (this
+can be overridden by a hemisphere designator, I<N>, I<S>, I<E>, I<W>).
 
 =item B<-z>
 
diff --git a/man/GeoidEval.usage b/man/GeoidEval.usage
index 9a23d3c..d3bb615 100644
--- a/man/GeoidEval.usage
+++ b/man/GeoidEval.usage
@@ -2,7 +2,7 @@ int usage(int retval, bool brief) {
   if (brief)
     ( retval ? std::cerr : std::cout ) << "Usage:\n"
 "    GeoidEval [ -n name ] [ -d dir ] [ -l ] [ -a | -c south west north east\n"
-"    ] [ -g ] [ -z zone ] [ --msltohae ] [ --haetomsl ] [ -v ] [\n"
+"    ] [ -w ] [ -z zone ] [ --msltohae ] [ --haetomsl ] [ -v ] [\n"
 "    --comment-delimiter commentdelim ] [ --version | -h | --help ] [\n"
 "    --input-file infile | --input-string instring ] [ --line-separator\n"
 "    linesep ] [ --output-file outfile ]\n"
@@ -10,7 +10,7 @@ int usage(int retval, bool brief) {
 "For full documentation type:\n"
 "    GeoidEval --help\n"
 "or visit:\n"
-"    http://geographiclib.sf.net/1.43/GeoidEval.1.html\n";
+"    http://geographiclib.sf.net/1.44/GeoidEval.1.html\n";
   else
     ( retval ? std::cerr : std::cout ) << "Man page:\n"
 "NAME\n"
@@ -18,7 +18,7 @@ int usage(int retval, bool brief) {
 "\n"
 "SYNOPSIS\n"
 "       GeoidEval [ -n name ] [ -d dir ] [ -l ] [ -a | -c south west north east\n"
-"       ] [ -g ] [ -z zone ] [ --msltohae ] [ --haetomsl ] [ -v ] [\n"
+"       ] [ -w ] [ -z zone ] [ --msltohae ] [ --haetomsl ] [ -v ] [\n"
 "       --comment-delimiter commentdelim ] [ --version | -h | --help ] [\n"
 "       --input-file infile | --input-string instring ] [ --line-separator\n"
 "       linesep ] [ --output-file outfile ]\n"
@@ -55,16 +55,14 @@ int usage(int retval, bool brief) {
 "\n"
 "       -a  cache the entire data set in memory.  See \"CACHE\".\n"
 "\n"
-"       -c  cache the data bounded by south west north east in memory.  See\n"
-"           \"CACHE\".\n"
+"       -c  cache the data bounded by south west north east in memory.  The\n"
+"           first two arguments specify the SW corner of the cache and the last\n"
+"           two arguments specify the NE corner.  The -w flag specifies that\n"
+"           longitude precedes latitude for these corners, provided that it\n"
+"           appears before -c.  See \"CACHE\".\n"
 "\n"
-"       -g  print the northerly and easterly gradients after the geoid height\n"
-"           (i.e., the rate at which the geoid height changes per unit distance\n"
-"           along the WGS84 ellipsoid in the specified directions).  As a\n"
-"           result of the way that the geoid data is stored, the calculation of\n"
-"           gradients can result in large quantization errors.  This is\n"
-"           particularly acute at high latitudes and for the easterly gradient.\n"
-"           For this reason, the use of this option is DEPRECATED.\n"
+"       -w  when reading geographic coordinates, longitude precedes latitude\n"
+"           (this can be overridden by a hemisphere designator, N, S, E, W).\n"
 "\n"
 "       -z  prefix each line of input by zone, e.g., \"38n\".  This should be\n"
 "           used when the input consists of UTM/UPS eastings and northings.\n"
diff --git a/man/Gravity.1 b/man/Gravity.1
index 83d2154..f52ff8d 100644
--- a/man/Gravity.1
+++ b/man/Gravity.1
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "GRAVITY 1"
-.TH GRAVITY 1 "2015-05-22" "GeographicLib 1.43" "GeographicLib Utilities"
+.TH GRAVITY 1 "2015-08-14" "GeographicLib 1.44" "GeographicLib Utilities"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
@@ -144,7 +144,7 @@ Gravity \-\- compute the earth's gravity field
 .IX Header "SYNOPSIS"
 \&\fBGravity\fR [ \fB\-n\fR \fIname\fR ] [ \fB\-d\fR \fIdir\fR ]
 [ \fB\-G\fR | \fB\-D\fR | \fB\-A\fR | \fB\-H\fR ] [ \fB\-c\fR \fIlat\fR \fIh\fR ]
-[ \fB\-p\fR \fIprec\fR ]
+[ \fB\-w\fR ] [ \fB\-p\fR \fIprec\fR ]
 [ \fB\-v\fR ]
 [ \fB\-\-comment\-delimiter\fR \fIcommentdelim\fR ]
 [ \fB\-\-version\fR | \fB\-h\fR | \fB\-\-help\fR ]
@@ -158,13 +158,14 @@ gravitational field on standard output.
 .PP
 The input line is of the form \fIlat\fR \fIlon\fR \fIh\fR.  \fIlat\fR and \fIlon\fR are
 the latitude and longitude expressed as decimal degrees or degrees,
-minutes, and seconds; see \fIGeoConvert\fR\|(1) for details.  \fIh\fR is the height
-above the ellipsoid in meters; this quantity is optional and defaults to
-0.  Alternatively, the gravity field can be computed at various points
-on a circle of latitude (constant \fIlat\fR and \fIh\fR) via the \fB\-c\fR option;
-in this case only the longitude should be given on the input lines.  The
-quantities printed out are governed by the \fB\-G\fR (default), \fB\-D\fR,
-\&\fB\-A\fR, or \fB\-H\fR options.
+minutes, and seconds; for details on the allowed formats for latitude
+and longitude, see the \f(CW\*(C`GEOGRAPHIC COORDINATES\*(C'\fR section of
+\&\fIGeoConvert\fR\|(1).  \fIh\fR is the height above the ellipsoid in meters; this
+quantity is optional and defaults to 0.  Alternatively, the gravity
+field can be computed at various points on a circle of latitude
+(constant \fIlat\fR and \fIh\fR) via the \fB\-c\fR option; in this case only the
+longitude should be given on the input lines.  The quantities printed
+out are governed by the \fB\-G\fR (default), \fB\-D\fR, \fB\-A\fR, or \fB\-H\fR options.
 .PP
 All the supported gravity models, except for grs80, use \s-1WGS84\s0 as the
 reference ellipsoid \fIa\fR = 6378137 m, \fIf\fR = 1/298.257223563, \fIomega\fR =
@@ -220,6 +221,11 @@ evaluate the field on a circle of latitude given by \fIlat\fR and \fIh\fR
 instead of reading these quantities from the input lines.  In this case,
 \&\fBGravity\fR can calculate the field considerably more quickly.  If geoid
 heights are being computed (the \fB\-H\fR option), then \fIh\fR must be zero.
+.IP "\fB\-w\fR" 4
+.IX Item "-w"
+on input and output, longitude precedes latitude (except that on input
+this can be overridden by a hemisphere designator, \fIN\fR, \fIS\fR, \fIE\fR,
+\&\fIW\fR).
 .IP "\fB\-p\fR" 4
 .IX Item "-p"
 set the output precision to \fIprec\fR.  By default \fIprec\fR is 5 for
diff --git a/man/Gravity.1.html b/man/Gravity.1.html
index aaac062..3b30e47 100644
--- a/man/Gravity.1.html
+++ b/man/Gravity.1.html
@@ -17,13 +17,13 @@
 
 <h1 id="SYNOPSIS">SYNOPSIS</h1>
 
-<p><b>Gravity</b> [ <b>-n</b> <i>name</i> ] [ <b>-d</b> <i>dir</i> ] [ <b>-G</b> | <b>-D</b> | <b>-A</b> | <b>-H</b> ] [ <b>-c</b> <i>lat</i> <i>h</i> ] [ <b>-p</b> <i>prec</i> ] [ <b>-v</b> ] [ <b>--comment-delimiter</b> <i>commentdelim</i> ] [ <b>--version</b> | <b>-h</b> | <b>--help</b> ] [ <b>--input-file</b> <i>infile</i> | <b>--input-string</b> <i>instring</i> ] [ <b>--line-separator</b> <i>linesep</i> ] [ <b>--output-file</b> <i>outfile</i> ]</p>
+<p><b>Gravity</b> [ <b>-n</b> <i>name</i> ] [ <b>-d</b> <i>dir</i> ] [ <b>-G</b> | <b>-D</b> | <b>-A</b> | <b>-H</b> ] [ <b>-c</b> <i>lat</i> <i>h</i> ] [ <b>-w</b> ] [ <b>-p</b> <i>prec</i> ] [ <b>-v</b> ] [ <b>--comment-delimiter</b> <i>commentdelim</i> ] [ <b>--version</b> | <b>-h</b> | <b>--help</b> ] [ <b>--input-file</b> <i>infile</i> | <b>--input-string</b> <i>instring</i> ] [ <b>--line-separator</b> <i>linesep</i> ] [ <b>--output-file</b> <i>outfile</i> ]</p>
 
 <h1 id="DESCRIPTION">DESCRIPTION</h1>
 
 <p><b>Gravity</b> reads in positions on standard input and prints out the gravitational field on standard output.</p>
 
-<p>The input line is of the form <i>lat</i> <i>lon</i> <i>h</i>. <i>lat</i> and <i>lon</i> are the latitude and longitude expressed as decimal degrees or degrees, minutes, and seconds; see GeoConvert(1) for details. <i>h</i> is the height above the ellipsoid in meters; this quantity is optional and defaults to 0. Alternatively, the gravity field can be computed at various points on a circle of latitude (constant <i>lat</i> and <i>h</i>) via the <b>-c</b> option; in this case only the lon [...]
+<p>The input line is of the form <i>lat</i> <i>lon</i> <i>h</i>. <i>lat</i> and <i>lon</i> are the latitude and longitude expressed as decimal degrees or degrees, minutes, and seconds; for details on the allowed formats for latitude and longitude, see the <code>GEOGRAPHIC COORDINATES</code> section of GeoConvert(1). <i>h</i> is the height above the ellipsoid in meters; this quantity is optional and defaults to 0. Alternatively, the gravity field can be computed at various points on a cir [...]
 
 <p>All the supported gravity models, except for grs80, use WGS84 as the reference ellipsoid <i>a</i> = 6378137 m, <i>f</i> = 1/298.257223563, <i>omega</i> = 7292115e-11 rad/s, and <i>GM</i> = 3986004.418e8 m^3/s^2.</p>
 
@@ -73,6 +73,12 @@
 <p>evaluate the field on a circle of latitude given by <i>lat</i> and <i>h</i> instead of reading these quantities from the input lines. In this case, <b>Gravity</b> can calculate the field considerably more quickly. If geoid heights are being computed (the <b>-H</b> option), then <i>h</i> must be zero.</p>
 
 </dd>
+<dt id="w"><b>-w</b></dt>
+<dd>
+
+<p>on input and output, longitude precedes latitude (except that on input this can be overridden by a hemisphere designator, <i>N</i>, <i>S</i>, <i>E</i>, <i>W</i>).</p>
+
+</dd>
 <dt id="p"><b>-p</b></dt>
 <dd>
 
diff --git a/man/Gravity.pod b/man/Gravity.pod
index b2d71da..8b1d489 100644
--- a/man/Gravity.pod
+++ b/man/Gravity.pod
@@ -6,7 +6,7 @@ Gravity -- compute the earth's gravity field
 
 B<Gravity> [ B<-n> I<name> ] [ B<-d> I<dir> ]
 [ B<-G> | B<-D> | B<-A> | B<-H> ] [ B<-c> I<lat> I<h> ]
-[ B<-p> I<prec> ]
+[ B<-w> ] [ B<-p> I<prec> ]
 [ B<-v> ]
 [ B<--comment-delimiter> I<commentdelim> ]
 [ B<--version> | B<-h> | B<--help> ]
@@ -21,13 +21,14 @@ gravitational field on standard output.
 
 The input line is of the form I<lat> I<lon> I<h>.  I<lat> and I<lon> are
 the latitude and longitude expressed as decimal degrees or degrees,
-minutes, and seconds; see GeoConvert(1) for details.  I<h> is the height
-above the ellipsoid in meters; this quantity is optional and defaults to
-0.  Alternatively, the gravity field can be computed at various points
-on a circle of latitude (constant I<lat> and I<h>) via the B<-c> option;
-in this case only the longitude should be given on the input lines.  The
-quantities printed out are governed by the B<-G> (default), B<-D>,
-B<-A>, or B<-H> options.
+minutes, and seconds; for details on the allowed formats for latitude
+and longitude, see the C<GEOGRAPHIC COORDINATES> section of
+GeoConvert(1).  I<h> is the height above the ellipsoid in meters; this
+quantity is optional and defaults to 0.  Alternatively, the gravity
+field can be computed at various points on a circle of latitude
+(constant I<lat> and I<h>) via the B<-c> option; in this case only the
+longitude should be given on the input lines.  The quantities printed
+out are governed by the B<-G> (default), B<-D>, B<-A>, or B<-H> options.
 
 All the supported gravity models, except for grs80, use WGS84 as the
 reference ellipsoid I<a> = 6378137 m, I<f> = 1/298.257223563, I<omega> =
@@ -93,6 +94,12 @@ instead of reading these quantities from the input lines.  In this case,
 B<Gravity> can calculate the field considerably more quickly.  If geoid
 heights are being computed (the B<-H> option), then I<h> must be zero.
 
+=item B<-w>
+
+on input and output, longitude precedes latitude (except that on input
+this can be overridden by a hemisphere designator, I<N>, I<S>, I<E>,
+I<W>).
+
 =item B<-p>
 
 set the output precision to I<prec>.  By default I<prec> is 5 for
diff --git a/man/Gravity.usage b/man/Gravity.usage
index cc706a2..d235042 100644
--- a/man/Gravity.usage
+++ b/man/Gravity.usage
@@ -1,24 +1,24 @@
 int usage(int retval, bool brief) {
   if (brief)
     ( retval ? std::cerr : std::cout ) << "Usage:\n"
-"    Gravity [ -n name ] [ -d dir ] [ -G | -D | -A | -H ] [ -c lat h ] [ -p\n"
-"    prec ] [ -v ] [ --comment-delimiter commentdelim ] [ --version | -h |\n"
-"    --help ] [ --input-file infile | --input-string instring ] [\n"
+"    Gravity [ -n name ] [ -d dir ] [ -G | -D | -A | -H ] [ -c lat h ] [ -w\n"
+"    ] [ -p prec ] [ -v ] [ --comment-delimiter commentdelim ] [ --version |\n"
+"    -h | --help ] [ --input-file infile | --input-string instring ] [\n"
 "    --line-separator linesep ] [ --output-file outfile ]\n"
 "\n"
 "For full documentation type:\n"
 "    Gravity --help\n"
 "or visit:\n"
-"    http://geographiclib.sf.net/1.43/Gravity.1.html\n";
+"    http://geographiclib.sf.net/1.44/Gravity.1.html\n";
   else
     ( retval ? std::cerr : std::cout ) << "Man page:\n"
 "NAME\n"
 "       Gravity -- compute the earth's gravity field\n"
 "\n"
 "SYNOPSIS\n"
-"       Gravity [ -n name ] [ -d dir ] [ -G | -D | -A | -H ] [ -c lat h ] [ -p\n"
-"       prec ] [ -v ] [ --comment-delimiter commentdelim ] [ --version | -h |\n"
-"       --help ] [ --input-file infile | --input-string instring ] [\n"
+"       Gravity [ -n name ] [ -d dir ] [ -G | -D | -A | -H ] [ -c lat h ] [ -w\n"
+"       ] [ -p prec ] [ -v ] [ --comment-delimiter commentdelim ] [ --version |\n"
+"       -h | --help ] [ --input-file infile | --input-string instring ] [\n"
 "       --line-separator linesep ] [ --output-file outfile ]\n"
 "\n"
 "DESCRIPTION\n"
@@ -27,12 +27,14 @@ int usage(int retval, bool brief) {
 "\n"
 "       The input line is of the form lat lon h.  lat and lon are the latitude\n"
 "       and longitude expressed as decimal degrees or degrees, minutes, and\n"
-"       seconds; see GeoConvert(1) for details.  h is the height above the\n"
-"       ellipsoid in meters; this quantity is optional and defaults to 0.\n"
-"       Alternatively, the gravity field can be computed at various points on a\n"
-"       circle of latitude (constant lat and h) via the -c option; in this case\n"
-"       only the longitude should be given on the input lines.  The quantities\n"
-"       printed out are governed by the -G (default), -D, -A, or -H options.\n"
+"       seconds; for details on the allowed formats for latitude and longitude,\n"
+"       see the \"GEOGRAPHIC COORDINATES\" section of GeoConvert(1).  h is the\n"
+"       height above the ellipsoid in meters; this quantity is optional and\n"
+"       defaults to 0.  Alternatively, the gravity field can be computed at\n"
+"       various points on a circle of latitude (constant lat and h) via the -c\n"
+"       option; in this case only the longitude should be given on the input\n"
+"       lines.  The quantities printed out are governed by the -G (default),\n"
+"       -D, -A, or -H options.\n"
 "\n"
 "       All the supported gravity models, except for grs80, use WGS84 as the\n"
 "       reference ellipsoid a = 6378137 m, f = 1/298.257223563, omega =\n"
@@ -81,6 +83,10 @@ int usage(int retval, bool brief) {
 "           If geoid heights are being computed (the -H option), then h must be\n"
 "           zero.\n"
 "\n"
+"       -w  on input and output, longitude precedes latitude (except that on\n"
+"           input this can be overridden by a hemisphere designator, N, S, E,\n"
+"           W).\n"
+"\n"
 "       -p  set the output precision to prec.  By default prec is 5 for\n"
 "           acceleration due to gravity, 3 for the gravity disturbance and\n"
 "           anomaly, and 4 for the geoid height.\n"
diff --git a/man/MagneticField.1 b/man/MagneticField.1
index 7196da5..134f87a 100644
--- a/man/MagneticField.1
+++ b/man/MagneticField.1
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "MAGNETICFIELD 1"
-.TH MAGNETICFIELD 1 "2015-05-22" "GeographicLib 1.43" "GeographicLib Utilities"
+.TH MAGNETICFIELD 1 "2015-08-14" "GeographicLib 1.44" "GeographicLib Utilities"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
@@ -144,7 +144,7 @@ MagneticField \-\- compute the earth's magnetic field
 .IX Header "SYNOPSIS"
 \&\fBMagneticField\fR [ \fB\-n\fR \fIname\fR ] [ \fB\-d\fR \fIdir\fR ]
 [ \fB\-t\fR \fItime\fR | \fB\-c\fR \fItime\fR \fIlat\fR \fIh\fR ]
-[ \fB\-r\fR ] [ \fB\-T\fR \fItguard\fR ] [ \fB\-H\fR \fIhguard\fR ] [ \fB\-p\fR \fIprec\fR ]
+[ \fB\-r\fR ] [ \fB\-w\fR ] [ \fB\-T\fR \fItguard\fR ] [ \fB\-H\fR \fIhguard\fR ] [ \fB\-p\fR \fIprec\fR ]
 [ \fB\-v\fR ]
 [ \fB\-\-comment\-delimiter\fR \fIcommentdelim\fR ]
 [ \fB\-\-version\fR | \fB\-h\fR | \fB\-\-help\fR ]
@@ -160,14 +160,16 @@ rate of change.
 The input line is of the form \fItime\fR \fIlat\fR \fIlon\fR \fIh\fR. \fItime\fR is a
 date of the form 2012\-07\-03, a fractional year such as 2012.5, or the
 string \*(L"now\*(R".  \fIlat\fR and \fIlon\fR are the latitude and longitude
-expressed as decimal degrees or degrees, minutes, and seconds; see
-\&\fIGeoConvert\fR\|(1) for details.  \fIh\fR is the height above the ellipsoid in
-meters; this is optional and defaults to zero.  Alternatively, \fItime\fR
-can be given on the command line as the argument to the \fB\-t\fR option, in
-which case it should not be included on the input lines.  Finally, the
-magnetic field can be computed at various points on a circle of latitude
-(constant \fItime\fR, \fIlat\fR, and \fIh\fR) via the \fB\-c\fR option; in this case
-only the longitude should be given on the input lines.
+expressed as decimal degrees or degrees, minutes, and seconds; for
+details on the allowed formats for latitude and longitude, see the
+\&\f(CW\*(C`GEOGRAPHIC COORDINATES\*(C'\fR section of \fIGeoConvert\fR\|(1).  \fIh\fR is the height
+above the ellipsoid in meters; this is optional and defaults to zero.
+Alternatively, \fItime\fR can be given on the command line as the argument
+to the \fB\-t\fR option, in which case it should not be included on the
+input lines.  Finally, the magnetic field can be computed at various
+points on a circle of latitude (constant \fItime\fR, \fIlat\fR, and \fIh\fR) via
+the \fB\-c\fR option; in this case only the longitude should be given on the
+input lines.
 .PP
 The output consists of the following 7 items:
 .PP
@@ -210,6 +212,11 @@ quickly.
 .IP "\fB\-r\fR" 4
 .IX Item "-r"
 toggle whether to report the rates of change of the field.
+.IP "\fB\-w\fR" 4
+.IX Item "-w"
+on input and output, longitude precedes latitude (except that on input
+this can be overridden by a hemisphere designator, \fIN\fR, \fIS\fR, \fIE\fR,
+\&\fIW\fR).
 .IP "\fB\-T\fR" 4
 .IX Item "-T"
 signal an error if \fItime\fR lies \fItguard\fR years (default 50 yr) beyond
diff --git a/man/MagneticField.1.html b/man/MagneticField.1.html
index 9f3bb6d..1b188c9 100644
--- a/man/MagneticField.1.html
+++ b/man/MagneticField.1.html
@@ -17,13 +17,13 @@
 
 <h1 id="SYNOPSIS">SYNOPSIS</h1>
 
-<p><b>MagneticField</b> [ <b>-n</b> <i>name</i> ] [ <b>-d</b> <i>dir</i> ] [ <b>-t</b> <i>time</i> | <b>-c</b> <i>time</i> <i>lat</i> <i>h</i> ] [ <b>-r</b> ] [ <b>-T</b> <i>tguard</i> ] [ <b>-H</b> <i>hguard</i> ] [ <b>-p</b> <i>prec</i> ] [ <b>-v</b> ] [ <b>--comment-delimiter</b> <i>commentdelim</i> ] [ <b>--version</b> | <b>-h</b> | <b>--help</b> ] [ <b>--input-file</b> <i>infile</i> | <b>--input-string</b> <i>instring</i> ] [ <b>--line-separator</b> <i>linesep</i> ] [ <b>--output-fi [...]
+<p><b>MagneticField</b> [ <b>-n</b> <i>name</i> ] [ <b>-d</b> <i>dir</i> ] [ <b>-t</b> <i>time</i> | <b>-c</b> <i>time</i> <i>lat</i> <i>h</i> ] [ <b>-r</b> ] [ <b>-w</b> ] [ <b>-T</b> <i>tguard</i> ] [ <b>-H</b> <i>hguard</i> ] [ <b>-p</b> <i>prec</i> ] [ <b>-v</b> ] [ <b>--comment-delimiter</b> <i>commentdelim</i> ] [ <b>--version</b> | <b>-h</b> | <b>--help</b> ] [ <b>--input-file</b> <i>infile</i> | <b>--input-string</b> <i>instring</i> ] [ <b>--line-separator</b> <i>linesep</i> ] [  [...]
 
 <h1 id="DESCRIPTION">DESCRIPTION</h1>
 
 <p><b>MagneticField</b> reads in times and positions on standard input and prints out the geomagnetic field on standard output and, optionally, its rate of change.</p>
 
-<p>The input line is of the form <i>time</i> <i>lat</i> <i>lon</i> <i>h</i>. <i>time</i> is a date of the form 2012-07-03, a fractional year such as 2012.5, or the string "now". <i>lat</i> and <i>lon</i> are the latitude and longitude expressed as decimal degrees or degrees, minutes, and seconds; see GeoConvert(1) for details. <i>h</i> is the height above the ellipsoid in meters; this is optional and defaults to zero. Alternatively, <i>time</i> can be given on the command line  [...]
+<p>The input line is of the form <i>time</i> <i>lat</i> <i>lon</i> <i>h</i>. <i>time</i> is a date of the form 2012-07-03, a fractional year such as 2012.5, or the string "now". <i>lat</i> and <i>lon</i> are the latitude and longitude expressed as decimal degrees or degrees, minutes, and seconds; for details on the allowed formats for latitude and longitude, see the <code>GEOGRAPHIC COORDINATES</code> section of GeoConvert(1). <i>h</i> is the height above the ellipsoid in meter [...]
 
 <p>The output consists of the following 7 items:</p>
 
@@ -75,6 +75,12 @@
 <p>toggle whether to report the rates of change of the field.</p>
 
 </dd>
+<dt id="w"><b>-w</b></dt>
+<dd>
+
+<p>on input and output, longitude precedes latitude (except that on input this can be overridden by a hemisphere designator, <i>N</i>, <i>S</i>, <i>E</i>, <i>W</i>).</p>
+
+</dd>
 <dt id="T"><b>-T</b></dt>
 <dd>
 
diff --git a/man/MagneticField.pod b/man/MagneticField.pod
index 9af0d85..7b2e5bc 100644
--- a/man/MagneticField.pod
+++ b/man/MagneticField.pod
@@ -6,7 +6,7 @@ MagneticField -- compute the earth's magnetic field
 
 B<MagneticField> [ B<-n> I<name> ] [ B<-d> I<dir> ]
 [ B<-t> I<time> | B<-c> I<time> I<lat> I<h> ]
-[ B<-r> ] [ B<-T> I<tguard> ] [ B<-H> I<hguard> ] [ B<-p> I<prec> ]
+[ B<-r> ] [ B<-w> ] [ B<-T> I<tguard> ] [ B<-H> I<hguard> ] [ B<-p> I<prec> ]
 [ B<-v> ]
 [ B<--comment-delimiter> I<commentdelim> ]
 [ B<--version> | B<-h> | B<--help> ]
@@ -23,14 +23,16 @@ rate of change.
 The input line is of the form I<time> I<lat> I<lon> I<h>. I<time> is a
 date of the form 2012-07-03, a fractional year such as 2012.5, or the
 string "now".  I<lat> and I<lon> are the latitude and longitude
-expressed as decimal degrees or degrees, minutes, and seconds; see
-GeoConvert(1) for details.  I<h> is the height above the ellipsoid in
-meters; this is optional and defaults to zero.  Alternatively, I<time>
-can be given on the command line as the argument to the B<-t> option, in
-which case it should not be included on the input lines.  Finally, the
-magnetic field can be computed at various points on a circle of latitude
-(constant I<time>, I<lat>, and I<h>) via the B<-c> option; in this case
-only the longitude should be given on the input lines.
+expressed as decimal degrees or degrees, minutes, and seconds; for
+details on the allowed formats for latitude and longitude, see the
+C<GEOGRAPHIC COORDINATES> section of GeoConvert(1).  I<h> is the height
+above the ellipsoid in meters; this is optional and defaults to zero.
+Alternatively, I<time> can be given on the command line as the argument
+to the B<-t> option, in which case it should not be included on the
+input lines.  Finally, the magnetic field can be computed at various
+points on a circle of latitude (constant I<time>, I<lat>, and I<h>) via
+the B<-c> option; in this case only the longitude should be given on the
+input lines.
 
 The output consists of the following 7 items:
 
@@ -79,6 +81,12 @@ quickly.
 
 toggle whether to report the rates of change of the field.
 
+=item B<-w>
+
+on input and output, longitude precedes latitude (except that on input
+this can be overridden by a hemisphere designator, I<N>, I<S>, I<E>,
+I<W>).
+
 =item B<-T>
 
 signal an error if I<time> lies I<tguard> years (default 50 yr) beyond
diff --git a/man/MagneticField.usage b/man/MagneticField.usage
index 2eaa1c7..cc9a189 100644
--- a/man/MagneticField.usage
+++ b/man/MagneticField.usage
@@ -2,15 +2,15 @@ int usage(int retval, bool brief) {
   if (brief)
     ( retval ? std::cerr : std::cout ) << "Usage:\n"
 "    MagneticField [ -n name ] [ -d dir ] [ -t time | -c time lat h ] [ -r ]\n"
-"    [ -T tguard ] [ -H hguard ] [ -p prec ] [ -v ] [ --comment-delimiter\n"
-"    commentdelim ] [ --version | -h | --help ] [ --input-file infile |\n"
-"    --input-string instring ] [ --line-separator linesep ] [ --output-file\n"
-"    outfile ]\n"
+"    [ -w ] [ -T tguard ] [ -H hguard ] [ -p prec ] [ -v ] [\n"
+"    --comment-delimiter commentdelim ] [ --version | -h | --help ] [\n"
+"    --input-file infile | --input-string instring ] [ --line-separator\n"
+"    linesep ] [ --output-file outfile ]\n"
 "\n"
 "For full documentation type:\n"
 "    MagneticField --help\n"
 "or visit:\n"
-"    http://geographiclib.sf.net/1.43/MagneticField.1.html\n";
+"    http://geographiclib.sf.net/1.44/MagneticField.1.html\n";
   else
     ( retval ? std::cerr : std::cout ) << "Man page:\n"
 "NAME\n"
@@ -18,10 +18,10 @@ int usage(int retval, bool brief) {
 "\n"
 "SYNOPSIS\n"
 "       MagneticField [ -n name ] [ -d dir ] [ -t time | -c time lat h ] [ -r ]\n"
-"       [ -T tguard ] [ -H hguard ] [ -p prec ] [ -v ] [ --comment-delimiter\n"
-"       commentdelim ] [ --version | -h | --help ] [ --input-file infile |\n"
-"       --input-string instring ] [ --line-separator linesep ] [ --output-file\n"
-"       outfile ]\n"
+"       [ -w ] [ -T tguard ] [ -H hguard ] [ -p prec ] [ -v ] [\n"
+"       --comment-delimiter commentdelim ] [ --version | -h | --help ] [\n"
+"       --input-file infile | --input-string instring ] [ --line-separator\n"
+"       linesep ] [ --output-file outfile ]\n"
 "\n"
 "DESCRIPTION\n"
 "       MagneticField reads in times and positions on standard input and prints\n"
@@ -31,14 +31,15 @@ int usage(int retval, bool brief) {
 "       The input line is of the form time lat lon h. time is a date of the\n"
 "       form 2012-07-03, a fractional year such as 2012.5, or the string \"now\".\n"
 "       lat and lon are the latitude and longitude expressed as decimal degrees\n"
-"       or degrees, minutes, and seconds; see GeoConvert(1) for details.  h is\n"
-"       the height above the ellipsoid in meters; this is optional and defaults\n"
-"       to zero.  Alternatively, time can be given on the command line as the\n"
-"       argument to the -t option, in which case it should not be included on\n"
-"       the input lines.  Finally, the magnetic field can be computed at\n"
-"       various points on a circle of latitude (constant time, lat, and h) via\n"
-"       the -c option; in this case only the longitude should be given on the\n"
-"       input lines.\n"
+"       or degrees, minutes, and seconds; for details on the allowed formats\n"
+"       for latitude and longitude, see the \"GEOGRAPHIC COORDINATES\" section of\n"
+"       GeoConvert(1).  h is the height above the ellipsoid in meters; this is\n"
+"       optional and defaults to zero.  Alternatively, time can be given on the\n"
+"       command line as the argument to the -t option, in which case it should\n"
+"       not be included on the input lines.  Finally, the magnetic field can be\n"
+"       computed at various points on a circle of latitude (constant time, lat,\n"
+"       and h) via the -c option; in this case only the longitude should be\n"
+"       given on the input lines.\n"
 "\n"
 "       The output consists of the following 7 items:\n"
 "\n"
@@ -74,6 +75,10 @@ int usage(int retval, bool brief) {
 "\n"
 "       -r  toggle whether to report the rates of change of the field.\n"
 "\n"
+"       -w  on input and output, longitude precedes latitude (except that on\n"
+"           input this can be overridden by a hemisphere designator, N, S, E,\n"
+"           W).\n"
+"\n"
 "       -T  signal an error if time lies tguard years (default 50 yr) beyond\n"
 "           the range for the model.\n"
 "\n"
diff --git a/man/Planimeter.1 b/man/Planimeter.1
index 9b8b209..a47af16 100644
--- a/man/Planimeter.1
+++ b/man/Planimeter.1
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "PLANIMETER 1"
-.TH PLANIMETER 1 "2015-05-22" "GeographicLib 1.43" "GeographicLib Utilities"
+.TH PLANIMETER 1 "2015-08-14" "GeographicLib 1.44" "GeographicLib Utilities"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
@@ -143,7 +143,7 @@ Planimeter \-\- compute the area of geodesic polygons
 .SH "SYNOPSIS"
 .IX Header "SYNOPSIS"
 \&\fBPlanimeter\fR [ \fB\-r\fR ] [ \fB\-s\fR ] [ \fB\-l\fR ] [ \fB\-e\fR \fIa\fR \fIf\fR ]
-[ \fB\-p\fR \fIprec\fR ] [ \fB\-G\fR | \fB\-E\fR | \fB\-Q\fR | \fB\-R\fR ]
+[ \fB\-w\fR ] [ \fB\-p\fR \fIprec\fR ] [ \fB\-G\fR | \fB\-E\fR | \fB\-Q\fR | \fB\-R\fR ]
 [ \fB\-\-comment\-delimiter\fR \fIcommentdelim\fR ]
 [ \fB\-\-version\fR | \fB\-h\fR | \fB\-\-help\fR ]
 [ \fB\-\-input\-file\fR \fIinfile\fR | \fB\-\-input\-string\fR \fIinstring\fR ]
@@ -212,6 +212,10 @@ is allowed for \fIf\fR.  (Also, if \fIf\fR > 1, the flattening is set to
 \&\fIf\fR = 1/298.257223563.  If entering vertices as \s-1UTM/UPS\s0 or \s-1MGRS\s0
 coordinates, use the default ellipsoid, since the conversion of these
 coordinates to latitude and longitude always uses the \s-1WGS84\s0 parameters.
+.IP "\fB\-w\fR" 4
+.IX Item "-w"
+when reading geographic coordinates, longitude precedes latitude (this
+can be overridden by a hemisphere designator, \fIN\fR, \fIS\fR, \fIE\fR, \fIW\fR).
 .IP "\fB\-p\fR" 4
 .IX Item "-p"
 set the output precision to \fIprec\fR (default 6); the perimeter is given
diff --git a/man/Planimeter.1.html b/man/Planimeter.1.html
index f2abae2..3cb3c25 100644
--- a/man/Planimeter.1.html
+++ b/man/Planimeter.1.html
@@ -17,7 +17,7 @@
 
 <h1 id="SYNOPSIS">SYNOPSIS</h1>
 
-<p><b>Planimeter</b> [ <b>-r</b> ] [ <b>-s</b> ] [ <b>-l</b> ] [ <b>-e</b> <i>a</i> <i>f</i> ] [ <b>-p</b> <i>prec</i> ] [ <b>-G</b> | <b>-E</b> | <b>-Q</b> | <b>-R</b> ] [ <b>--comment-delimiter</b> <i>commentdelim</i> ] [ <b>--version</b> | <b>-h</b> | <b>--help</b> ] [ <b>--input-file</b> <i>infile</i> | <b>--input-string</b> <i>instring</i> ] [ <b>--line-separator</b> <i>linesep</i> ] [ <b>--output-file</b> <i>outfile</i> ]</p>
+<p><b>Planimeter</b> [ <b>-r</b> ] [ <b>-s</b> ] [ <b>-l</b> ] [ <b>-e</b> <i>a</i> <i>f</i> ] [ <b>-w</b> ] [ <b>-p</b> <i>prec</i> ] [ <b>-G</b> | <b>-E</b> | <b>-Q</b> | <b>-R</b> ] [ <b>--comment-delimiter</b> <i>commentdelim</i> ] [ <b>--version</b> | <b>-h</b> | <b>--help</b> ] [ <b>--input-file</b> <i>infile</i> | <b>--input-string</b> <i>instring</i> ] [ <b>--line-separator</b> <i>linesep</i> ] [ <b>--output-file</b> <i>outfile</i> ]</p>
 
 <h1 id="DESCRIPTION">DESCRIPTION</h1>
 
@@ -59,6 +59,12 @@
 <p>specify the ellipsoid via <i>a</i> <i>f</i>; the equatorial radius is <i>a</i> and the flattening is <i>f</i>. Setting <i>f</i> = 0 results in a sphere. Specify <i>f</i> < 0 for a prolate ellipsoid. A simple fraction, e.g., 1/297, is allowed for <i>f</i>. (Also, if <i>f</i> > 1, the flattening is set to 1/<i>f</i>.) By default, the WGS84 ellipsoid is used, <i>a</i> = 6378137 m, <i>f</i> = 1/298.257223563. If entering vertices as UTM/UPS or MGRS coordinates, use the default ellip [...]
 
 </dd>
+<dt id="w"><b>-w</b></dt>
+<dd>
+
+<p>when reading geographic coordinates, longitude precedes latitude (this can be overridden by a hemisphere designator, <i>N</i>, <i>S</i>, <i>E</i>, <i>W</i>).</p>
+
+</dd>
 <dt id="p"><b>-p</b></dt>
 <dd>
 
diff --git a/man/Planimeter.pod b/man/Planimeter.pod
index 789a984..4e01d03 100644
--- a/man/Planimeter.pod
+++ b/man/Planimeter.pod
@@ -5,7 +5,7 @@ Planimeter -- compute the area of geodesic polygons
 =head1 SYNOPSIS
 
 B<Planimeter> [ B<-r> ] [ B<-s> ] [ B<-l> ] [ B<-e> I<a> I<f> ]
-[ B<-p> I<prec> ] [ B<-G> | B<-E> | B<-Q> | B<-R> ]
+[ B<-w> ] [ B<-p> I<prec> ] [ B<-G> | B<-E> | B<-Q> | B<-R> ]
 [ B<--comment-delimiter> I<commentdelim> ]
 [ B<--version> | B<-h> | B<--help> ]
 [ B<--input-file> I<infile> | B<--input-string> I<instring> ]
@@ -82,6 +82,11 @@ I<f> = 1/298.257223563.  If entering vertices as UTM/UPS or MGRS
 coordinates, use the default ellipsoid, since the conversion of these
 coordinates to latitude and longitude always uses the WGS84 parameters.
 
+=item B<-w>
+
+when reading geographic coordinates, longitude precedes latitude (this
+can be overridden by a hemisphere designator, I<N>, I<S>, I<E>, I<W>).
+
 =item B<-p>
 
 set the output precision to I<prec> (default 6); the perimeter is given
diff --git a/man/Planimeter.usage b/man/Planimeter.usage
index 2422ee0..c51982d 100644
--- a/man/Planimeter.usage
+++ b/man/Planimeter.usage
@@ -1,25 +1,25 @@
 int usage(int retval, bool brief) {
   if (brief)
     ( retval ? std::cerr : std::cout ) << "Usage:\n"
-"    Planimeter [ -r ] [ -s ] [ -l ] [ -e a f ] [ -p prec ] [ -G | -E | -Q |\n"
-"    -R ] [ --comment-delimiter commentdelim ] [ --version | -h | --help ] [\n"
-"    --input-file infile | --input-string instring ] [ --line-separator\n"
-"    linesep ] [ --output-file outfile ]\n"
+"    Planimeter [ -r ] [ -s ] [ -l ] [ -e a f ] [ -w ] [ -p prec ] [ -G | -E\n"
+"    | -Q | -R ] [ --comment-delimiter commentdelim ] [ --version | -h |\n"
+"    --help ] [ --input-file infile | --input-string instring ] [\n"
+"    --line-separator linesep ] [ --output-file outfile ]\n"
 "\n"
 "For full documentation type:\n"
 "    Planimeter --help\n"
 "or visit:\n"
-"    http://geographiclib.sf.net/1.43/Planimeter.1.html\n";
+"    http://geographiclib.sf.net/1.44/Planimeter.1.html\n";
   else
     ( retval ? std::cerr : std::cout ) << "Man page:\n"
 "NAME\n"
 "       Planimeter -- compute the area of geodesic polygons\n"
 "\n"
 "SYNOPSIS\n"
-"       Planimeter [ -r ] [ -s ] [ -l ] [ -e a f ] [ -p prec ] [ -G | -E | -Q |\n"
-"       -R ] [ --comment-delimiter commentdelim ] [ --version | -h | --help ] [\n"
-"       --input-file infile | --input-string instring ] [ --line-separator\n"
-"       linesep ] [ --output-file outfile ]\n"
+"       Planimeter [ -r ] [ -s ] [ -l ] [ -e a f ] [ -w ] [ -p prec ] [ -G | -E\n"
+"       | -Q | -R ] [ --comment-delimiter commentdelim ] [ --version | -h |\n"
+"       --help ] [ --input-file infile | --input-string instring ] [\n"
+"       --line-separator linesep ] [ --output-file outfile ]\n"
 "\n"
 "DESCRIPTION\n"
 "       Measure the area of a geodesic polygon.  Reads polygon vertices from\n"
@@ -80,6 +80,9 @@ int usage(int retval, bool brief) {
 "           these coordinates to latitude and longitude always uses the WGS84\n"
 "           parameters.\n"
 "\n"
+"       -w  when reading geographic coordinates, longitude precedes latitude\n"
+"           (this can be overridden by a hemisphere designator, N, S, E, W).\n"
+"\n"
 "       -p  set the output precision to prec (default 6); the perimeter is\n"
 "           given (in meters) with prec digits after the decimal point; the\n"
 "           area is given (in meters^2) with (prec - 5) digits after the\n"
diff --git a/man/RhumbSolve.1 b/man/RhumbSolve.1
index e4bbd8c..37d872c 100644
--- a/man/RhumbSolve.1
+++ b/man/RhumbSolve.1
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "RHUMBSOLVE 1"
-.TH RHUMBSOLVE 1 "2015-05-22" "GeographicLib 1.43" "GeographicLib Utilities"
+.TH RHUMBSOLVE 1 "2015-08-14" "GeographicLib 1.44" "GeographicLib Utilities"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
@@ -144,7 +144,7 @@ RhumbSolve \-\- perform rhumb line calculations
 .IX Header "SYNOPSIS"
 \&\fBRhumbSolve\fR [ \fB\-i\fR | \fB\-l\fR \fIlat1\fR \fIlon1\fR \fIazi12\fR ]
 [ \fB\-e\fR \fIa\fR \fIf\fR ]
-[ \fB\-d\fR | \fB\-:\fR ] [ \fB\-p\fR \fIprec\fR ] [ \fB\-s\fR ]
+[ \fB\-d\fR | \fB\-:\fR ] [ \fB\-w\fR ] [ \fB\-p\fR \fIprec\fR ] [ \fB\-s\fR ]
 [ \fB\-\-comment\-delimiter\fR \fIcommentdelim\fR ]
 [ \fB\-\-version\fR | \fB\-h\fR | \fB\-\-help\fR ]
 [ \fB\-\-input\-file\fR \fIinfile\fR | \fB\-\-input\-string\fR \fIinstring\fR ]
@@ -191,8 +191,10 @@ there are two shortest rhumb lines and the east-going one is chosen.
 perform an inverse calculation (see 3 above).
 .IP "\fB\-l\fR" 4
 .IX Item "-l"
-line mode (see 2 above); generate a sequence of points along the
-rhumb line specified by \fIlat1\fR \fIlon1\fR \fIazi12\fR.
+line mode (see 2 above); generate a sequence of points along the rhumb
+line specified by \fIlat1\fR \fIlon1\fR \fIazi12\fR.  The \fB\-w\fR flag can be used
+to swap the default order of the 2 geographic coordinates, provided that
+it appears before \fB\-l\fR.
 .IP "\fB\-e\fR" 4
 .IX Item "-e"
 specify the ellipsoid via \fIa\fR \fIf\fR; the equatorial radius is \fIa\fR and
@@ -208,6 +210,11 @@ output angles as degrees, minutes, seconds instead of decimal degrees.
 .IX Item "-:"
 like \fB\-d\fR, except use : as a separator instead of the d, ', and "
 delimiters.
+.IP "\fB\-w\fR" 4
+.IX Item "-w"
+on input and output, longitude precedes latitude (except that on input
+this can be overridden by a hemisphere designator, \fIN\fR, \fIS\fR, \fIE\fR,
+\&\fIW\fR).
 .IP "\fB\-p\fR" 4
 .IX Item "-p"
 set the output precision to \fIprec\fR (default 3); \fIprec\fR is the
@@ -258,18 +265,17 @@ file name of \*(L"\-\*(R" stands for standard output.
 .IX Header "INPUT"
 \&\fBRhumbSolve\fR measures all angles in degrees, all lengths (\fIs12\fR) in
 meters, and all areas (\fIS12\fR) in meters^2.  On input angles (latitude,
-longitude, azimuth) can be as decimal degrees or degrees (d), minutes
-('), seconds (\*(L").  A decimal point can only appear in the least
-significant component and the designator (d, ', or \*(R") for this component
-is optional; thus \f(CW\*(C`40d30\*(C'\fR, \f(CW\*(C`40d30\*(Aq\*(C'\fR, \f(CW\*(C`40.5d\*(C'\fR, and \f(CW40.5\fR are all
-equivalent.  By default, latitude precedes longitude for each point;
-however on input either may be given first by appending (or prepending)
-\&\fIN\fR or \fIS\fR to the latitude and \fIE\fR or \fIW\fR to the longitude.
-Azimuths are measured clockwise from north; however this may be
-overridden with \fIE\fR or \fIW\fR.
+longitude, azimuth, arc length) can be as decimal degrees or degrees,
+minutes, seconds.  For example, \f(CW\*(C`40d30\*(C'\fR, \f(CW\*(C`40d30\*(Aq\*(C'\fR, \f(CW\*(C`40:30\*(C'\fR, \f(CW\*(C`40.5d\*(C'\fR,
+and \f(CW40.5\fR are all equivalent.  By default, latitude precedes longitude
+for each point (the \fB\-w\fR flag switches this convention); however on
+input either may be given first by appending (or prepending) \fIN\fR or
+\&\fIS\fR to the latitude and \fIE\fR or \fIW\fR to the longitude.  Azimuths are
+measured clockwise from north; however this may be overridden with \fIE\fR
+or \fIW\fR.
 .PP
-See the \f(CW\*(C`QUOTING\*(C'\fR section of \fIGeoConvert\fR\|(1) for how to quote the \s-1DMS\s0
-designators ' and ".
+For details on the allowed formats for angles, see the \f(CW\*(C`GEOGRAPHIC
+COORDINATES\*(C'\fR section of \fIGeoConvert\fR\|(1).
 .SH "PRECISION"
 .IX Header "PRECISION"
 \&\fIprec\fR gives precision of the output with \fIprec\fR = 0 giving 1 m
diff --git a/man/RhumbSolve.1.html b/man/RhumbSolve.1.html
index 9f5be90..bc52287 100644
--- a/man/RhumbSolve.1.html
+++ b/man/RhumbSolve.1.html
@@ -17,7 +17,7 @@
 
 <h1 id="SYNOPSIS">SYNOPSIS</h1>
 
-<p><b>RhumbSolve</b> [ <b>-i</b> | <b>-l</b> <i>lat1</i> <i>lon1</i> <i>azi12</i> ] [ <b>-e</b> <i>a</i> <i>f</i> ] [ <b>-d</b> | <b>-:</b> ] [ <b>-p</b> <i>prec</i> ] [ <b>-s</b> ] [ <b>--comment-delimiter</b> <i>commentdelim</i> ] [ <b>--version</b> | <b>-h</b> | <b>--help</b> ] [ <b>--input-file</b> <i>infile</i> | <b>--input-string</b> <i>instring</i> ] [ <b>--line-separator</b> <i>linesep</i> ] [ <b>--output-file</b> <i>outfile</i> ]</p>
+<p><b>RhumbSolve</b> [ <b>-i</b> | <b>-l</b> <i>lat1</i> <i>lon1</i> <i>azi12</i> ] [ <b>-e</b> <i>a</i> <i>f</i> ] [ <b>-d</b> | <b>-:</b> ] [ <b>-w</b> ] [ <b>-p</b> <i>prec</i> ] [ <b>-s</b> ] [ <b>--comment-delimiter</b> <i>commentdelim</i> ] [ <b>--version</b> | <b>-h</b> | <b>--help</b> ] [ <b>--input-file</b> <i>infile</i> | <b>--input-string</b> <i>instring</i> ] [ <b>--line-separator</b> <i>linesep</i> ] [ <b>--output-file</b> <i>outfile</i> ]</p>
 
 <h1 id="DESCRIPTION">DESCRIPTION</h1>
 
@@ -53,7 +53,7 @@
 <dt id="l"><b>-l</b></dt>
 <dd>
 
-<p>line mode (see 2 above); generate a sequence of points along the rhumb line specified by <i>lat1</i> <i>lon1</i> <i>azi12</i>.</p>
+<p>line mode (see 2 above); generate a sequence of points along the rhumb line specified by <i>lat1</i> <i>lon1</i> <i>azi12</i>. The <b>-w</b> flag can be used to swap the default order of the 2 geographic coordinates, provided that it appears before <b>-l</b>.</p>
 
 </dd>
 <dt id="e"><b>-e</b></dt>
@@ -74,6 +74,12 @@
 <p>like <b>-d</b>, except use : as a separator instead of the d, ', and " delimiters.</p>
 
 </dd>
+<dt id="w"><b>-w</b></dt>
+<dd>
+
+<p>on input and output, longitude precedes latitude (except that on input this can be overridden by a hemisphere designator, <i>N</i>, <i>S</i>, <i>E</i>, <i>W</i>).</p>
+
+</dd>
 <dt id="p"><b>-p</b></dt>
 <dd>
 
@@ -138,9 +144,9 @@
 
 <h1 id="INPUT">INPUT</h1>
 
-<p><b>RhumbSolve</b> measures all angles in degrees, all lengths (<i>s12</i>) in meters, and all areas (<i>S12</i>) in meters^2. On input angles (latitude, longitude, azimuth) can be as decimal degrees or degrees (d), minutes ('), seconds ("). A decimal point can only appear in the least significant component and the designator (d, ', or ") for this component is optional; thus <code>40d30</code>, <code>40d30'</code>, <code>40.5d</code>, and <code>40.5</code> are all [...]
+<p><b>RhumbSolve</b> measures all angles in degrees, all lengths (<i>s12</i>) in meters, and all areas (<i>S12</i>) in meters^2. On input angles (latitude, longitude, azimuth, arc length) can be as decimal degrees or degrees, minutes, seconds. For example, <code>40d30</code>, <code>40d30'</code>, <code>40:30</code>, <code>40.5d</code>, and <code>40.5</code> are all equivalent. By default, latitude precedes longitude for each point (the <b>-w</b> flag switches this convention); howeve [...]
 
-<p>See the <code>QUOTING</code> section of GeoConvert(1) for how to quote the DMS designators ' and ".</p>
+<p>For details on the allowed formats for angles, see the <code>GEOGRAPHIC COORDINATES</code> section of GeoConvert(1).</p>
 
 <h1 id="PRECISION">PRECISION</h1>
 
diff --git a/man/RhumbSolve.pod b/man/RhumbSolve.pod
index b74c2e8..34ce44e 100644
--- a/man/RhumbSolve.pod
+++ b/man/RhumbSolve.pod
@@ -6,7 +6,7 @@ RhumbSolve -- perform rhumb line calculations
 
 B<RhumbSolve> [ B<-i> | B<-l> I<lat1> I<lon1> I<azi12> ]
 [ B<-e> I<a> I<f> ]
-[ B<-d> | B<-:> ] [ B<-p> I<prec> ] [ B<-s> ]
+[ B<-d> | B<-:> ] [ B<-w> ] [ B<-p> I<prec> ] [ B<-s> ]
 [ B<--comment-delimiter> I<commentdelim> ]
 [ B<--version> | B<-h> | B<--help> ]
 [ B<--input-file> I<infile> | B<--input-string> I<instring> ]
@@ -68,8 +68,10 @@ perform an inverse calculation (see 3 above).
 
 =item B<-l>
 
-line mode (see 2 above); generate a sequence of points along the
-rhumb line specified by I<lat1> I<lon1> I<azi12>.
+line mode (see 2 above); generate a sequence of points along the rhumb
+line specified by I<lat1> I<lon1> I<azi12>.  The B<-w> flag can be used
+to swap the default order of the 2 geographic coordinates, provided that
+it appears before B<-l>.
 
 =item B<-e>
 
@@ -89,6 +91,12 @@ output angles as degrees, minutes, seconds instead of decimal degrees.
 like B<-d>, except use : as a separator instead of the d, ', and "
 delimiters.
 
+=item B<-w>
+
+on input and output, longitude precedes latitude (except that on input
+this can be overridden by a hemisphere designator, I<N>, I<S>, I<E>,
+I<W>).
+
 =item B<-p>
 
 set the output precision to I<prec> (default 3); I<prec> is the
@@ -151,18 +159,17 @@ file name of "-" stands for standard output.
 
 B<RhumbSolve> measures all angles in degrees, all lengths (I<s12>) in
 meters, and all areas (I<S12>) in meters^2.  On input angles (latitude,
-longitude, azimuth) can be as decimal degrees or degrees (d), minutes
-('), seconds (").  A decimal point can only appear in the least
-significant component and the designator (d, ', or ") for this component
-is optional; thus C<40d30>, C<40d30'>, C<40.5d>, and C<40.5> are all
-equivalent.  By default, latitude precedes longitude for each point;
-however on input either may be given first by appending (or prepending)
-I<N> or I<S> to the latitude and I<E> or I<W> to the longitude.
-Azimuths are measured clockwise from north; however this may be
-overridden with I<E> or I<W>.
-
-See the C<QUOTING> section of GeoConvert(1) for how to quote the DMS
-designators ' and ".
+longitude, azimuth, arc length) can be as decimal degrees or degrees,
+minutes, seconds.  For example, C<40d30>, C<40d30'>, C<40:30>, C<40.5d>,
+and C<40.5> are all equivalent.  By default, latitude precedes longitude
+for each point (the B<-w> flag switches this convention); however on
+input either may be given first by appending (or prepending) I<N> or
+I<S> to the latitude and I<E> or I<W> to the longitude.  Azimuths are
+measured clockwise from north; however this may be overridden with I<E>
+or I<W>.
+
+For details on the allowed formats for angles, see the C<GEOGRAPHIC
+COORDINATES> section of GeoConvert(1).
 
 =head1 PRECISION
 
diff --git a/man/RhumbSolve.usage b/man/RhumbSolve.usage
index 19aa99d..0c2ef70 100644
--- a/man/RhumbSolve.usage
+++ b/man/RhumbSolve.usage
@@ -1,25 +1,25 @@
 int usage(int retval, bool brief) {
   if (brief)
     ( retval ? std::cerr : std::cout ) << "Usage:\n"
-"    RhumbSolve [ -i | -l lat1 lon1 azi12 ] [ -e a f ] [ -d | -: ] [ -p prec\n"
-"    ] [ -s ] [ --comment-delimiter commentdelim ] [ --version | -h | --help\n"
-"    ] [ --input-file infile | --input-string instring ] [ --line-separator\n"
-"    linesep ] [ --output-file outfile ]\n"
+"    RhumbSolve [ -i | -l lat1 lon1 azi12 ] [ -e a f ] [ -d | -: ] [ -w ] [\n"
+"    -p prec ] [ -s ] [ --comment-delimiter commentdelim ] [ --version | -h\n"
+"    | --help ] [ --input-file infile | --input-string instring ] [\n"
+"    --line-separator linesep ] [ --output-file outfile ]\n"
 "\n"
 "For full documentation type:\n"
 "    RhumbSolve --help\n"
 "or visit:\n"
-"    http://geographiclib.sf.net/1.43/RhumbSolve.1.html\n";
+"    http://geographiclib.sf.net/1.44/RhumbSolve.1.html\n";
   else
     ( retval ? std::cerr : std::cout ) << "Man page:\n"
 "NAME\n"
 "       RhumbSolve -- perform rhumb line calculations\n"
 "\n"
 "SYNOPSIS\n"
-"       RhumbSolve [ -i | -l lat1 lon1 azi12 ] [ -e a f ] [ -d | -: ] [ -p prec\n"
-"       ] [ -s ] [ --comment-delimiter commentdelim ] [ --version | -h | --help\n"
-"       ] [ --input-file infile | --input-string instring ] [ --line-separator\n"
-"       linesep ] [ --output-file outfile ]\n"
+"       RhumbSolve [ -i | -l lat1 lon1 azi12 ] [ -e a f ] [ -d | -: ] [ -w ] [\n"
+"       -p prec ] [ -s ] [ --comment-delimiter commentdelim ] [ --version | -h\n"
+"       | --help ] [ --input-file infile | --input-string instring ] [\n"
+"       --line-separator linesep ] [ --output-file outfile ]\n"
 "\n"
 "DESCRIPTION\n"
 "       The path with constant heading between two points on the ellipsoid at\n"
@@ -58,7 +58,9 @@ int usage(int retval, bool brief) {
 "       -i  perform an inverse calculation (see 3 above).\n"
 "\n"
 "       -l  line mode (see 2 above); generate a sequence of points along the\n"
-"           rhumb line specified by lat1 lon1 azi12.\n"
+"           rhumb line specified by lat1 lon1 azi12.  The -w flag can be used\n"
+"           to swap the default order of the 2 geographic coordinates, provided\n"
+"           that it appears before -l.\n"
 "\n"
 "       -e  specify the ellipsoid via a f; the equatorial radius is a and the\n"
 "           flattening is f.  Setting f = 0 results in a sphere.  Specify f < 0\n"
@@ -73,6 +75,10 @@ int usage(int retval, bool brief) {
 "       -:  like -d, except use : as a separator instead of the d, ', and \"\n"
 "           delimiters.\n"
 "\n"
+"       -w  on input and output, longitude precedes latitude (except that on\n"
+"           input this can be overridden by a hemisphere designator, N, S, E,\n"
+"           W).\n"
+"\n"
 "       -p  set the output precision to prec (default 3); prec is the precision\n"
 "           relative to 1 m.  See \"PRECISION\".\n"
 "\n"
@@ -120,17 +126,16 @@ int usage(int retval, bool brief) {
 "INPUT\n"
 "       RhumbSolve measures all angles in degrees, all lengths (s12) in meters,\n"
 "       and all areas (S12) in meters^2.  On input angles (latitude, longitude,\n"
-"       azimuth) can be as decimal degrees or degrees (d), minutes ('), seconds\n"
-"       (\").  A decimal point can only appear in the least significant\n"
-"       component and the designator (d, ', or \") for this component is\n"
-"       optional; thus \"40d30\", \"40d30'\", \"40.5d\", and 40.5 are all equivalent.\n"
-"       By default, latitude precedes longitude for each point; however on\n"
-"       input either may be given first by appending (or prepending) N or S to\n"
-"       the latitude and E or W to the longitude.  Azimuths are measured\n"
-"       clockwise from north; however this may be overridden with E or W.\n"
-"\n"
-"       See the \"QUOTING\" section of GeoConvert(1) for how to quote the DMS\n"
-"       designators ' and \".\n"
+"       azimuth, arc length) can be as decimal degrees or degrees, minutes,\n"
+"       seconds.  For example, \"40d30\", \"40d30'\", \"40:30\", \"40.5d\", and 40.5\n"
+"       are all equivalent.  By default, latitude precedes longitude for each\n"
+"       point (the -w flag switches this convention); however on input either\n"
+"       may be given first by appending (or prepending) N or S to the latitude\n"
+"       and E or W to the longitude.  Azimuths are measured clockwise from\n"
+"       north; however this may be overridden with E or W.\n"
+"\n"
+"       For details on the allowed formats for angles, see the \"GEOGRAPHIC\n"
+"       COORDINATES\" section of GeoConvert(1).\n"
 "\n"
 "PRECISION\n"
 "       prec gives precision of the output with prec = 0 giving 1 m precision,\n"
diff --git a/man/TransverseMercatorProj.1 b/man/TransverseMercatorProj.1
index f95c49b..b61d431 100644
--- a/man/TransverseMercatorProj.1
+++ b/man/TransverseMercatorProj.1
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "TRANSVERSEMERCATORPROJ 1"
-.TH TRANSVERSEMERCATORPROJ 1 "2015-05-22" "GeographicLib 1.43" "GeographicLib Utilities"
+.TH TRANSVERSEMERCATORPROJ 1 "2015-08-14" "GeographicLib 1.44" "GeographicLib Utilities"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
@@ -144,7 +144,7 @@ TransverseMercatorProj \-\- perform transverse Mercator projection
 .IX Header "SYNOPSIS"
 \&\fBTransverseMercatorProj\fR [ \fB\-s\fR | \fB\-t\fR ]
 [ \fB\-l\fR \fIlon0\fR ] [ \fB\-k\fR \fIk0\fR ] [ \fB\-r\fR ]
-[ \fB\-e\fR \fIa\fR \fIf\fR ] [ \fB\-p\fR \fIprec\fR ]
+[ \fB\-e\fR \fIa\fR \fIf\fR ] [ \fB\-w\fR ] [ \fB\-p\fR \fIprec\fR ]
 [ \fB\-\-comment\-delimiter\fR \fIcommentdelim\fR ]
 [ \fB\-\-version\fR | \fB\-h\fR | \fB\-\-help\fR ]
 [ \fB\-\-input\-file\fR \fIinfile\fR | \fB\-\-input\-string\fR \fIinstring\fR ]
@@ -160,11 +160,13 @@ exact transverse Mercator projection is used.
 .PP
 Geodetic coordinates are provided on standard input as a set of lines
 containing (blank separated) \fIlatitude\fR and \fIlongitude\fR (decimal
-degrees or degrees, minutes, seconds).  For each set of geodetic
-coordinates, the corresponding projected easting, \fIx\fR, and northing,
-\&\fIy\fR, (meters) are printed on standard output together with the meridian
-convergence \fIgamma\fR (degrees) and scale \fIk\fR.  The meridian convergence
-is the bearing of the \fIy\fR axis measured clockwise from true north.
+degrees or degrees, minutes, seconds); for detils on the allowed
+formats for latitude and longitude, see the \f(CW\*(C`GEOGRAPHIC COORDINATES\*(C'\fR
+section of \fIGeoConvert\fR\|(1).  For each set of geodetic coordinates, the
+corresponding projected easting, \fIx\fR, and northing, \fIy\fR, (meters) are
+printed on standard output together with the meridian convergence
+\&\fIgamma\fR (degrees) and scale \fIk\fR.  The meridian convergence is the
+bearing of the \fIy\fR axis measured clockwise from true north.
 .SH "OPTIONS"
 .IX Header "OPTIONS"
 .IP "\fB\-s\fR" 4
@@ -194,6 +196,11 @@ is allowed for \fIf\fR.  (Also, if \fIf\fR > 1, the flattening is set to
 1/\fIf\fR.)  By default, the \s-1WGS84\s0 ellipsoid is used, \fIa\fR = 6378137 m,
 \&\fIf\fR = 1/298.257223563.  If the exact algorithm is used, \fIf\fR must be
 positive.
+.IP "\fB\-w\fR" 4
+.IX Item "-w"
+on input and output, longitude precedes latitude (except that on input
+this can be overridden by a hemisphere designator, \fIN\fR, \fIS\fR, \fIE\fR,
+\&\fIW\fR).
 .IP "\fB\-p\fR" 4
 .IX Item "-p"
 set the output precision to \fIprec\fR (default 6).  \fIprec\fR is the number
diff --git a/man/TransverseMercatorProj.1.html b/man/TransverseMercatorProj.1.html
index d19c583..6c94c52 100644
--- a/man/TransverseMercatorProj.1.html
+++ b/man/TransverseMercatorProj.1.html
@@ -17,13 +17,13 @@
 
 <h1 id="SYNOPSIS">SYNOPSIS</h1>
 
-<p><b>TransverseMercatorProj</b> [ <b>-s</b> | <b>-t</b> ] [ <b>-l</b> <i>lon0</i> ] [ <b>-k</b> <i>k0</i> ] [ <b>-r</b> ] [ <b>-e</b> <i>a</i> <i>f</i> ] [ <b>-p</b> <i>prec</i> ] [ <b>--comment-delimiter</b> <i>commentdelim</i> ] [ <b>--version</b> | <b>-h</b> | <b>--help</b> ] [ <b>--input-file</b> <i>infile</i> | <b>--input-string</b> <i>instring</i> ] [ <b>--line-separator</b> <i>linesep</i> ] [ <b>--output-file</b> <i>outfile</i> ]</p>
+<p><b>TransverseMercatorProj</b> [ <b>-s</b> | <b>-t</b> ] [ <b>-l</b> <i>lon0</i> ] [ <b>-k</b> <i>k0</i> ] [ <b>-r</b> ] [ <b>-e</b> <i>a</i> <i>f</i> ] [ <b>-w</b> ] [ <b>-p</b> <i>prec</i> ] [ <b>--comment-delimiter</b> <i>commentdelim</i> ] [ <b>--version</b> | <b>-h</b> | <b>--help</b> ] [ <b>--input-file</b> <i>infile</i> | <b>--input-string</b> <i>instring</i> ] [ <b>--line-separator</b> <i>linesep</i> ] [ <b>--output-file</b> <i>outfile</i> ]</p>
 
 <h1 id="DESCRIPTION">DESCRIPTION</h1>
 
 <p>Perform the transverse Mercator projections. Convert geodetic coordinates to transverse Mercator coordinates. The central meridian is given by <i>lon0</i>. The longitude of origin is the equator. The scale on the central meridian is <i>k0</i>. By default an implementation of the exact transverse Mercator projection is used.</p>
 
-<p>Geodetic coordinates are provided on standard input as a set of lines containing (blank separated) <i>latitude</i> and <i>longitude</i> (decimal degrees or degrees, minutes, seconds). For each set of geodetic coordinates, the corresponding projected easting, <i>x</i>, and northing, <i>y</i>, (meters) are printed on standard output together with the meridian convergence <i>gamma</i> (degrees) and scale <i>k</i>. The meridian convergence is the bearing of the <i>y</i> axis measured cloc [...]
+<p>Geodetic coordinates are provided on standard input as a set of lines containing (blank separated) <i>latitude</i> and <i>longitude</i> (decimal degrees or degrees, minutes, seconds); for detils on the allowed formats for latitude and longitude, see the <code>GEOGRAPHIC COORDINATES</code> section of GeoConvert(1). For each set of geodetic coordinates, the corresponding projected easting, <i>x</i>, and northing, <i>y</i>, (meters) are printed on standard output together with the meridi [...]
 
 <h1 id="OPTIONS">OPTIONS</h1>
 
@@ -65,6 +65,12 @@
 <p>specify the ellipsoid via <i>a</i> <i>f</i>; the equatorial radius is <i>a</i> and the flattening is <i>f</i>. Setting <i>f</i> = 0 results in a sphere. Specify <i>f</i> < 0 for a prolate ellipsoid. A simple fraction, e.g., 1/297, is allowed for <i>f</i>. (Also, if <i>f</i> > 1, the flattening is set to 1/<i>f</i>.) By default, the WGS84 ellipsoid is used, <i>a</i> = 6378137 m, <i>f</i> = 1/298.257223563. If the exact algorithm is used, <i>f</i> must be positive.</p>
 
 </dd>
+<dt id="w"><b>-w</b></dt>
+<dd>
+
+<p>on input and output, longitude precedes latitude (except that on input this can be overridden by a hemisphere designator, <i>N</i>, <i>S</i>, <i>E</i>, <i>W</i>).</p>
+
+</dd>
 <dt id="p"><b>-p</b></dt>
 <dd>
 
diff --git a/man/TransverseMercatorProj.pod b/man/TransverseMercatorProj.pod
index 62220ef..95669ad 100644
--- a/man/TransverseMercatorProj.pod
+++ b/man/TransverseMercatorProj.pod
@@ -6,7 +6,7 @@ TransverseMercatorProj -- perform transverse Mercator projection
 
 B<TransverseMercatorProj> [ B<-s> | B<-t> ]
 [ B<-l> I<lon0> ] [ B<-k> I<k0> ] [ B<-r> ]
-[ B<-e> I<a> I<f> ] [ B<-p> I<prec> ]
+[ B<-e> I<a> I<f> ] [ B<-w> ] [ B<-p> I<prec> ]
 [ B<--comment-delimiter> I<commentdelim> ]
 [ B<--version> | B<-h> | B<--help> ]
 [ B<--input-file> I<infile> | B<--input-string> I<instring> ]
@@ -23,11 +23,13 @@ exact transverse Mercator projection is used.
 
 Geodetic coordinates are provided on standard input as a set of lines
 containing (blank separated) I<latitude> and I<longitude> (decimal
-degrees or degrees, minutes, seconds).  For each set of geodetic
-coordinates, the corresponding projected easting, I<x>, and northing,
-I<y>, (meters) are printed on standard output together with the meridian
-convergence I<gamma> (degrees) and scale I<k>.  The meridian convergence
-is the bearing of the I<y> axis measured clockwise from true north.
+degrees or degrees, minutes, seconds); for detils on the allowed
+formats for latitude and longitude, see the C<GEOGRAPHIC COORDINATES>
+section of GeoConvert(1).  For each set of geodetic coordinates, the
+corresponding projected easting, I<x>, and northing, I<y>, (meters) are
+printed on standard output together with the meridian convergence
+I<gamma> (degrees) and scale I<k>.  The meridian convergence is the
+bearing of the I<y> axis measured clockwise from true north.
 
 =head1 OPTIONS
 
@@ -66,6 +68,12 @@ is allowed for I<f>.  (Also, if I<f> E<gt> 1, the flattening is set to
 I<f> = 1/298.257223563.  If the exact algorithm is used, I<f> must be
 positive.
 
+=item B<-w>
+
+on input and output, longitude precedes latitude (except that on input
+this can be overridden by a hemisphere designator, I<N>, I<S>, I<E>,
+I<W>).
+
 =item B<-p>
 
 set the output precision to I<prec> (default 6).  I<prec> is the number
diff --git a/man/TransverseMercatorProj.usage b/man/TransverseMercatorProj.usage
index 07c0690..504b243 100644
--- a/man/TransverseMercatorProj.usage
+++ b/man/TransverseMercatorProj.usage
@@ -2,14 +2,14 @@ int usage(int retval, bool brief) {
   if (brief)
     ( retval ? std::cerr : std::cout ) << "Usage:\n"
 "    TransverseMercatorProj [ -s | -t ] [ -l lon0 ] [ -k k0 ] [ -r ] [ -e a\n"
-"    f ] [ -p prec ] [ --comment-delimiter commentdelim ] [ --version | -h |\n"
-"    --help ] [ --input-file infile | --input-string instring ] [\n"
+"    f ] [ -w ] [ -p prec ] [ --comment-delimiter commentdelim ] [ --version\n"
+"    | -h | --help ] [ --input-file infile | --input-string instring ] [\n"
 "    --line-separator linesep ] [ --output-file outfile ]\n"
 "\n"
 "For full documentation type:\n"
 "    TransverseMercatorProj --help\n"
 "or visit:\n"
-"    http://geographiclib.sf.net/1.43/TransverseMercatorProj.1.html\n";
+"    http://geographiclib.sf.net/1.44/TransverseMercatorProj.1.html\n";
   else
     ( retval ? std::cerr : std::cout ) << "Man page:\n"
 "NAME\n"
@@ -17,8 +17,8 @@ int usage(int retval, bool brief) {
 "\n"
 "SYNOPSIS\n"
 "       TransverseMercatorProj [ -s | -t ] [ -l lon0 ] [ -k k0 ] [ -r ] [ -e a\n"
-"       f ] [ -p prec ] [ --comment-delimiter commentdelim ] [ --version | -h |\n"
-"       --help ] [ --input-file infile | --input-string instring ] [\n"
+"       f ] [ -w ] [ -p prec ] [ --comment-delimiter commentdelim ] [ --version\n"
+"       | -h | --help ] [ --input-file infile | --input-string instring ] [\n"
 "       --line-separator linesep ] [ --output-file outfile ]\n"
 "\n"
 "DESCRIPTION\n"
@@ -30,11 +30,13 @@ int usage(int retval, bool brief) {
 "\n"
 "       Geodetic coordinates are provided on standard input as a set of lines\n"
 "       containing (blank separated) latitude and longitude (decimal degrees or\n"
-"       degrees, minutes, seconds).  For each set of geodetic coordinates, the\n"
-"       corresponding projected easting, x, and northing, y, (meters) are\n"
-"       printed on standard output together with the meridian convergence gamma\n"
-"       (degrees) and scale k.  The meridian convergence is the bearing of the\n"
-"       y axis measured clockwise from true north.\n"
+"       degrees, minutes, seconds); for detils on the allowed formats for\n"
+"       latitude and longitude, see the \"GEOGRAPHIC COORDINATES\" section of\n"
+"       GeoConvert(1).  For each set of geodetic coordinates, the corresponding\n"
+"       projected easting, x, and northing, y, (meters) are printed on standard\n"
+"       output together with the meridian convergence gamma (degrees) and scale\n"
+"       k.  The meridian convergence is the bearing of the y axis measured\n"
+"       clockwise from true north.\n"
 "\n"
 "OPTIONS\n"
 "       -s  use the sixth-order Krueger series approximation to the transverse\n"
@@ -58,6 +60,10 @@ int usage(int retval, bool brief) {
 "           1/298.257223563.  If the exact algorithm is used, f must be\n"
 "           positive.\n"
 "\n"
+"       -w  on input and output, longitude precedes latitude (except that on\n"
+"           input this can be overridden by a hemisphere designator, N, S, E,\n"
+"           W).\n"
+"\n"
 "       -p  set the output precision to prec (default 6).  prec is the number\n"
 "           of digits after the decimal point for lengths (in meters).  For\n"
 "           latitudes and longitudes (in degrees), the number of digits after\n"
diff --git a/matlab/Makefile.am b/matlab/Makefile.am
index 02dbdef..4447607 100644
--- a/matlab/Makefile.am
+++ b/matlab/Makefile.am
@@ -44,7 +44,6 @@ $(srcdir)/geographiclib/private/A3coeff.m \
 $(srcdir)/geographiclib/private/A3f.m \
 $(srcdir)/geographiclib/private/AngDiff.m \
 $(srcdir)/geographiclib/private/AngNormalize.m \
-$(srcdir)/geographiclib/private/AngNormalize2.m \
 $(srcdir)/geographiclib/private/AngRound.m \
 $(srcdir)/geographiclib/private/C1f.m \
 $(srcdir)/geographiclib/private/C1pf.m \
@@ -55,13 +54,16 @@ $(srcdir)/geographiclib/private/C4coeff.m \
 $(srcdir)/geographiclib/private/C4f.m \
 $(srcdir)/geographiclib/private/G4coeff.m \
 $(srcdir)/geographiclib/private/GeoRotation.m \
+$(srcdir)/geographiclib/private/LatFix.m \
 $(srcdir)/geographiclib/private/SinCosSeries.m \
+$(srcdir)/geographiclib/private/atan2dx.m \
 $(srcdir)/geographiclib/private/cbrtx.m \
 $(srcdir)/geographiclib/private/cvmgt.m \
 $(srcdir)/geographiclib/private/eatanhe.m \
 $(srcdir)/geographiclib/private/geoid_file.m \
 $(srcdir)/geographiclib/private/geoid_load_file.m \
 $(srcdir)/geographiclib/private/norm2.m \
+$(srcdir)/geographiclib/private/sincosdx.m \
 $(srcdir)/geographiclib/private/sumx.m \
 $(srcdir)/geographiclib/private/swap.m \
 $(srcdir)/geographiclib/private/tauf.m \
diff --git a/matlab/Makefile.in b/matlab/Makefile.in
index 38f9e26..36169b5 100644
--- a/matlab/Makefile.in
+++ b/matlab/Makefile.in
@@ -292,7 +292,6 @@ $(srcdir)/geographiclib/private/A3coeff.m \
 $(srcdir)/geographiclib/private/A3f.m \
 $(srcdir)/geographiclib/private/AngDiff.m \
 $(srcdir)/geographiclib/private/AngNormalize.m \
-$(srcdir)/geographiclib/private/AngNormalize2.m \
 $(srcdir)/geographiclib/private/AngRound.m \
 $(srcdir)/geographiclib/private/C1f.m \
 $(srcdir)/geographiclib/private/C1pf.m \
@@ -303,13 +302,16 @@ $(srcdir)/geographiclib/private/C4coeff.m \
 $(srcdir)/geographiclib/private/C4f.m \
 $(srcdir)/geographiclib/private/G4coeff.m \
 $(srcdir)/geographiclib/private/GeoRotation.m \
+$(srcdir)/geographiclib/private/LatFix.m \
 $(srcdir)/geographiclib/private/SinCosSeries.m \
+$(srcdir)/geographiclib/private/atan2dx.m \
 $(srcdir)/geographiclib/private/cbrtx.m \
 $(srcdir)/geographiclib/private/cvmgt.m \
 $(srcdir)/geographiclib/private/eatanhe.m \
 $(srcdir)/geographiclib/private/geoid_file.m \
 $(srcdir)/geographiclib/private/geoid_load_file.m \
 $(srcdir)/geographiclib/private/norm2.m \
+$(srcdir)/geographiclib/private/sincosdx.m \
 $(srcdir)/geographiclib/private/sumx.m \
 $(srcdir)/geographiclib/private/swap.m \
 $(srcdir)/geographiclib/private/tauf.m \
diff --git a/matlab/geographiclib/Contents.m b/matlab/geographiclib/Contents.m
index 26c5af8..c053af5 100644
--- a/matlab/geographiclib/Contents.m
+++ b/matlab/geographiclib/Contents.m
@@ -1,5 +1,5 @@
 % GeographicLib toolbox
-% Version 1.43 2015-05-23
+% Version 1.44 2015-08-14
 %
 %   This toolbox provides native MATLAB implementations of a subset of the
 %   C++ library, GeographicLib.  Key components of this toolbox are
@@ -22,10 +22,9 @@
 %     * Angles (latitude, longitude, azimuth, meridian convergence) are
 %       measured in degrees.
 %     * Distances are measured in meters, areas in meters^2.
-%     * Latitudes must lie in [-90,90] and longitudes and azimuths in
-%       [-540,540).  However most routines don't check that this condition
-%       holds.  (Exceptions are the grid system and geoid functions.  These
-%       return NaNs for invalid inputs.)
+%     * Latitudes must lie in [-90,90].  However most routines don't check
+%       that this condition holds.  (Exceptions are the grid system and
+%       geoid functions.  These return NaNs for invalid inputs.)
 %     * The ellipsoid is specified as [a, e], where a = equatorial radius
 %       and e = eccentricity.  The eccentricity can be pure imaginary to
 %       denote a prolate ellipsoid.
@@ -92,4 +91,4 @@
 
 % Copyright (c) Charles Karney (2015) <charles at karney.com>.
 %
-% This file was distributed with GeographicLib 1.43.
+% This file was distributed with GeographicLib 1.44.
diff --git a/matlab/geographiclib/cassini_fwd.m b/matlab/geographiclib/cassini_fwd.m
index f4bf3e4..eac89c1 100644
--- a/matlab/geographiclib/cassini_fwd.m
+++ b/matlab/geographiclib/cassini_fwd.m
@@ -25,7 +25,7 @@ function [x, y, azi, rk] = cassini_fwd(lat0, lon0, lat, lon, ellipsoid)
 
 % Copyright (c) Charles Karney (2012-2015) <charles at karney.com>.
 %
-% This file was distributed with GeographicLib 1.42.
+% This file was distributed with GeographicLib 1.44.
 
   narginchk(4, 5)
   if nargin < 5, ellipsoid = defaultellipsoid; end
@@ -38,20 +38,15 @@ function [x, y, azi, rk] = cassini_fwd(lat0, lon0, lat, lon, ellipsoid)
     error('ellipsoid must be a vector of size 2')
   end
 
-  tiny = sqrt(realmin);
   degree = pi/180;
   f = ecc2flat(ellipsoid(2));
-  lat = AngRound(lat);
-  dlon = AngDiff(AngNormalize(lon0), AngNormalize(lon)) + Z;
+  dlon = AngDiff(lon0, lon) + Z;
   [s12, azi1, azi2, ~, ~, ~, ~, sig12] = ...
       geoddistance(lat, -abs(dlon), lat, abs(dlon), ellipsoid);
-  c = sig12 < 100 * tiny;
-  sig12(c) = 0;
-  s12(c) = 0;
   sig12 = 0.5 * sig12;
   s12 = 0.5 * s12;
   c = s12 == 0;
-  da = (azi2 - azi2)/2;
+  da = AngDiff(azi1, azi2)/2;
   s = abs(dlon) <= 90;
   azi1(c & s) = 90 - da(c & s);
   azi2(c & s) = 90 + da(c & s);
@@ -66,11 +61,11 @@ function [x, y, azi, rk] = cassini_fwd(lat0, lon0, lat, lon, ellipsoid)
   azi = AngNormalize(azi2);
   [~, ~, ~, ~, ~, ~, rk] = ...
       geodreckon(lat, dlon, -sig12, azi, ellipsoid, true);
-  [sbet , cbet ] = norm2((1-f) * sind(lat ), cosd(lat ));
-  [sbet0, cbet0] = norm2((1-f) * sind(lat0), cosd(lat0));
-  alp = azi * degree;
-  salp = sin(alp); salp(alp == -180) = 0;
-  calp = cos(alp); calp(abs(alp) == 90) = 0;
+  [sbet, cbet] = sincosdx(lat);
+  [sbet, cbet] = norm2((1-f) * sbet, cbet);
+  [sbet0, cbet0] = sincosdx(lat0);
+  [sbet0, cbet0] = norm2((1-f) * sbet0, cbet0);
+  [salp, calp] = sincosdx(azi);
   salp0 = salp .* cbet;
   calp0 = hypot(calp, salp .* sbet);
   sbet1 = calp0;
diff --git a/matlab/geographiclib/eqdazim_fwd.m b/matlab/geographiclib/eqdazim_fwd.m
index 730c389..90c1233 100644
--- a/matlab/geographiclib/eqdazim_fwd.m
+++ b/matlab/geographiclib/eqdazim_fwd.m
@@ -36,7 +36,7 @@ function [x, y, azi, rk] = eqdazim_fwd(lat0, lon0, lat, lon, ellipsoid)
 
 % Copyright (c) Charles Karney (2012-2015) <charles at karney.com>.
 %
-% This file was distributed with GeographicLib 1.42.
+% This file was distributed with GeographicLib 1.44.
 
   narginchk(4, 5)
   if nargin < 5, ellipsoid = defaultellipsoid; end
@@ -48,9 +48,9 @@ function [x, y, azi, rk] = eqdazim_fwd(lat0, lon0, lat, lon, ellipsoid)
 
   [s, azi0, azi, ~, m, ~, ~, sig] = ...
       geoddistance(lat0, lon0, lat, lon, ellipsoid);
-  azi0 = azi0 * (pi/180);
-  x = s .* sin(azi0);
-  y = s .* cos(azi0);
+  [x, y] = sincosdx(azi0);
+  x = s .* x;
+  y = s .* y;
   rk = m ./ s;
   rk(sig <= 0.01 * sqrt(realmin)) = 1;
 end
diff --git a/matlab/geographiclib/eqdazim_inv.m b/matlab/geographiclib/eqdazim_inv.m
index e96f3d9..0485f1f 100644
--- a/matlab/geographiclib/eqdazim_inv.m
+++ b/matlab/geographiclib/eqdazim_inv.m
@@ -36,7 +36,7 @@ function [lat, lon, azi, rk] = eqdazim_inv(lat0, lon0, x, y, ellipsoid)
 
 % Copyright (c) Charles Karney (2012-2015) <charles at karney.com>.
 %
-% This file was distributed with GeographicLib 1.42.
+% This file was distributed with GeographicLib 1.44.
 
   narginchk(4, 5)
   if nargin < 5, ellipsoid = defaultellipsoid; end
@@ -46,7 +46,7 @@ function [lat, lon, azi, rk] = eqdazim_inv(lat0, lon0, x, y, ellipsoid)
     error('lat0, lon0, x, y have incompatible sizes')
   end
 
-  azi0 = atan2(x, y) / (pi/180);
+  azi0 = atan2dx(x, y);
   s = hypot(x, y);
   [lat, lon, azi, ~, m, ~, ~, sig] = geodreckon(lat0, lon0, s, azi0, ellipsoid);
   rk = m ./ s;
diff --git a/matlab/geographiclib/gedistance.m b/matlab/geographiclib/gedistance.m
index 99a405d..dbad171 100644
--- a/matlab/geographiclib/gedistance.m
+++ b/matlab/geographiclib/gedistance.m
@@ -28,7 +28,7 @@ function [s12, azi1, azi2, S12] = gedistance(lat1, lon1, lat2, lon2, ellipsoid)
 
 % Copyright (c) Charles Karney (2014-2015) <charles at karney.com>.
 %
-% This file was distributed with GeographicLib 1.43.
+% This file was distributed with GeographicLib 1.44.
 
   narginchk(4, 5)
   if nargin < 5, ellipsoid = defaultellipsoid; end
@@ -44,7 +44,6 @@ function [s12, azi1, azi2, S12] = gedistance(lat1, lon1, lat2, lon2, ellipsoid)
   lat1 = lat1 + Z; lon1 = lon1 + Z;
   lat2 = lat2 + Z; lon2 = lon2 + Z;
 
-  degree = pi/180;
   tiny = sqrt(realmin);
 
   a = ellipsoid(1);
@@ -55,19 +54,19 @@ function [s12, azi1, azi2, S12] = gedistance(lat1, lon1, lat2, lon2, ellipsoid)
 
   areap = nargout >= 4;
 
-  lon12 = AngDiff(AngNormalize(lon1(:)), AngNormalize(lon2(:)));
-  lon12 = AngRound(lon12);
+  lat1 = AngRound(LatFix(lat1(:)));
+  lat2 = AngRound(LatFix(lat2(:)));
+  lon12 = AngRound(AngDiff(lon1(:), lon2(:)));
 
-  phi = lat1 * degree;
-  sbet1 = f1 * sin(phi); cbet1 = cos(phi); cbet1(lat1 == -90) = tiny;
+  [sbet1, cbet1] = sincosdx(lat1);
+  sbet1 = f1 * sbet1; cbet1 = max(tiny, cbet1);
   [sbet1, cbet1] = norm2(sbet1, cbet1);
 
-  phi = lat2 * degree;
-  sbet2 = f1 * sin(phi); cbet2 = cos(phi); cbet2(abs(lat2) == 90) = tiny;
+  [sbet2, cbet2] = sincosdx(lat2);
+  sbet2 = f1 * sbet2; cbet2 = max(tiny, cbet2);
   [sbet2, cbet2] = norm2(sbet2, cbet2);
 
-  lam12 = lon12 * degree;
-  slam12 = sin(lam12); slam12(lon12 == 180) = 0; clam12 = cos(lam12);
+  [slam12, clam12] = sincosdx(lon12);
 
   % Solve great circle
   sgam1 = cbet2 .* slam12; cgam1 = +cbet1 .* sbet2 - sbet1 .* cbet2 .* clam12;
@@ -92,8 +91,8 @@ function [s12, azi1, azi2, S12] = gedistance(lat1, lon1, lat2, lon2, ellipsoid)
   s12 = A1 .* (atan2(ssig12, csig12) + ...
                (SinCosSeries(true, ssig2, csig2, C1a) - ...
                 SinCosSeries(true, ssig1, csig1, C1a)));
-  azi1 = atan2(sgam1, cgam1 .* sqrt(1 - e2 * cbet1.^2)) / degree;
-  azi2 = atan2(sgam2, cgam2 .* sqrt(1 - e2 * cbet2.^2)) / degree;
+  azi1 = atan2dx(sgam1, cgam1 .* sqrt(1 - e2 * cbet1.^2));
+  azi2 = atan2dx(sgam2, cgam2 .* sqrt(1 - e2 * cbet2.^2));
 
   s12 = reshape(s12, S); azi1 = reshape(azi1, S); azi2 = reshape(azi2, S);
 
diff --git a/matlab/geographiclib/gedoc.m b/matlab/geographiclib/gedoc.m
index edb9b09..8e1b1ee 100644
--- a/matlab/geographiclib/gedoc.m
+++ b/matlab/geographiclib/gedoc.m
@@ -66,8 +66,6 @@ function gedoc
 %
 %   Restrictions on the inputs:
 %     * All latitudes must lie in [-90, 90].
-%     * All longitudes and azimuths must lie in [-540, 540).  On output,
-%       these quantities lie in [-180, 180).
 %     * The distance s12 is unrestricted.  This allows great ellipses to
 %       wrap around the ellipsoid.
 %     * The equatorial radius, a, must be positive.
diff --git a/matlab/geographiclib/geocent_fwd.m b/matlab/geographiclib/geocent_fwd.m
index 252e68f..8cfe11f 100644
--- a/matlab/geographiclib/geocent_fwd.m
+++ b/matlab/geographiclib/geocent_fwd.m
@@ -22,7 +22,7 @@ function [X, Y, Z, M] = geocent_fwd(lat, lon, h, ellipsoid)
 
 % Copyright (c) Charles Karney (2015) <charles at karney.com>.
 %
-% This file was distributed with GeographicLib 1.42.
+% This file was distributed with GeographicLib 1.44.
 
   narginchk(2, 4)
   if nargin < 3, h = 0; end
@@ -35,22 +35,15 @@ function [X, Y, Z, M] = geocent_fwd(lat, lon, h, ellipsoid)
   if length(ellipsoid(:)) ~= 2
     error('ellipsoid must be a vector of size 2')
   end
-  lat = lat + z; lon = lon + z; h = h + z;
+  lat = LatFix(lat) + z; lon = lon + z; h = h + z;
 
-  degree = pi/180;
   a = ellipsoid(1);
   e2 = ellipsoid(2)^2;
   e2m = 1 - e2;
 
-  lon = AngNormalize(lon);
-
-  phi = lat * degree;
-  lam = lon * degree;
-  sphi = sin(phi);
-  cphi = cos(phi); cphi(abs(lat) == 90) = 0;
+  [slam, clam] = sincosdx(lon);
+  [sphi, cphi] = sincosdx(lat);
   n = a./sqrt(1 - e2 * sphi.^2);
-  slam = sin(lam); slam(lon == -180) = 0;
-  clam = cos(lam); clam(abs(lon) == 90) = 0;
   Z = (e2m * n + h) .* sphi;
   X = (n + h) .* cphi;
   Y = X .* slam;
diff --git a/matlab/geographiclib/geocent_inv.m b/matlab/geographiclib/geocent_inv.m
index 38f28d2..df7c21b 100644
--- a/matlab/geographiclib/geocent_inv.m
+++ b/matlab/geographiclib/geocent_inv.m
@@ -20,7 +20,7 @@ function [lat, lon, h, M] = geocent_inv(X, Y, Z, ellipsoid)
 
 % Copyright (c) Charles Karney (2015) <charles at karney.com>.
 %
-% This file was distributed with GeographicLib 1.42.
+% This file was distributed with GeographicLib 1.44.
 
   narginchk(3, 4)
   if nargin < 4, ellipsoid = defaultellipsoid; end
@@ -34,7 +34,6 @@ function [lat, lon, h, M] = geocent_inv(X, Y, Z, ellipsoid)
   end
   X = X + z; Y = Y + z; Z = Z + z;
 
-  degree = pi/180;
   a = ellipsoid(1);
   e2 = ellipsoid(2)^2;
   e2m = 1 - e2;
@@ -143,9 +142,9 @@ function [lat, lon, h, M] = geocent_inv(X, Y, Z, ellipsoid)
     sphi(far) = Z(far)/2 ./ H;
     cphi(far) = R(far) ./ H;
   end
-  lat = atan2(sphi, cphi) / degree;
+  lat = atan2dx(sphi, cphi);
   % Negative signs return lon in [-180, 180).  0- converts -0 to +0.
-  lon = 0 - atan2(-slam, clam) / degree;
+  lon = atan2dx(slam, clam);
   if nargout > 3
     M = GeoRotation(sphi, cphi, slam, clam);
   end
diff --git a/matlab/geographiclib/geoddistance.m b/matlab/geographiclib/geoddistance.m
index 6ff9648..55142b5 100644
--- a/matlab/geographiclib/geoddistance.m
+++ b/matlab/geographiclib/geoddistance.m
@@ -44,7 +44,7 @@ function [s12, azi1, azi2, S12, m12, M12, M21, a12] = geoddistance ...
 
 % Copyright (c) Charles Karney (2012-2015) <charles at karney.com>.
 %
-% This file was distributed with GeographicLib 1.43.
+% This file was distributed with GeographicLib 1.44.
 %
 % This is a straightforward transcription of the C++ implementation in
 % GeographicLib and the C++ source should be consulted for additional
@@ -84,18 +84,27 @@ function [s12, azi1, azi2, S12, m12, M12, M21, a12] = geoddistance ...
   n = f / (2 - f);
   b = a * f1;
 
+  distp = true;
   areap = nargout >= 4;
+  redp = nargout >= 5;
   scalp = nargout >= 6;
 
+  % mask for Lengths: 1 = distance, 2 = reduced length, 4 = geodesic scale
+  lengthmask = distp;
+  if redp
+    lengthmask = 2;
+  end
+  if scalp
+    lengthmask = lengthmask + 4;
+  end
   A3x = A3coeff(n);
   C3x = C3coeff(n);
 
-  lon12 = AngDiff(AngNormalize(lon1(:)), AngNormalize(lon2(:)));
-  lon12 = AngRound(lon12);
+  lon12 = AngRound(AngDiff(lon1(:), lon2(:)));
   lonsign = 2 * (lon12 >= 0) - 1;
   lon12 = lonsign .* lon12;
-  lat1 = AngRound(lat1(:));
-  lat2 = AngRound(lat2(:));
+  lat1 = AngRound(LatFix(lat1(:)));
+  lat2 = AngRound(LatFix(lat2(:)));
   swapp = 2 * (abs(lat1) >= abs(lat2)) - 1;
   lonsign(swapp < 0) = - lonsign(swapp < 0);
   [lat1(swapp < 0), lat2(swapp < 0)] = swap(lat1(swapp < 0), lat2(swapp < 0));
@@ -104,13 +113,11 @@ function [s12, azi1, azi2, S12, m12, M12, M21, a12] = geoddistance ...
   lat1 = latsign .* lat1;
   lat2 = latsign .* lat2;
 
-  phi = lat1 * degree;
-  sbet1 = f1 * sin(phi); cbet1 = cos(phi); cbet1(lat1 == -90) = tiny;
-  [sbet1, cbet1] = norm2(sbet1, cbet1);
+  [sbet1, cbet1] = sincosdx(lat1); sbet1 = f1 * sbet1;
+  [sbet1, cbet1] = norm2(sbet1, cbet1); cbet1 = max(tiny, cbet1);
 
-  phi = lat2 * degree;
-  sbet2 = f1 * sin(phi); cbet2 = cos(phi); cbet2(abs(lat2) == 90) = tiny;
-  [sbet2, cbet2] = norm2(sbet2, cbet2);
+  [sbet2, cbet2] = sincosdx(lat2); sbet2 = f1 * sbet2;
+  [sbet2, cbet2] = norm2(sbet2, cbet2); cbet2 = max(tiny, cbet2);
 
   c = cbet1 < -sbet1 & cbet2 == cbet1;
   sbet2(c) = (2 * (sbet2(c) < 0) - 1) .* sbet1(c);
@@ -120,7 +127,7 @@ function [s12, azi1, azi2, S12, m12, M12, M21, a12] = geoddistance ...
   dn1 = sqrt(1 + ep2 * sbet1.^2);
   dn2 = sqrt(1 + ep2 * sbet2.^2);
   lam12 = lon12 * degree;
-  slam12 = sin(lam12); slam12(lon12 == 180) = 0; clam12 = cos(lam12);
+  [slam12, clam12] = sincosdx(lon12);
 
   sig12 = Z; ssig1 = Z; csig1 = Z; ssig2 = Z; csig2 = Z;
   calp1 = Z; salp1 = Z; calp2 = Z; salp2 = Z;
@@ -141,8 +148,10 @@ function [s12, azi1, azi2, S12, m12, M12, M21, a12] = geoddistance ...
     [s12(m), m12(m), ~, M12(m), M21(m)] = ...
         Lengths(n, sig12(m), ...
                 ssig1(m), csig1(m), dn1(m), ssig2(m), csig2(m), dn2(m), ...
-                cbet1(m), cbet2(m), scalp, ep2);
+                cbet1(m), cbet2(m), bitor(1+2, lengthmask), ep2);
     m = m & (sig12 < 1 | m12 >= 0);
+    g = m & sig12 < 3 * tiny;
+    sig12(g) = 0; s12(g) = 0; m12(g) = 0;
     m12(m) = m12(m) * b;
     s12(m) = s12(m) * b;
   end
@@ -157,84 +166,92 @@ function [s12, azi1, azi2, S12, m12, M12, M21, a12] = geoddistance ...
 
   g = ~eq & ~m;
 
-  dnm = Z;
-  [sig12(g), salp1(g), calp1(g), salp2(g), calp2(g), dnm(g)] = ...
-      InverseStart(sbet1(g), cbet1(g), dn1(g), sbet2(g), cbet2(g), dn2(g), ...
-                   lam12(g), f, A3x);
-
-  s = g & sig12 >= 0;
-  s12(s) = b * sig12(s) .* dnm(s);
-  m12(s) = b * dnm(s).^2 .* sin(sig12(s) ./ dnm(s));
-  if scalp
-    M12(s) = cos(sig12(s) ./ dnm(s)); M21(s) = M12(s);
-  end
-  omg12(s) = lam12(s) ./ (f1 * dnm(s));
-
-  g = g & sig12 < 0;
-
-  salp1a = Z + tiny; calp1a = Z + 1;
-  salp1b = Z + tiny; calp1b = Z - 1;
-  ssig1 = Z; csig1 = Z; ssig2 = Z; csig2 = Z;
-  epsi = Z; v = Z; dv = Z;
-  numit = Z;
-  tripn = Z > 0;
-  tripb = tripn;
-  gsave = g;
-  for k = 0 : maxit2 - 1
-    if k == 0 && ~any(g), break, end
-    numit(g) = k;
-    [v(g), dv(g), ...
-     salp2(g), calp2(g), sig12(g), ...
-     ssig1(g), csig1(g), ssig2(g), csig2(g), epsi(g), omg12(g)] = ...
-        Lambda12(sbet1(g), cbet1(g), dn1(g), ...
-                 sbet2(g), cbet2(g), dn2(g), ...
-                 salp1(g), calp1(g), f, A3x, C3x);
-    v = v - lam12;
-    g = g & ~(tripb | ~(abs(v) >= ((tripn * 6) + 2) * tol0));
-    if ~any(g), break, end
-
-    c = g & v > 0;
-    if k <= maxit1
-      c = c & calp1 ./ salp1 > calp1b ./ salp1b;
+  if any(g)
+    dnm = Z;
+    [sig12(g), salp1(g), calp1(g), salp2(g), calp2(g), dnm(g)] = ...
+        InverseStart(sbet1(g), cbet1(g), dn1(g), sbet2(g), cbet2(g), dn2(g), ...
+                     lam12(g), f, A3x);
+
+    s = g & sig12 >= 0;
+    s12(s) = b * sig12(s) .* dnm(s);
+    m12(s) = b * dnm(s).^2 .* sin(sig12(s) ./ dnm(s));
+    if scalp
+      M12(s) = cos(sig12(s) ./ dnm(s)); M21(s) = M12(s);
     end
-    salp1b(c) = salp1(c); calp1b(c) = calp1(c);
+    omg12(s) = lam12(s) ./ (f1 * dnm(s));
+
+    g = g & sig12 < 0;
+
+    salp1a = Z + tiny; calp1a = Z + 1;
+    salp1b = Z + tiny; calp1b = Z - 1;
+    ssig1 = Z; csig1 = Z; ssig2 = Z; csig2 = Z;
+    epsi = Z; v = Z; dv = Z;
+    numit = Z;
+    tripn = Z > 0;
+    tripb = tripn;
+    gsave = g;
+    for k = 0 : maxit2 - 1
+      if k == 0 && ~any(g), break, end
+      numit(g) = k;
+      [v(g), dv(g), ...
+       salp2(g), calp2(g), sig12(g), ...
+       ssig1(g), csig1(g), ssig2(g), csig2(g), epsi(g), omg12(g)] = ...
+          Lambda12(sbet1(g), cbet1(g), dn1(g), ...
+                   sbet2(g), cbet2(g), dn2(g), ...
+                   salp1(g), calp1(g), f, A3x, C3x);
+      v = v - lam12;
+      g = g & ~(tripb | ~(abs(v) >= ((tripn * 6) + 2) * tol0));
+      if ~any(g), break, end
+
+      c = g & v > 0;
+      if k <= maxit1
+        c = c & calp1 ./ salp1 > calp1b ./ salp1b;
+      end
+      salp1b(c) = salp1(c); calp1b(c) = calp1(c);
 
-    c = g & v < 0;
-    if k <= maxit1
-      c = c & calp1 ./ salp1 < calp1a ./ salp1a;
-    end
-    salp1a(c) = salp1(c); calp1a(c) = calp1(c);
-
-    if k == maxit1, tripn(g) = false; end
-    if k < maxit1
-      dalp1 = -v ./ dv;
-      sdalp1 = sin(dalp1); cdalp1 = cos(dalp1);
-      nsalp1 = salp1 .* cdalp1 + calp1 .* sdalp1;
-      calp1(g) = calp1(g) .* cdalp1(g) - salp1(g) .* sdalp1(g);
-      salp1(g) = nsalp1(g);
-      tripn = g & abs(v) <= 16 * tol0;
-      c = g & ~(dv > 0 & nsalp1 > 0 & abs(dalp1) < pi);
-      tripn(c) = false;
-    else
-      c = g;
+      c = g & v < 0;
+      if k <= maxit1
+        c = c & calp1 ./ salp1 < calp1a ./ salp1a;
+      end
+      salp1a(c) = salp1(c); calp1a(c) = calp1(c);
+
+      if k == maxit1, tripn(g) = false; end
+      if k < maxit1
+        dalp1 = -v ./ dv;
+        sdalp1 = sin(dalp1); cdalp1 = cos(dalp1);
+        nsalp1 = salp1 .* cdalp1 + calp1 .* sdalp1;
+        calp1(g) = calp1(g) .* cdalp1(g) - salp1(g) .* sdalp1(g);
+        salp1(g) = nsalp1(g);
+        tripn = g & abs(v) <= 16 * tol0;
+        c = g & ~(dv > 0 & nsalp1 > 0 & abs(dalp1) < pi);
+        tripn(c) = false;
+      else
+        c = g;
+      end
+
+      salp1(c) = (salp1a(c) + salp1b(c))/2;
+      calp1(c) = (calp1a(c) + calp1b(c))/2;
+      [salp1(g), calp1(g)] = norm2(salp1(g), calp1(g));
+      tripb(c) = abs(salp1a(c) - salp1(c)) + (calp1a(c) - calp1(c)) < tolb | ...
+          abs(salp1(c) - salp1b(c)) + (calp1(c) - calp1b(c)) < tolb;
     end
 
-    salp1(c) = (salp1a(c) + salp1b(c))/2;
-    calp1(c) = (calp1a(c) + calp1b(c))/2;
-    [salp1(g), calp1(g)] = norm2(salp1(g), calp1(g));
-    tripb(c) = (abs(salp1a(c) - salp1(c)) + (calp1a(c) - calp1(c)) < tolb | ...
-                abs(salp1(c) - salp1b(c)) + (calp1(c) - calp1b(c)) < tolb);
-  end
+    g = gsave;
+    if bitand(2+4, lengthmask)
+      % set distance bit if redp or scalp, so that J12 is computed in a
+      % canonical way.
+      lengthmask = bitor(1, lengthmask);
+    end
 
-  g = gsave;
-  [s12(g), m12(g), ~, M12(g), M21(g)] = ...
-      Lengths(epsi(g), sig12(g), ...
-              ssig1(g), csig1(g), dn1(g), ssig2(g), csig2(g), dn2(g), ...
-              cbet1(g), cbet2(g), scalp, ep2);
+    [s12(g), m12(g), ~, M12(g), M21(g)] = ...
+        Lengths(epsi(g), sig12(g), ...
+                ssig1(g), csig1(g), dn1(g), ssig2(g), csig2(g), dn2(g), ...
+                cbet1(g), cbet2(g), lengthmask, ep2);
 
-  m12(g) = m12(g) * b;
-  s12(g) = s12(g) * b;
-  omg12(g) = lam12(g) - omg12(g);
+    m12(g) = m12(g) * b;
+    s12(g) = s12(g) * b;
+    omg12(g) = lam12(g) - omg12(g);
+  end
 
   s12 = 0 + s12;
 
@@ -249,9 +266,9 @@ function [s12, azi1, azi2, S12, m12, M12, M21, a12] = geoddistance ...
     [ssig2, csig2] = norm2(ssig2, csig2);
 
     C4x = C4coeff(n);
-    C4a = C4f(epsi, C4x);
-    B41 = SinCosSeries(false, ssig1, csig1, C4a);
-    B42 = SinCosSeries(false, ssig2, csig2, C4a);
+    Ca = C4f(epsi, C4x);
+    B41 = SinCosSeries(false, ssig1, csig1, Ca);
+    B42 = SinCosSeries(false, ssig2, csig2, Ca);
     S12 = A4 .* (B42 - B41);
     S12(calp0 == 0 | salp0 == 0) = 0;
 
@@ -279,18 +296,23 @@ function [s12, azi1, azi2, S12, m12, M12, M21, a12] = geoddistance ...
   [calp1(swapp<0), calp2(swapp<0)] = swap(calp1(swapp<0), calp2(swapp<0));
   if scalp
     [M12(swapp<0), M21(swapp<0)] = swap(M12(swapp<0), M21(swapp<0));
+    M12 = reshape(M12, S); M21 = reshape(M21, S);
   end
   salp1 = salp1 .* swapp .* lonsign; calp1 = calp1 .* swapp .* latsign;
   salp2 = salp2 .* swapp .* lonsign; calp2 = calp2 .* swapp .* latsign;
 
-  azi1 = 0 - atan2(-salp1, calp1) / degree;
-  azi2 = 0 - atan2(-salp2, calp2) / degree;
+  azi1 = atan2dx(salp1, calp1);
+  azi2 = atan2dx(salp2, calp2);
   a12 = sig12 / degree;
 
   s12 = reshape(s12, S); azi1 = reshape(azi1, S); azi2 = reshape(azi2, S);
-  m12 = reshape(m12, S); M12 = reshape(M12, S); M21 = reshape(M21, S);
-  a12 = reshape(a12, S);
-  if (areap)
+  if redp
+    m12 = reshape(m12, S);
+  end
+  if nargout >= 8
+    a12 = reshape(a12, S);
+  end
+  if areap
     S12 = reshape(S12, S);
   end
 end
@@ -310,13 +332,13 @@ function [sig12, salp1, calp1, salp2, calp2, dnm] = ...
   etol2 = 0.1 * tol2 / sqrt( max(0.001, abs(f)) * min(1, 1 - f/2) / 2 );
   xthresh = 1000 * tol2;
 
-  sig12 = -ones(N, 1); salp2 = NaN(N, 1); calp2 = NaN(N, 1);
+  sig12 = -ones(N, 1); salp2 = nan(N, 1); calp2 = nan(N, 1);
   sbet12 = sbet2 .* cbet1 - cbet2 .* sbet1;
   cbet12 = cbet2 .* cbet1 + sbet2 .* sbet1;
   sbet12a = sbet2 .* cbet1 + cbet2 .* sbet1;
   s = cbet12 >= 0 & sbet12 < 0.5 & cbet2 .* lam12 < 0.5;
   omg12 = lam12;
-  dnm = NaN(N, 1);
+  dnm = nan(N, 1);
   sbetm2 = (sbet1(s) + sbet2(s)).^2;
   sbetm2 = sbetm2 ./ (sbetm2 + (cbet1(s) + cbet2(s)).^2);
   dnm(s) = sqrt(1 + ep2 * sbetm2);
@@ -356,7 +378,7 @@ function [sig12, salp1, calp1, salp2, calp2, dnm] = ...
       [~, m12b, m0] = ...
           Lengths(n, pi + bet12a, ...
                   sbet1(s), -cbet1(s), dn1(s), sbet2(s), cbet2(s), dn2(s), ...
-                  cbet1(s), cbet2(s), false);
+                  cbet1(s), cbet2(s), 2);
       x = -1 + m12b ./ (cbet1(s) .* cbet2(s) .* m0 * pi);
       betscale = cvmgt(sbet12a(s) ./ x, - f * cbet1(s).^2 * pi, x < -0.01);
       lamscale = betscale ./ cbet1(s);
@@ -465,16 +487,16 @@ function [lam12, dlam12, ...
                 comg1 .* comg2 + somg1 .* somg2);
   k2 = calp0.^2 * ep2;
   epsi = k2 ./ (2 * (1 + sqrt(1 + k2)) + k2);
-  C3a = C3f(epsi, C3x);
-  B312 = SinCosSeries(true, ssig2, csig2, C3a) - ...
-         SinCosSeries(true, ssig1, csig1, C3a);
+  Ca = C3f(epsi, C3x);
+  B312 = SinCosSeries(true, ssig2, csig2, Ca) - ...
+         SinCosSeries(true, ssig1, csig1, Ca);
   h0 = -f * A3f(epsi, A3x);
   domg12 = salp0 .* h0 .* (sig12 + B312);
   lam12 = omg12 + domg12;
 
   [~, dlam12] = ...
       Lengths(epsi, sig12, ...
-              ssig1, csig1, dn1, ssig2, csig2, dn2, cbet1, cbet2, false);
+              ssig1, csig1, dn1, ssig2, csig2, dn2, cbet1, cbet2, 2);
   dlam12 = dlam12 .* f1 ./ (calp2 .* cbet2);
   z = calp2 == 0;
   dlam12(z) = - 2 * f1 .* dn1(z) ./ sbet1(z);
@@ -482,37 +504,53 @@ end
 
 function [s12b, m12b, m0, M12, M21] = ...
       Lengths(epsi, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2, ...
-              cbet1, cbet2, scalp, ep2)
+              cbet1, cbet2, outmask, ep2)
 %LENGTHS  Compute various lengths associate with a geodesic
 
-  if isempty(sig12)
-    s12b = [];
-    m12b = [];
-    m0 = [];
-    M12 = [];
-    M21 = [];
-    return
+  N = nan(size(sig12));
+  if bitand(1+2+4, outmask)
+    A1 = A1m1f(epsi);
+    Ca = C1f(epsi);
+    if bitand(2+4, outmask)
+      A2 = A2m1f(epsi);
+      Cb = C2f(epsi);
+      m0 = A1 - A2;
+      A2 = 1 + A2;
+    end
+    A1 = 1 + A1;
   end
-
-  C1a = C1f(epsi);
-  C2a = C2f(epsi);
-  A1m1 = A1m1f(epsi);
-  AB1 = (1 + A1m1) .* (SinCosSeries(true, ssig2, csig2, C1a) - ...
-                       SinCosSeries(true, ssig1, csig1, C1a));
-  A2m1 = A2m1f(epsi);
-  AB2 = (1 + A2m1) .* (SinCosSeries(true, ssig2, csig2, C2a) - ...
-                       SinCosSeries(true, ssig1, csig1, C2a));
-  m0 = A1m1 - A2m1;
-  J12 = m0 .* sig12 + (AB1 - AB2);
-  m12b = dn2 .* (csig1 .* ssig2) - dn1 .* (ssig1 .* csig2) - ...
-         csig1 .* csig2 .* J12;
-  s12b = (1 + A1m1) .* sig12 + AB1;
-  if scalp
+  if bitand(1, outmask)
+    B1 = SinCosSeries(true, ssig2, csig2, Ca) - ...
+         SinCosSeries(true, ssig1, csig1, Ca);
+    s12b = A1 .* (sig12 + B1);
+    if bitand(2+4, outmask)
+      B2 = SinCosSeries(true, ssig2, csig2, Cb) - ...
+           SinCosSeries(true, ssig1, csig1, Cb);
+      J12 = m0 .* sig12 + (A1 .* B1 - A2 .* B2);
+    end
+  else
+    s12b = N;                           % assign arbitrary unused result
+    if bitand(2+4, outmask)
+      for l = 1 : size(Cb, 2)
+        % Assume here that size(Ca, 2) >= size(Cb, 2)
+        Cb(:, l) = A1 .* Ca(:, l) - A2 .* Cb(:, l);
+      end
+      J12 = m0 .* sig12 + (SinCosSeries(true, ssig2, csig2, Cb) - ...
+                           SinCosSeries(true, ssig1, csig1, Cb));
+    end
+  end
+  if bitand(2, outmask)
+    m12b = dn2 .* (csig1 .* ssig2) - dn1 .* (ssig1 .* csig2) - ...
+           csig1 .* csig2 .* J12;
+  else
+    m0 = N; m12b = N;                   % assign arbitrary unused result
+  end
+  if bitand(4, outmask)
     csig12 = csig1 .* csig2 + ssig1 .* ssig2;
     t = ep2 * (cbet1 - cbet2) .* (cbet1 + cbet2) ./ (dn1 + dn2);
     M12 = csig12 + (t .* ssig2 - csig2 .* J12) .* ssig1 ./ dn1;
     M21 = csig12 - (t .* ssig1 - csig1 .* J12) .* ssig2 ./ dn2;
   else
-    M12 = sig12; M21 = M12;             % assign arbitrary values
+    M12 = N; M21 = N;                   % assign arbitrary unused result
   end
 end
diff --git a/matlab/geographiclib/geoddoc.m b/matlab/geographiclib/geoddoc.m
index c29cd0f..a04e801 100644
--- a/matlab/geographiclib/geoddoc.m
+++ b/matlab/geographiclib/geoddoc.m
@@ -88,8 +88,6 @@ function geoddoc
 %
 %   Restrictions on the inputs:
 %     * All latitudes must lie in [-90, 90].
-%     * All longitudes and azimuths must lie in [-540, 540).  On output,
-%       these quantities lie in [-180, 180).
 %     * The distance s12 is unrestricted.  This allows geodesics to wrap
 %       around the ellipsoid.  Such geodesics are no longer shortest paths.
 %       However they retain the property that they are the straightest
diff --git a/matlab/geographiclib/geodreckon.m b/matlab/geographiclib/geodreckon.m
index 0d169e9..62c757b 100644
--- a/matlab/geographiclib/geodreckon.m
+++ b/matlab/geographiclib/geodreckon.m
@@ -33,9 +33,7 @@ function [lat2, lon2, azi2, S12, m12, M12, M21, a12_s12] = geodreckon ...
 %   If long_unroll is unset (the default), then the value lon2 is in the
 %   range [-180,180).  If long_unroll is set, the longitude is "unrolled"
 %   so that the quantity lon2 - lon1 indicates how many times and in what
-%   sense the geodesic encircles the ellipsoid.  Because lon2 might be
-%   outside the normal allowed range for longitudes, [-540, 540), be sure
-%   to normalize it with rem(lon2, 360) before using it in other calls.
+%   sense the geodesic encircles the ellipsoid.
 %
 %   The two optional arguments, ellipsoid and flags, may be given in any
 %   order and either or both may be omitted.
@@ -71,7 +69,7 @@ function [lat2, lon2, azi2, S12, m12, M12, M21, a12_s12] = geodreckon ...
 
 % Copyright (c) Charles Karney (2012-2015) <charles at karney.com>.
 %
-% This file was distributed with GeographicLib 1.43.
+% This file was distributed with GeographicLib 1.44.
 %
 % This is a straightforward transcription of the C++ implementation in
 % GeographicLib and the C++ source should be consulted for additional
@@ -111,6 +109,7 @@ function [lat2, lon2, azi2, S12, m12, M12, M21, a12_s12] = geodreckon ...
   end
   arcmode = bitand(flags, 1);
   long_unroll = bitand(flags, 2);
+  Z = zeros(prod(S),1);
 
   degree = pi/180;
   tiny = sqrt(realmin);
@@ -130,17 +129,14 @@ function [lat2, lon2, azi2, S12, m12, M12, M21, a12_s12] = geodreckon ...
   A3x = A3coeff(n);
   C3x = C3coeff(n);
 
-  lat1 = lat1(:);
+  lat1 = AngRound(LatFix(lat1(:)));
   lon1 = lon1(:);
-  azi1 = AngRound(AngNormalize(azi1(:)));
+  azi1 = AngRound(azi1(:));
   s12_a12 = s12_a12(:);
 
-  alp1 = azi1 * degree;
-  salp1 = sin(alp1); salp1(azi1 == -180) = 0;
-  calp1 = cos(alp1); calp1(abs(azi1) == 90) = 0;
-  phi = lat1 * degree;
-  sbet1 = f1 * sin(phi);
-  cbet1 = cos(phi); cbet1(abs(lat1) == 90) = tiny;
+  [salp1, calp1] = sincosdx(azi1);
+  [sbet1, cbet1] = sincosdx(lat1);
+  sbet1 = f1 * sbet1; cbet1 = max(tiny, cbet1);
   [sbet1, cbet1] = norm2(sbet1, cbet1);
   dn1 = sqrt(1 + ep2 * sbet1.^2);
 
@@ -164,12 +160,7 @@ function [lat2, lon2, azi2, S12, m12, M12, M21, a12_s12] = geodreckon ...
 
   if arcmode
     sig12 = s12_a12 * degree;
-    ssig12 = sin(sig12);
-    csig12 = cos(sig12);
-    s12a = abs(s12_a12);
-    s12a = s12a - 180 * floor(s12a / 180);
-    ssig12(s12a == 0) = 0;
-    csig12(s12a == 90) = 0;
+    [ssig12, csig12] = sincosdx(s12_a12);
   else
     tau12 = s12_a12 ./ (b * (1 + A1m1));
     s = sin(tau12); c = cos(tau12);
@@ -216,16 +207,17 @@ function [lat2, lon2, azi2, S12, m12, M12, M21, a12_s12] = geodreckon ...
   if long_unroll
     lon2 = lon1 + lon12;
   else
-    lon12 = AngNormalize2(lon12);
+    lon12 = AngNormalize(lon12);
     lon2 = AngNormalize(AngNormalize(lon1) + lon12);
   end
-  lat2 = atan2(sbet2, f1 * cbet2) / degree;
-  azi2 = 0 - atan2(-salp2, calp2) / degree;
+  lat2 = atan2dx(sbet2, f1 * cbet2);
+  azi2 = atan2dx(salp2, calp2);
   if arcmode
     a12_s12 = b * ((1 + A1m1) .* sig12 + AB1);
   else
     a12_s12 = sig12 / degree;
   end
+  a12_s12 = reshape(a12_s12 + Z, S);
 
   if redlp || scalp
     A2m1 = A2m1f(epsi);
@@ -237,13 +229,13 @@ function [lat2, lon2, azi2, S12, m12, M12, M21, a12_s12] = geodreckon ...
     if redlp
       m12 = b * ((dn2 .* (csig1 .* ssig2) - dn1 .* (ssig1 .* csig2)) ...
                  - csig1 .* csig2 .* J12);
-      m12 = reshape(m12, S);
+      m12 = reshape(m12 + Z, S);
     end
     if scalp
       t = k2 .* (ssig2 - ssig1) .* (ssig2 + ssig1) ./ (dn1 + dn2);
       M12 = csig12 + (t .* ssig2 - csig2 .* J12) .* ssig1 ./ dn1;
       M21 = csig12 - (t .* ssig1 - csig1 .* J12) .* ssig2 ./  dn2;
-      M12 = reshape(M12, S); M21 = reshape(M21, S);
+      M12 = reshape(M12 + Z, S); M21 = reshape(M21 + Z, S);
     end
   end
 
@@ -258,6 +250,8 @@ function [lat2, lon2, azi2, S12, m12, M12, M21, a12_s12] = geodreckon ...
                    ssig12 .* (csig1 .* ssig12 ./ (1 + csig12) + ssig1), ...
                    csig12 <= 0);
     calp12 = salp0.^2 + calp0.^2 .* csig1 .* csig2;
+    % Enlarge salp1, calp1 is case lat1 is an array and azi1 is a scalar
+    s = zeros(size(salp0)); salp1 = salp1 + s; calp1 = calp1 + s;
     s = calp0 == 0 | salp0 == 0;
     salp12(s) = salp2(s) .* calp1(s) - calp2(s) .* salp1(s);
     calp12(s) = calp2(s) .* calp1(s) + salp2(s) .* salp1(s);
@@ -269,10 +263,11 @@ function [lat2, lon2, azi2, S12, m12, M12, M21, a12_s12] = geodreckon ...
       c2 = a^2;
     end
     S12 = c2 * atan2(salp12, calp12) + A4 .* (B42 - B41);
+    S12 = reshape(S12 + Z, S);
   end
 
-  lat2 = reshape(lat2, S);
+  lat2 = reshape(lat2 + Z, S);
   lon2 = reshape(lon2, S);
-  azi2 = reshape(azi2, S);
+  azi2 = reshape(azi2 + Z, S);
 
 end
diff --git a/matlab/geographiclib/geoid_height.m b/matlab/geographiclib/geoid_height.m
index 495e066..814f710 100644
--- a/matlab/geographiclib/geoid_height.m
+++ b/matlab/geographiclib/geoid_height.m
@@ -70,7 +70,7 @@ function N = geoid_height(lat, lon, geoidname, geoiddir)
   end
   narginchk(2, 4)
   if nargin == 3 && isstruct(geoidname)
-    N = geoid_height_int(lat, lon, geoidname);
+    N = geoid_height_int(lat, lon, geoidname, true);
   else
     if nargin < 3
       geoidname = '';
@@ -82,7 +82,7 @@ function N = geoid_height(lat, lon, geoidname, geoiddir)
     if ~(isstruct(saved_geoid) && strcmp(saved_geoid.file, geoidfile))
       saved_geoid = geoid_load_file(geoidfile);
     end
-    N = geoid_height_int(lat, lon, saved_geoid);
+    N = geoid_height_int(lat, lon, saved_geoid, true);
   end
 end
 
@@ -129,7 +129,6 @@ function N = geoid_height_int(lat, lon, geoid, cubic)
            -18,   36,  -64,   0,   66,   51, 0,   0, -102,  31;...
             18,  -36,    2,   0,  -66,  -51, 0,   0,  102,  31];
   end
-  if nargin < 4, cubic = true; end
   try
     s = size(lat + lon);
   catch
@@ -166,7 +165,7 @@ function N = geoid_height_int(lat, lon, geoid, cubic)
             2);
   end
   N = geoid.offset + geoid.scale * N;
-  N(~(abs(lat) <= 90 & abs(lon) <= 540)) = nan;
+  N(~(abs(lat) <= 90 & isfinite(lon))) = nan;
   N = reshape(N, s);
 end
 
diff --git a/matlab/geographiclib/gereckon.m b/matlab/geographiclib/gereckon.m
index 1fce932..c2913ce 100644
--- a/matlab/geographiclib/gereckon.m
+++ b/matlab/geographiclib/gereckon.m
@@ -45,8 +45,8 @@ function [lat2, lon2, azi2, S12] = gereckon(lat1, lon1, s12, azi1, ellipsoid)
     error('ellipsoid must be a vector of size 2')
   end
 
-  degree = pi/180;
   tiny = sqrt(realmin);
+  Z = zeros(prod(S),1);
 
   a = ellipsoid(1);
   e2 = ellipsoid(2)^2;
@@ -55,17 +55,14 @@ function [lat2, lon2, azi2, S12] = gereckon(lat1, lon1, s12, azi1, ellipsoid)
 
   areap = nargout >= 4;
 
-  lat1 = lat1(:);
-  lon1 = AngNormalize(lon1(:));
-  azi1 = AngRound(AngNormalize(azi1(:)));
+  lat1 = AngRound(LatFix(lat1(:)));
+  lon1 = lon1(:);
+  azi1 = AngRound(azi1(:));
   s12 = s12(:);
 
-  alp1 = azi1 * degree;
-  sgam1 = sin(alp1); sgam1(azi1 == -180) = 0;
-  cgam1 = cos(alp1); cgam1(abs(azi1) == 90) = 0;
-  phi = lat1 * degree;
-  sbet1 = f1 * sin(phi);
-  cbet1 = cos(phi); cbet1(abs(lat1) == 90) = tiny;
+  [sgam1, cgam1] = sincosdx(azi1);
+  [sbet1, cbet1] = sincosdx(lat1);
+  sbet1 = f1 * sbet1; cbet1 = max(tiny, cbet1);
   [sbet1, cbet1] = norm2(sbet1, cbet1);
   [sgam1, cgam1] = norm2(sgam1 .* sqrt(1 - e2 * cbet1.^2), cgam1);
   sgam0 = sgam1 .* cbet1; cgam0 = hypot(cgam1, sgam1 .* sbet1);
@@ -104,17 +101,15 @@ function [lat2, lon2, azi2, S12] = gereckon(lat1, lon1, s12, azi1, ellipsoid)
   cbet2(cbet2 == 0) = tiny;
   slam2 = sgam0 .* ssig2; clam2 = csig2;
   sgam2 = sgam0; cgam2 = cgam0 .* csig2;
-  lam12 = atan2(slam2 .* clam1 - clam2 .* slam1, ...
-                clam2 .* clam1 + slam2 .* slam1);
-  lon12 = lam12 / degree;
-  lon12 = AngNormalize2(lon12);
-  lon2 = AngNormalize(lon1 + lon12);
-  lat2 = atan2(sbet2, f1 * cbet2) / degree;
-  azi2 = 0 - atan2(-sgam2, cgam2 .* sqrt(1 - e2 * cbet2.^2)) / degree;
+  lon12 = atan2dx(slam2 .* clam1 - clam2 .* slam1, ...
+                  clam2 .* clam1 + slam2 .* slam1);
+  lon2 = AngNormalize(AngNormalize(lon1) + lon12);
+  lat2 = atan2dx(sbet2, f1 * cbet2);
+  azi2 = atan2dx(sgam2, cgam2 .* sqrt(1 - e2 * cbet2.^2));
 
-  lat2 = reshape(lat2, S);
+  lat2 = reshape(lat2 + Z, S);
   lon2 = reshape(lon2, S);
-  azi2 = reshape(azi2, S);
+  azi2 = reshape(azi2 + Z, S);
 
   if areap
     n = f / (2 - f);
@@ -139,6 +134,7 @@ function [lat2, lon2, azi2, S12] = gereckon(lat1, lon1, s12, azi1, ellipsoid)
       c2 = a^2;
     end
     S12 = c2 * atan2(sgam12, cgam12) + A4 .* (B42 - B41);
+    S12 = reshape(S12 + Z, S);
   end
 
 end
diff --git a/matlab/geographiclib/gnomonic_fwd.m b/matlab/geographiclib/gnomonic_fwd.m
index efb5efc..3690be0 100644
--- a/matlab/geographiclib/gnomonic_fwd.m
+++ b/matlab/geographiclib/gnomonic_fwd.m
@@ -44,7 +44,7 @@ function [x, y, azi, rk] = gnomonic_fwd(lat0, lon0, lat, lon, ellipsoid)
 
 % Copyright (c) Charles Karney (2012-2015) <charles at karney.com>.
 %
-% This file was distributed with GeographicLib 1.42.
+% This file was distributed with GeographicLib 1.44.
 
   narginchk(4, 5)
   if nargin < 5, ellipsoid = defaultellipsoid; end
@@ -56,10 +56,10 @@ function [x, y, azi, rk] = gnomonic_fwd(lat0, lon0, lat, lon, ellipsoid)
 
   [~, azi0, azi, ~, m, M] = geoddistance(lat0, lon0, lat, lon, ellipsoid);
   rho = m ./ M;
-  azi0 = azi0 * (pi/180);
-  x = rho .* sin(azi0);
-  y = rho .* cos(azi0);
+  [x, y] = sincosdx(azi0);
+  x = rho .* x;
+  y = rho .* y;
   rk = M;
-  x(M <= 0) = NaN;
-  y(M <= 0) = NaN;
+  x(M <= 0) = nan;
+  y(M <= 0) = nan;
 end
diff --git a/matlab/geographiclib/gnomonic_inv.m b/matlab/geographiclib/gnomonic_inv.m
index 100877d..3a5edd1 100644
--- a/matlab/geographiclib/gnomonic_inv.m
+++ b/matlab/geographiclib/gnomonic_inv.m
@@ -45,7 +45,7 @@ function [lat, lon, azi, rk] = gnomonic_inv(lat0, lon0, x, y, ellipsoid)
 
 % Copyright (c) Charles Karney (2012-2015) <charles at karney.com>.
 %
-% This file was distributed with GeographicLib 1.42.
+% This file was distributed with GeographicLib 1.44.
 
   narginchk(4, 5)
   if nargin < 5, ellipsoid = defaultellipsoid; end
@@ -62,7 +62,7 @@ function [lat, lon, azi, rk] = gnomonic_inv(lat0, lon0, x, y, ellipsoid)
   eps1 = a * 0.01 * sqrt(eps);
 
   lat0 = lat0 + Z; lon0 = lon0 + Z; x = x + Z; y = y + Z;
-  azi0 = atan2(x, y) / (pi/180);
+  azi0 = atan2dx(x, y);
   rho = hypot(x, y);
   s = a * atan(rho / a);
   little = rho <= a;
@@ -83,10 +83,10 @@ function [lat, lon, azi, rk] = gnomonic_inv(lat0, lon0, x, y, ellipsoid)
   end
   c = ~trip;
   if any(c)
-    lat(c) = NaN;
-    lon(c) = NaN;
-    azi(c) = NaN;
-    M(c) = NaN;
+    lat(c) = nan;
+    lon(c) = nan;
+    azi(c) = nan;
+    M(c) = nan;
   end
   rk = M;
 end
diff --git a/matlab/geographiclib/mgrs_fwd.m b/matlab/geographiclib/mgrs_fwd.m
index 84858f4..56f1dee 100644
--- a/matlab/geographiclib/mgrs_fwd.m
+++ b/matlab/geographiclib/mgrs_fwd.m
@@ -11,11 +11,12 @@ function mgrs = mgrs_fwd(x, y, zone, isnorth, prec)
 %   giving 1 m precision.  For example, prec = 2 corresponding to 1 km
 %   precision, returns a string such as 38SMB4488.  A value of -1 means
 %   that only the grid zone, e.g., 38S, is returned.  The maximum allowed
-%   value of prec is 11 (denoting 1 um precision).  The MGRS references are
-%   returned in a cell array of strings.  x, y, zone, isnorth, prec can be
-%   scalars or arrays of the same size.  Values that can't be converted to
-%   MGRS return the "invalid" string, INV.  The inverse operation is
-%   performed by mgrs_inv.
+%   value of prec is 11 (denoting 1 um precision).  prec < -1 is treated a
+%   NaN, while prec > 11 is treated the same as prec = 11.  The MGRS
+%   references are returned in a cell array of strings.  x, y, zone,
+%   isnorth, prec can be scalars or arrays of the same size.  Values that
+%   can't be converted to MGRS return the "invalid" string, INV.  The
+%   inverse operation is performed by mgrs_inv.
 %
 %   The allowed values of (x,y) are
 %        UTM: x in [100 km, 900 km]
@@ -36,7 +37,7 @@ function mgrs = mgrs_fwd(x, y, zone, isnorth, prec)
   narginchk(4, 5)
   if nargin < 5, prec = 5; end
   zone = floor(zone);
-  prec = floor(prec);
+  prec = min(11, max(-2, floor(prec))); % this converts NaNs to -2.
   try
     s = size(x + y + zone + isnorth + prec);
   catch
@@ -47,7 +48,6 @@ function mgrs = mgrs_fwd(x, y, zone, isnorth, prec)
   Z = zeros(num, 1);
   x = x(:) + Z; y = y(:) + Z; zone = zone(:) + Z;
   isnorth = isnorth(:) + Z; prec = prec(:) + Z;
-  prec(~(prec >= -1 & prec <= 11)) = -2;
   mgrs = repmat('INV', num, 1);
   if ~any(prec >= -1), mgrs = reshape(cellstr(mgrs), s); return, end
   maxprec = max(prec);
@@ -110,12 +110,12 @@ function mgrs = mgrs_fwd_utm(x, y, zone, prec)
   band(c) = LatitudeBand(utmups_inv(x(c), y(c), zone(c), 1));
   mgrs(:,3) = latband(band + 11);
   if prec < 0, return, end
-  xh = floor(x / 1e5); yh = floor(y / 1e5);
+  x = floor(x * 1e6); y = floor(y * 1e6);
+  xh = floor(x / 1e11); yh = floor(y / 1e11);
   mgrs(:,4) = utmcols(mod(zone - 1, 3) * 8 + xh);
   mgrs(:,5) = utmrow(mod(yh + mod(zone - 1, 2) * 5, 20) + 1);
   if prec == 0, return, end
-  x = x - 1e5 * xh; y = y - 1e5 * yh;
-  xy = formatnum(x, y, prec);
+  xy = formatnum(x, xh, y, yh, prec);
   mgrs(:,5+(1:2*prec)) = xy;
 end
 
@@ -128,16 +128,15 @@ function mgrs = mgrs_fwd_upsn(x, y, prec)
   end
   mgrs = char(zeros(length(x), 3 + 2 * prec) + ' ');
   if isempty(x), return, end
-  xh = floor(x / 1e5);
+  x = floor(x * 1e6); y = floor(y * 1e6);
+  xh = floor(x / 1e11); yh = floor(y / 1e11);
   eastp = xh >= 20;
   mgrs(:,1) = upsband(eastp + 1);
   if prec < 0, return, end
-  yh = floor(y / 1e5);
   mgrs(:,2) = upscols(eastp * 7 + xh - cvmgt(20, 13, eastp) + 1);
   mgrs(:,3) = upsrow(yh - 13 + 1);
   if prec == 0, return, end
-  x = x - 1e5 * xh; y = y - 1e5 * yh;
-  xy = formatnum(x, y, prec);
+  xy = formatnum(x, xh, y, yh, prec);
   mgrs(:,3+(1:2*prec)) = xy;
 end
 
@@ -150,27 +149,24 @@ function mgrs = mgrs_fwd_upss(x, y, prec)
   end
   mgrs = char(zeros(length(x), 3 + 2 * prec) + ' ');
   if isempty(x), return, end
-  xh = floor(x / 1e5);
+  x = floor(x * 1e6); y = floor(y * 1e6);
+  xh = floor(x / 1e11); yh = floor(y / 1e11);
   eastp = xh >= 20;
   mgrs(:,1) = upsband(eastp + 1);
   if prec < 0, return, end
-  yh = floor(y / 1e5);
   mgrs(:,2) = upscols(eastp * 12 + xh - cvmgt(20, 8, eastp) + 1);
   mgrs(:,3) = upsrow(yh - 8 + 1);
   if prec == 0, return, end
-  x = x - 1e5 * xh; y = y - 1e5 * yh;
-  xy = formatnum(x, y, prec);
+  xy = formatnum(x, xh, y, yh, prec);
   mgrs(:,3+(1:2*prec)) = xy;
 end
 
-function xy = formatnum(x, y, prec)
-  if (prec < 5)
-    x = x / 10 ^ (5 - prec); y = y / 10 ^ (5 - prec);
-  elseif (prec > 5)
-    x = x * 10 ^ (prec - 5); y = y * 10 ^ (prec - 5);
-  end
-  xy = [num2str(floor(x), ['%0', int2str(prec), 'd']), ...
-        num2str(floor(y), ['%0', int2str(prec), 'd'])];
+function xy = formatnum(x, xh, y, yh, prec)
+  x = x - xh * 1e11; y = y - yh * 1e11;
+  d = 10 ^ (11 - prec);
+  x = floor(x / d); y = floor(y / d);
+  xy = [num2str(x, ['%0', int2str(prec), 'd']), ...
+        num2str(y, ['%0', int2str(prec), 'd'])];
 end
 
 function band = LatitudeBand(lat)
diff --git a/matlab/geographiclib/mgrs_inv.m b/matlab/geographiclib/mgrs_inv.m
index 4547101..eb1c7d7 100644
--- a/matlab/geographiclib/mgrs_inv.m
+++ b/matlab/geographiclib/mgrs_inv.m
@@ -92,18 +92,15 @@ function [x, y, zone, northp, prec] = mgrs_inv_utm(mgrs, center)
   rowind(even) = mod(rowind(even) - 5, 20);
   % good values in [0,20), bad values = -1
   rowind(bad) = -1;
-  [x, y, prec] = decodexy(mgrs(:, 6:end), center);
+  rowfix = fixutmrow(band, colind, rowind);
+  [x, y, prec] = decodexy(mgrs(:, 6:end), ...
+                          colind + 1, rowfix + (1-northp) * 100, center);
   prec(mgrs(:,4) == ' ') = -1;
-  ok = ok & (prec == -1 | (colind >= 0 & rowind >= 0));
-  rowind = fixutmrow(band, colind, rowind);
-  colind = colind + 1;
-  x = colind * 1e5 + x;
-  y = rowind * 1e5 + y + (1-northp) * 100e5;
-  x(prec == -1) = ...
-          (5 - (zone(prec == -1) == 31 & band(prec == -1) == 7)) * 1e5;
-  y(prec == -1) = ...
-          floor(8 * (band(prec == -1) + 0.5) * 100/90 + 0.5) * 1e5 + ...
-          (1- northp(prec == -1)) * 100e5;
+  zoneonly = prec == -1;
+  ok = ok & (zoneonly | (colind >= 0 & rowind >= 0 & rowfix < 100));
+  x(zoneonly) = (5 - (zone(zoneonly) == 31 & band(zoneonly) == 7)) * 1e5;
+  y(zoneonly) = floor(8 * (band(zoneonly) + 0.5) * 100/90 + 0.5) * 1e5 + ...
+      (1- northp(zoneonly)) * 100e5;
   x(~ok) = nan;
   y(~ok) = nan;
   northp(~ok) = false;
@@ -126,14 +123,14 @@ function [x, y, zone, northp, prec] = mgrs_inv_upsn(mgrs, center)
   colind = lookup(upscols, mgrs(:, 2));
   ok = ok & (colind < 0 | mod(floor(colind / 7) + eastp, 2) == 0);
   rowind = lookup(upsrow, mgrs(:, 3));
-  [x, y, prec] = decodexy(mgrs(:, 4:end), center);
+  rowind = rowind + 13;
+  colind = colind + 13;
+  [x, y, prec] = decodexy(mgrs(:, 4:end), colind, rowind, center);
   prec(mgrs(:,2) == ' ') = -1;
-  ok = ok & (prec == -1 | (colind >= 0 & rowind >= 0));
-  x = (colind + 13) * 1e5 + x;
-  y = (rowind + 13) * 1e5 + y;
-  x(prec == -1) = ((2*eastp(prec == -1) - 1) * ...
-                   floor(4 * 100/90 + 0.5) + 20) * 1e5;
-  y(prec == -1) = 20e5;
+  zoneonly = prec == -1;
+  ok = ok & (zoneonly | (colind >= 0 & rowind >= 0));
+  x(zoneonly) = ((2*eastp(zoneonly) - 1) * floor(4 * 100/90 + 0.5) + 20) * 1e5;
+  y(zoneonly) = 20e5;
   x(~ok) = nan;
   y(~ok) = nan;
   northp(~ok) = false;
@@ -160,36 +157,52 @@ function [x, y, zone, northp, prec] = mgrs_inv_upss(mgrs, center)
   colind(eastp & colind < 12) = -1;
   ok = ok & (colind < 0 | mod(floor(colind / 12) + eastp, 2) == 0);
   rowind = lookup(upsrow, mgrs(:, 3));
-  [x, y, prec] = decodexy(mgrs(:, 4:end), center);
+  rowind = rowind + 8;
+  colind = colind + 8;
+  [x, y, prec] = decodexy(mgrs(:, 4:end), colind, rowind, center);
   prec(mgrs(:,2) == ' ') = -1;
-  ok = ok & (prec == -1 | (colind >= 0 & rowind >= 0));
-  x = (colind + 8) * 1e5 + x;
-  y = (rowind + 8) * 1e5 + y;
-  x(prec == -1) = ((2*eastp(prec == -1) - 1) * ...
-                   floor(4 * 100/90 + 0.5) + 20) * 1e5;
-  y(prec == -1) = 20e5;
+  zoneonly = prec == -1;
+  ok = ok & (zoneonly | (colind >= 0 & rowind >= 0));
+  x(zoneonly) = ((2*eastp(zoneonly) - 1) * floor(4 * 100/90 + 0.5) + 20) * 1e5;
+  y(zoneonly) = 20e5;
   x(~ok) = nan;
   y(~ok) = nan;
   zone(~ok) = -4;
   prec(~ok) = -2;
 end
 
-function [x, y, prec] = decodexy(xy, center)
+function [x, y, prec] = decodexy(xy, xh, yh, center)
   num = size(xy, 1);
   x = nan(num, 1); y = x;
   len = strlen(xy);
   prec = len / 2;
   digits = sum(isspace(xy) | isstrprop(xy, 'digit'), 2) == size(xy, 2);
-  ok = len < 22 & mod(len, 2) == 0 & digits;
+  ok = len <= 22 & mod(len, 2) == 0 & digits;
   prec(~ok) = -2;
   if ~any(ok), return, end
-  x(prec == 0) = 0.5e5; y(prec == 0) = 0.5e5;
+  cent = center * 0.5;
+  in = prec == 0;
+  if any(in)
+    x(in) = (xh(in) + cent) * 1e5; y(in) = (yh(in) + cent) * 1e5;
+  end
   minprec = max(1,min(prec(ok))); maxprec = max(prec(ok));
   for p = minprec:maxprec
-    m = 1e5 / 10^p;
-    cent = center * m/2;
-    x(prec == p) = str2double(cellstr(xy(prec == p, 0+(1:p)))) * m + cent;
-    y(prec == p) = str2double(cellstr(xy(prec == p, p+(1:p)))) * m + cent;
+    in = prec == p;
+    if ~any(in)
+      continue
+    end
+    m = 10^p;
+    x(in) = xh(in) * m + str2double(cellstr(xy(in, 0+(1:p)))) + cent;
+    y(in) = yh(in) * m + str2double(cellstr(xy(in, p+(1:p)))) + cent;
+    if p < 5
+      m = 1e5 / m;
+      x(in) = x(in) * m;
+      y(in) = y(in) * m;
+    elseif p > 5
+      m = m / 1e5;
+      x(in) = x(in) / m;
+      y(in) = y(in) / m;
+    end
   end
 end
 
diff --git a/matlab/geographiclib/polarst_fwd.m b/matlab/geographiclib/polarst_fwd.m
index 48fa39c..a05e01c 100644
--- a/matlab/geographiclib/polarst_fwd.m
+++ b/matlab/geographiclib/polarst_fwd.m
@@ -26,12 +26,12 @@ function [x, y, gam, k] = polarst_fwd(isnorth, lat, lon, ellipsoid)
 
 % Copyright (c) Charles Karney (2015) <charles at karney.com>.
 %
-% This file was distributed with GeographicLib 1.42.
+% This file was distributed with GeographicLib 1.44.
 
   narginchk(3, 4)
   if nargin < 4, ellipsoid = defaultellipsoid; end
   try
-    [~] = isnorth + lat + lon;
+    Z = zeros(size(isnorth + lat + lon));
   catch
     error('isnorth, lat, lon have incompatible sizes')
   end
@@ -39,7 +39,6 @@ function [x, y, gam, k] = polarst_fwd(isnorth, lat, lon, ellipsoid)
     error('ellipsoid must be a vector of size 2')
   end
 
-  degree = pi/180;
   overflow = 1/eps^2;
   a = ellipsoid(1);
   e2 = ellipsoid(2)^2;
@@ -47,22 +46,20 @@ function [x, y, gam, k] = polarst_fwd(isnorth, lat, lon, ellipsoid)
   c = sqrt(e2m) * exp(eatanhe(1, e2));
 
   isnorth = 2 * logical(isnorth) - 1;
-  lat = lat .* isnorth;
-  phi = lat * degree;
-  lam = AngNormalize(lon) .* degree;
-  tau = tan(phi); tau(abs(lat) == 90) = sign(lat(abs(lat) == 90)) * overflow;
+  lat = LatFix(lat) .* isnorth;
+  tau = tand(lat); tau(abs(lat) == 90) = sign(lat(abs(lat) == 90)) * overflow;
   taup = taupf(tau, e2);
   rho = hypot(1, taup) + abs(taup);
   rho(taup >= 0) = cvmgt(1./rho(taup >= 0), 0, lat(taup >= 0) ~= 90);
   rho = rho * (2 * a / c);
-  lon = AngNormalize(lon);
-  x = rho .* sin(lam); x(lon == -180) = 0;
-  y = -isnorth .* rho .* cos(lam); x(abs(lon) == 90) = 0;
+  [x, y] = sincosdx(lon);
+  x = rho .* x;
+  y = -isnorth .* rho .* y;
   if nargout > 2
-    gam = isnorth .* lon;
+    gam = AngNormalize(isnorth .* lon) + Z;
     if nargout > 3
       secphi = hypot(1, tau);
-      k = (rho / a) .* secphi .* sqrt(e2m + e2 .* secphi.^-2);
+      k = (rho / a) .* secphi .* sqrt(e2m + e2 .* secphi.^-2) + Z;
       k(lat == 90) = 1;
     end
   end
diff --git a/matlab/geographiclib/polarst_inv.m b/matlab/geographiclib/polarst_inv.m
index e8b5f01..d20611b 100644
--- a/matlab/geographiclib/polarst_inv.m
+++ b/matlab/geographiclib/polarst_inv.m
@@ -26,12 +26,12 @@ function [lat, lon, gam, k] = polarst_inv(isnorth, x, y, ellipsoid)
 
 % Copyright (c) Charles Karney (2015) <charles at karney.com>.
 %
-% This file was distributed with GeographicLib 1.42.
+% This file was distributed with GeographicLib 1.44.
 
   narginchk(3, 4)
   if nargin < 4, ellipsoid = defaultellipsoid; end
   try
-    [~] = isnorth + x + y;
+    Z = zeros(size(isnorth + x + y));
   catch
     error('isnorth, x, y have incompatible sizes')
   end
@@ -39,7 +39,6 @@ function [lat, lon, gam, k] = polarst_inv(isnorth, x, y, ellipsoid)
     error('ellipsoid must be a vector of size 2')
   end
 
-  degree = pi/180;
   a = ellipsoid(1);
   e2 = ellipsoid(2)^2;
   e2m = 1 - e2;
@@ -50,16 +49,15 @@ function [lat, lon, gam, k] = polarst_inv(isnorth, x, y, ellipsoid)
   t = rho / (2 * a / c);
   taup = (1 ./ t - t) / 2;
   tau = tauf(taup, e2);
-  phi = atan(tau);
-  lat =  phi / degree;
+  lat = atand(tau);
   lat(rho == 0) = 90;
   lat = isnorth .* lat;
-  lon = 0 - atan2( -x, -isnorth .* y) / degree;
+  lon = atan2dx(x, -isnorth .* y);
   if nargout > 2
-    gam = isnorth .* lon;
+    gam = AngNormalize(isnorth .* lon);
     if nargout > 3
       secphi = hypot(1, tau);
-      k = (rho / a) .* secphi .* sqrt(e2m + e2 .* secphi.^-2);
+      k = (rho / a) .* secphi .* sqrt(e2m + e2 .* secphi.^-2) + Z;
       k(rho == 0) = 1;
     end
   end
diff --git a/matlab/geographiclib/private/A2m1f.m b/matlab/geographiclib/private/A2m1f.m
index dff4099..c89b1ae 100644
--- a/matlab/geographiclib/private/A2m1f.m
+++ b/matlab/geographiclib/private/A2m1f.m
@@ -7,10 +7,10 @@ function A2m1 = A2m1f(epsi)
   persistent coeff
   if isempty(coeff)
     coeff = [ ...
-        25, 36, 64, 0, 256, ...
+        -11, -28, -192, 0, 256, ...
             ];
   end
   eps2 = epsi.^2;
   t = polyval(coeff(1 : end - 1), eps2) / coeff(end);
-  A2m1 = t .* (1 - epsi) - epsi;
+  A2m1 = (t - epsi) ./ (1 + epsi);
 end
diff --git a/matlab/geographiclib/private/AngDiff.m b/matlab/geographiclib/private/AngDiff.m
index 60d1bbf..6b2c420 100644
--- a/matlab/geographiclib/private/AngDiff.m
+++ b/matlab/geographiclib/private/AngDiff.m
@@ -5,9 +5,8 @@ function d = AngDiff(x, y)
 %   rounds the result.  x and y must be in [-180,180].  x and y can be any
 %   compatible shapes.
 
-  [d, t] = sumx(-x, y);
-  c = (d - 180) + t > 0;
-  d(c) = (d(c) - 360) + t(c);
-  c = (d + 180) + t <= 0;
-  d(c) = (d(c) + 360) + t(c);
+  [d, t] = sumx(AngNormalize(x), AngNormalize(-y));
+  d = - AngNormalize(d);
+  d(d == 180 & t < 0) = -180;
+  d = d - t;
 end
diff --git a/matlab/geographiclib/private/AngNormalize.m b/matlab/geographiclib/private/AngNormalize.m
index 28f42bb..8027ffc 100644
--- a/matlab/geographiclib/private/AngNormalize.m
+++ b/matlab/geographiclib/private/AngNormalize.m
@@ -1,9 +1,10 @@
 function x = AngNormalize(x)
 %ANGNORMALIZE  Reduce angle to range [-180, 180)
 %
-%   x = ANGNORMALIZE(x) reduces angles in [-540, 540) to the range
-%   [-180, 180).  x can be any shape.
+%   x = ANGNORMALIZE(x) reduces angles to the range [-180, 180).  x can be
+%   any shape.
 
+  x = rem(x, 360);
   x(x >= 180) = x(x >= 180) - 360;
   x(x < -180) = x(x < -180) + 360;
 end
diff --git a/matlab/geographiclib/private/AngNormalize2.m b/matlab/geographiclib/private/AngNormalize2.m
deleted file mode 100644
index 6c89f98..0000000
--- a/matlab/geographiclib/private/AngNormalize2.m
+++ /dev/null
@@ -1,8 +0,0 @@
-function x = AngNormalize2(x)
-%ANGNORMALIZE2  Reduce any angle to range [-180, 180)
-%
-%   x = ANGNORMALIZE(x) reduces arbitrary angles to the range [-180, 180).
-%   x can be any shape.
-
-  x = AngNormalize(rem(x, 360));
-end
diff --git a/matlab/geographiclib/private/C1pf.m b/matlab/geographiclib/private/C1pf.m
index 0f1b4d7..a753a29 100644
--- a/matlab/geographiclib/private/C1pf.m
+++ b/matlab/geographiclib/private/C1pf.m
@@ -1,8 +1,8 @@
 function C1p = C1pf(epsi)
 %C1PF  Evaluate C'_{1,k}
 %
-%   C1p = C1PF(epsi) evaluates C'_{1,l} using Eq. (21).  epsi is an
-%   K x 1 array and C1 is a K x 6 array.
+%   C1p = C1PF(epsi) evaluates C'_{1,l} using Eq. (21).  epsi is a K x 1
+%   array and C1 is a K x 6 array.
 
   persistent coeff nC1p
   if isempty(coeff)
diff --git a/matlab/geographiclib/private/C2f.m b/matlab/geographiclib/private/C2f.m
index bc62f8d..1981e79 100644
--- a/matlab/geographiclib/private/C2f.m
+++ b/matlab/geographiclib/private/C2f.m
@@ -1,8 +1,8 @@
 function C2 = C2f(epsi)
 %C2F  Evaluate C_{2,k}
 %
-%   C2 = C2F(epsi) evaluates C_{2,l} using Eq. (43).  epsi is an
-%   K x 1 array and C2 is a K x 6 array.
+%   C2 = C2F(epsi) evaluates C_{2,l} using Eq. (43).  epsi is a K x 1 array
+%   and C2 is a K x 6 array.
 
   persistent coeff nC2
   if isempty(coeff)
diff --git a/matlab/geographiclib/private/LatFix.m b/matlab/geographiclib/private/LatFix.m
new file mode 100644
index 0000000..75c5d1f
--- /dev/null
+++ b/matlab/geographiclib/private/LatFix.m
@@ -0,0 +1,9 @@
+function y = LatFix(x)
+%LATFIX  Check that latitiude is in [-90, 90]
+%
+%   y = LATFIX(x) returns x is it is in the range [-90, 90]; otherwise it
+%   returns NaN.  x can be any shape.
+
+  y = x;
+  y(abs(x) > 90) = nan;
+end
diff --git a/matlab/geographiclib/private/atan2dx.m b/matlab/geographiclib/private/atan2dx.m
new file mode 100644
index 0000000..30ef64f
--- /dev/null
+++ b/matlab/geographiclib/private/atan2dx.m
@@ -0,0 +1,25 @@
+function z = atan2dx(y, x)
+%ATAN2DX  Compute 2 argument arctangent with result in degrees
+%
+%   z = ATAN2DX(y, x) compute atan2(y, x) with result in degrees in
+%   [-180,180) and quadrant symmetries enforced.
+
+  persistent octavep
+  if isempty(octavep)
+    octavep = exist('OCTAVE_VERSION', 'builtin') ~= 0;
+  end
+  if ~octavep
+    % MATLAB implements symmetries already, just need to fix range
+    z = 0 - atan2d(0 - y, x);
+  else
+    q1 = abs(y) > abs(x); t = y(q1); y(q1) = x(q1); x(q1) = t;
+    q2 = x < 0; x(q2) = -x(q2);
+    q = 2 * q1 + q2;
+    z = atan2(y, x) * (180 / pi);       % z in [-45, 45]
+    % t = q == 0;        z(t) =    0 + z(t);
+    t = q == 1 & y >  0; z(t) =  180 - z(t);
+    t = q == 1 & y <= 0; z(t) = -180 - z(t);
+    t = q == 2;          z(t) =   90 - z(t);
+    t = q == 3;          z(t) =  -90 + z(t);
+  end
+end
diff --git a/matlab/geographiclib/private/sincosdx.m b/matlab/geographiclib/private/sincosdx.m
new file mode 100644
index 0000000..8b265d7
--- /dev/null
+++ b/matlab/geographiclib/private/sincosdx.m
@@ -0,0 +1,27 @@
+function [sinx, cosx] = sincosdx(x)
+%SINCOSDX  Compute sine and cosine with argument in degrees
+%
+%   [sinx, cosx] = SINCOSDX(x) compute sine and cosine of x in degrees with
+%   exact argument reduction and quadrant symmetries enforced.
+
+  persistent octavep
+  if isempty(octavep)
+    octavep = exist('OCTAVE_VERSION', 'builtin') ~= 0;
+  end
+  if ~octavep
+    % MATLAB implements argument reduction and symmetries already
+    sinx = sind(x); cosx = cosd(x);
+  else
+    r = rem(x, 360);
+    % workaround rem's bad handling of -0 in octave; fixed 2015-07-22
+    % http://savannah.gnu.org/bugs/?45587
+    r(x == 0 & signbit(x)) = -0;
+    q = floor(r / 90 + 0.5);
+    r = r - 90 * q;
+    q = mod(q, 4);
+    sinx = sind(r); cosx = cosd(r);
+    t = q == 1; z = 0 - sinx(t); sinx(t) = cosx(t); cosx(t) = z;
+    t = q == 2; sinx(t) = 0 - sinx(t); cosx(t) = 0 - cosx(t);
+    t = q == 3; z = sinx(t); sinx(t) = 0 - cosx(t); cosx(t) = z;
+  end
+end
diff --git a/matlab/geographiclib/projdoc.m b/matlab/geographiclib/projdoc.m
index bc0c0e5..5aafcaa 100644
--- a/matlab/geographiclib/projdoc.m
+++ b/matlab/geographiclib/projdoc.m
@@ -56,8 +56,6 @@ function projdoc
 %
 %   Restrictions on the inputs:
 %     * All latitudes must lie in [-90, 90].
-%     * All longitudes and azimuths must lie in [-540, 540).  On output,
-%       these quantities lie in [-180, 180).
 %     * The equatorial radius, a, must be positive.
 %     * The eccentricity, e, should be satisfy abs(e) < 0.2 in order to
 %       retain full accuracy (this corresponds to flattenings satisfying
diff --git a/matlab/geographiclib/tranmerc_fwd.m b/matlab/geographiclib/tranmerc_fwd.m
index 28b2de7..1f2e356 100644
--- a/matlab/geographiclib/tranmerc_fwd.m
+++ b/matlab/geographiclib/tranmerc_fwd.m
@@ -41,7 +41,7 @@ function [x, y, gam, k] = tranmerc_fwd(lat0, lon0, lat, lon, ellipsoid)
 
 % Copyright (c) Charles Karney (2012-2015) <charles at karney.com>.
 %
-% This file was distributed with GeographicLib 1.43.
+% This file was distributed with GeographicLib 1.44.
 
   narginchk(4, 5)
   if nargin < 5, ellipsoid = defaultellipsoid; end
@@ -54,7 +54,6 @@ function [x, y, gam, k] = tranmerc_fwd(lat0, lon0, lat, lon, ellipsoid)
     error('ellipsoid must be a vector of size 2')
   end
 
-  degree = pi/180;
   maxpow = 6;
 
   a = ellipsoid(1);
@@ -67,29 +66,28 @@ function [x, y, gam, k] = tranmerc_fwd(lat0, lon0, lat, lon, ellipsoid)
   b1 = (1 - f) * (A1m1f(n) + 1);
   a1 = b1 * a;
 
-  lon = AngDiff(AngNormalize(lon0), AngNormalize(lon));
+  lon = AngDiff(lon0, lon);
 
   latsign = 1 - 2 * (lat < 0);
   lonsign = 1 - 2 * (lon < 0);
   lon = lon .* lonsign;
-  lat = lat .* latsign;
+  lat = LatFix(lat) .* latsign;
   backside = lon > 90;
   latsign(backside & lat == 0) = -1;
   lon(backside) = 180 - lon(backside);
-  phi = lat * degree;
-  lam = lon * degree;
-  c = max(0, cos(lam));
-  tau = tan(phi);
+  [sphi, cphi] = sincosdx(lat);
+  [slam, clam] = sincosdx(lon);
+  tau = sphi ./ cphi;
   taup = taupf(tau, e2);
-  xip = atan2(taup, c);
-  etap = asinh(sin(lam) ./ hypot(taup, c));
-  gam = atan(tan(lam) .* taup ./ hypot(1, taup));
-  k = sqrt(e2m + e2 * cos(phi).^2) .* hypot(1, tau) ./ hypot(taup, c);
+  xip = atan2(taup, clam);
+  etap = asinh(slam ./ hypot(taup, clam));
+  gam = atan2dx(slam .* taup, clam .* hypot(1, taup));
+  k = sqrt(e2m + e2 * cphi.^2) .* hypot(1, tau) ./ hypot(taup, clam);
   c = ~(lat ~= 90);
   if any(c)
     xip(c) = pi/2;
     etap(c) = 0;
-    gam(c) = lam;
+    gam(c) = lon;
     k = cc;
   end
   c0 = cos(2 * xip); ch0 = cosh(2 * etap);
@@ -120,21 +118,22 @@ function [x, y, gam, k] = tranmerc_fwd(lat0, lon0, lat, lon, ellipsoid)
   ar = s0 .* ch0; ai = c0 .* sh0;
   xi  = xip  + ar .* xi0 - ai .* eta0;
   eta = etap + ai .* xi0 + ar .* eta0;
-  gam = gam - atan2(yi1, yr1);
+  gam = gam - atan2dx(yi1, yr1);
   k = k .* (b1 * hypot(yr1, yi1));
-  gam = gam / degree;
   xi(backside) = pi - xi(backside);
   y = a1 * xi .* latsign;
   x = a1 * eta .* lonsign;
   gam(backside) = 180 - gam(backside);
-  gam = gam .* latsign .* lonsign;
+  gam = AngNormalize(gam .* latsign .* lonsign);
 
   if isscalar(lat0) && lat0 == 0
     y0 = 0;
   else
-    [sbet0, cbet0] = norm2((1-f) * sind(lat0), cosd(lat0));
+    [sbet0, cbet0] = sincosdx(LatFix(lat0(:)));
+    [sbet0, cbet0] = norm2((1-f) * sbet0, cbet0);
     y0 = a1 * (atan2(sbet0, cbet0) + ...
                SinCosSeries(true, sbet0, cbet0, C1f(n)));
+    y0 = reshape(y0, size(lat0));
   end
   y = y - y0;
 end
diff --git a/matlab/geographiclib/tranmerc_inv.m b/matlab/geographiclib/tranmerc_inv.m
index 23fd620..7bac19d 100644
--- a/matlab/geographiclib/tranmerc_inv.m
+++ b/matlab/geographiclib/tranmerc_inv.m
@@ -41,7 +41,7 @@ function [lat, lon, gam, k] = tranmerc_inv(lat0, lon0, x, y, ellipsoid)
 
 % Copyright (c) Charles Karney (2012-2015) <charles at karney.com>.
 %
-% This file was distributed with GeographicLib 1.43.
+% This file was distributed with GeographicLib 1.44.
 
   narginchk(4, 5)
   if nargin < 5, ellipsoid = defaultellipsoid; end
@@ -54,7 +54,6 @@ function [lat, lon, gam, k] = tranmerc_inv(lat0, lon0, x, y, ellipsoid)
     error('ellipsoid must be a vector of size 2')
   end
 
-  degree = pi/180;
   maxpow = 6;
 
   a = ellipsoid(1);
@@ -70,9 +69,11 @@ function [lat, lon, gam, k] = tranmerc_inv(lat0, lon0, x, y, ellipsoid)
   if isscalar(lat0) && lat0 == 0
     y0 = 0;
   else
-    [sbet0, cbet0] = norm2((1-f) * sind(lat0), cosd(lat0));
+    [sbet0, cbet0] = sincosdx(LatFix(lat0(:)));
+    [sbet0, cbet0] = norm2((1-f) * sbet0, cbet0);
     y0 = a1 * (atan2(sbet0, cbet0) + ...
                SinCosSeries(true, sbet0, cbet0, C1f(n)));
+    y0 = reshape(y0, size(lat0));
   end
   y = y + y0;
 
@@ -113,33 +114,31 @@ function [lat, lon, gam, k] = tranmerc_inv(lat0, lon0, x, y, ellipsoid)
   ar = s0 .* ch0; ai = c0 .* sh0;
   xip  = xi  + ar .* xip0 - ai .* etap0;
   etap = eta + ai .* xip0 + ar .* etap0;
-  gam = atan2(yi1, yr1);
+  gam = atan2dx(yi1, yr1);
   k = b1 ./ hypot(yr1, yi1);
   s = sinh(etap);
   c = max(0, cos(xip));
   r = hypot(s, c);
-  lam = atan2(s, c);
-  taup = sin(xip)./r;
-  tau = tauf(taup, e2);
-  phi = atan(tau);
-  gam = gam + atan(tan(xip) .* tanh(etap));
+  lon = atan2dx(s, c);
+  sxip = sin(xip);
+  tau = tauf(sxip./r, e2);
+  lat = atan2dx(tau, 1);
+  gam = gam + atan2dx(sxip .* tanh(etap), c);
   c = r ~= 0;
-  k(c) = k(c) .* sqrt(e2m + e2 * cos(phi(c)).^2) .* ...
+  k(c) = k(c) .* sqrt(e2m + e2 ./ (1 + tau.^2)) .* ...
          hypot(1, tau(c)) .* r(c);
   c = ~c;
   if any(c)
-    phi(c) = pi/2;
-    lam(c) = 0;
+    lat(c) = 90;
+    lon(c) = 0;
     k(c) = k(c) * cc;
   end
-  lat = phi / degree .* xisign;
-  lon = lam / degree;
+  lat = lat .* xisign;
   lon(backside) = 180 - lon(backside);
   lon = lon .* etasign;
   lon = AngNormalize(lon + AngNormalize(lon0));
-  gam = gam/degree;
   gam(backside) = 180 - gam(backside);
-  gam = gam .* xisign .* etasign;
+  gam = AngNormalize(gam .* xisign .* etasign);
 end
 
 function bet = betf(n)
diff --git a/matlab/geographiclib/utmups_fwd.m b/matlab/geographiclib/utmups_fwd.m
index ab90b14..efcac8b 100644
--- a/matlab/geographiclib/utmups_fwd.m
+++ b/matlab/geographiclib/utmups_fwd.m
@@ -36,10 +36,10 @@ function [x, y, zone, isnorth, gam, k] = utmups_fwd(lat, lon, setzone)
 %
 %   The ranges are 100 km more restrictive than for mgrs_fwd.
 %
-%   UTMUPS_FWD checks its arguments and requires that lat in [-90deg,90deg]
-%   and lon in [-540deg,540deg] and that (x,y) lie in the limits given
-%   above.  If these conditions don't hold (x,y), gam, k are converted to
-%   NaN, zone to -4 and isnorthp to 0.
+%   UTMUPS_FWD checks its arguments and requires that lat is in
+%   [-90deg,90deg] and that (x,y) lie in the limits given above.  If these
+%   conditions don't hold (x,y), gam, k are converted to NaN, zone to -4
+%   and isnorthp to 0.
 %
 %   See also UTMUPS_INV, TRANMERC_FWD, POLARST_FWD, MGRS_FWD.
 
@@ -102,7 +102,7 @@ function zone = StandardZone(lat, lon, setzone)
   zone = floor(setzone) + zeros(size(lat));
   zone(~(zone >= INVALID & zone <= MAXZONE)) = INVALID;
   g = zone < MINZONE & zone ~= INVALID;
-  c = abs(lat) <= 90 & abs(lon) <= 540;
+  c = abs(lat) <= 90 & isfinite(lon);
   zone(g & ~c) = INVALID;
   g = g & c;
   c = zone == UTM | (lat >= -80 & lat < 84);
diff --git a/maxima/geod.mac b/maxima/geod.mac
index 1bb8f9d..64a8565 100644
--- a/maxima/geod.mac
+++ b/maxima/geod.mac
@@ -1,7 +1,7 @@
 /*
 Compute the series expansions for the ellipsoidal geodesic problem.
 
-Copyright (c) Charles Karney (2009-2012) <charles at karney.com> and
+Copyright (c) Charles Karney (2009-2015) <charles at karney.com> and
 licensed under the MIT/X11 License.  For more information, see
 http://geographiclib.sourceforge.net/
 
@@ -133,9 +133,9 @@ in A2 and C2[l].  This leads to a series where half the terms drop out.
 
 computeI2(maxpow):=block([sintegrand,sintegrandexp,s,sigma,tau1,k2,eps],
   sintegrand:1/sqrt(1+k2*sin(sigma)^2),
-/* Multiplicative factor (1-eps) */
+/* Multiplicative factor 1/(1+eps) */
   sintegrandexp:ataylor(
-      1/(1-eps)*subst([k2=4*eps/(1-eps)^2],sintegrand),
+      (1+eps)*subst([k2=4*eps/(1-eps)^2],sintegrand),
       eps,maxpow),
   s:trigreduce(integrate(sintegrandexp,sigma)),
   s:s-subst(sigma=0,s),
@@ -144,7 +144,7 @@ computeI2(maxpow):=block([sintegrand,sintegrandexp,s,sigma,tau1,k2,eps],
   for i:1 thru maxpow do C2[i]:coeff(tau1,sin(2*i*sigma)),
   if expand(tau1-sigma-sum(C2[i]*sin(2*i*sigma),i,1,maxpow)) # 0
   then error("left over terms in B2"),
-  A2:A2*(1-eps),
+  A2:A2/(1+eps),
   'done)$
 
 /*
@@ -303,7 +303,7 @@ codeA2(maxpow):=block([tab2:"    ",tab3:"      "],
       t;
     switch (nA2_/2) {"),
   for n:0 thru entier(maxpow/2) do block([
-    q:horner(ataylor(subst([eps=sqrt(eps2)],A2/(1-eps)-1),eps2,n)),
+    q:horner(ataylor(subst([eps=sqrt(eps2)],A2*(1+eps)-1),eps2,n)),
     linel:1200],
     print(concat(tab2,"case ",string(n),":")),
     print(concat(tab3,"t = ",string(q),";")),
@@ -313,7 +313,7 @@ codeA2(maxpow):=block([tab2:"    ",tab3:"      "],
       " && nA2_ <= ",string(maxpow),", \"Bad value of nA2_\");")),
   print(concat(tab3,"t = 0;")),
   print("    }
-    return t * (1 - eps) - eps;
+    return (t - eps) / (1 + eps);
   }"),
 'done)$
 
@@ -455,12 +455,12 @@ block([tt:ataylor(C1p[i],eps,ord),ttt,linel:1200],
         if j=ord or j=ord-1 then ";" else ""))))$
 
 dispA2(ord):=block(
-  [tt:ataylor(A2/(1-eps),eps,ord),ttt,linel:1200],
+  [tt:ataylor(A2*(1+eps),eps,ord),ttt,linel:1200],
   for j:2 step 2 thru ord do (ttt:coeff(tt,eps,j),
     print(concat(if j = 2 then "A2 = (1 " else "        ",
         if ttt>0 then "+ " else "- ",
         string(abs(ttt)), " * ", string(eps^j),
-        if j=ord or j = ord-1 then ") * (1 - eps);" else ""))))$
+        if j=ord or j = ord-1 then ") / (1 + eps);" else ""))))$
 
 dispC2(ord):=for i:1 thru ord do
 block([tt:ataylor(C2[i],eps,ord),ttt,linel:1200],
@@ -579,10 +579,6 @@ maxpow:8$
 computeall()$
 /* printcode()$ */
 dispseries()$
-/* Coefficients of I1 - I2 */
-A12:ratdisrep(taylor(A1-A2,eps,0,maxpow))$
-for j:1 thru maxpow do
-  C12[j]:ratdisrep(taylor((A1*C1[j]-A2*C2[j])/A12,eps,0,maxpow-1))$
 
 load("polyprint.mac")$
 printgeod():= block([macro:if simplenum then "GEOGRAPHICLIB_GEODESIC_ORDER"
@@ -590,13 +586,11 @@ printgeod():= block([macro:if simplenum then "GEOGRAPHICLIB_GEODESIC_ORDER"
   value1('(A1*(1-eps)-1),'eps,2,0),
   array1('C1,'eps,2,0),
   array1('C1p,'eps,2,0),
-  value1('(A2/(1-eps)-1),'eps,2,0),
+  value1('(A2*(1+eps)-1),'eps,2,0),
   array1('C2,eps,2,0),
   value2('A3,'n,'eps,1),
   array2('C3,'n,'eps,1),
-  array2('C4,'n,'eps,1),
-  value1('A12,'eps,1,0),
-  array1('C12,'eps,1,1))$
+  array2('C4,'n,'eps,1))$
 printgeod()$
 /* Save the values needed for geodesic.mac  This is commented out
 here to avoid accidentally overwriting files in a user's directory. */
diff --git a/maxima/geodesic.mac b/maxima/geodesic.mac
index fbd42f6..0993ddc 100644
--- a/maxima/geodesic.mac
+++ b/maxima/geodesic.mac
@@ -1,7 +1,7 @@
 /*
 Solve the direct and inverse geodesic problems accurately.
 
-Copyright (c) Charles Karney (2013-2014) <charles at karney.com> and
+Copyright (c) Charles Karney (2013-2015) <charles at karney.com> and
 licensed under the MIT/X11 License.  For more information, see
 http://geographiclib.sourceforge.net/
 
@@ -100,6 +100,9 @@ documented at
 
 */
 
+/* The corresponding version of GeographicLib */
+geod_version:[1,44,0]$
+
 /* Load series created by geod.mac (NEED TO UNCOMMENT THE LAST LINE OF
 geod.mac TO GENERATE THIS FILE). */
 load("geod30.lsp")$
@@ -133,8 +136,8 @@ if not exact then (
       l:endcons(horner(ataylor(C1[i],eps,nC1)),l),l)),
   C1pf(eps):=''(block([l:[]],for i:1 thru nC1p do
       l:endcons(horner(ataylor(C1p[i],eps,nC1p)),l),l)),
-  A2m1f(eps):=''(horner(ataylor(A2/(1-eps)-1,eps,nA2))
-    *(1-eps) - eps),
+  A2m1f(eps):=''((horner(ataylor(A2*(1+eps)-1,eps,nA2))
+      -eps)/(1+eps)),
   C2f(eps):=''(block([l:[]],for i:1 thru nC2 do
       l:endcons(horner(ataylor(C2[i],eps,nC2)),l),l)),
   A3coeff(n):=
@@ -202,23 +205,40 @@ sumx(u, v):=block([s,up,vpp,t],
 
 swapx(x, y):=[y,x]$
 
-SinCosNorm(sinx, cosx):=block([r : hypotx(sinx, cosx)],
-  [sinx/r, cosx/r])$
+norm2(x, y):=block([r : hypotx(x, y)], [x/r, y/r])$
 
-AngNormalize(x):= if x >= 180b0 then x - 360b0
-else (if x < -180b0 then x + 360b0 else x)$
-AngNormalize2(x):=AngNormalize(mod(x, 360b0))$
+AngNormalize(x):=block([y:x-360b0*floor(x/360b0+0.5)],
+  if y < -180b0 then y+360b0 else if y < 180b0 then y else y-360b0)$
 
-AngDiff(x, y) := block([t,d,r:sumx(-x,y)],
-  d:r[1], t:r[2],
-  if (d - 180b0) + t > 0b0 then d : d - 360b0
-  else if (d + 180b0) + t <= 0b0 then d : d + 360b0,
-  d + t)$
+AngDiff(x, y) := block([t,d,r:sumx(AngNormalize(x),AngNormalize(-y))],
+  d:-AngNormalize(r[1]), t:r[2],
+  (if d = 180b0 and t < 0b0 then -180b0 else d) - t)$
 
 AngRound(x) := block([z:1/16b0, y:abs(x)],
   y : if y < z then z - (z - y) else y,
   if x < 0b0 then 0b0-y else y)$
 
+sincosdx(x):=block([r,q:floor(x/90b0 + 0.5),s,c],
+  r:(x-q*90b0)*degree,
+  s:sin(r), c:cos(r),
+  q:mod(q,4),
+  if     q = 0 then [  s,   c]
+  elseif q = 1 then [  c, 0-s]
+  elseif q = 2 then [0-s, 0-c]
+  else              [0-c,   s])$
+
+atan2dx(y,x):=block([q,xx,yy,ang],
+  if abs(y) > abs(x)
+  then (xx:y, yy:x, q:2)
+  else (xx:x, yy:y, q:0),
+  if xx < 0
+  then (xx:-xx, q:q+1),
+  ang:atan2(yy, xx) / degree,
+  if     q = 0 then ang
+  elseif q = 1 then (if y > 0b0 then 180b0 else -180b0) - ang
+  elseif q = 2 then  90 - ang
+  else              -90 + ang)$
+
 /* Indices in geodesic struct */
 block([i:0], g_a:(i:i+1), g_f:(i:i+1), g_f1:(i:i+1), g_e2:(i:i+1),
   g_ep2:(i:i+1), g_n:(i:i+1), g_b:(i:i+1), g_c2:(i:i+1), g_etol2:(i:i+1),
@@ -276,7 +296,7 @@ geod_lineinit(g,lat1,lon1,azi1):=block([a, f,
   A1m1, A2m1, A3c, B11, B21, B31,
   A4, B41, C1a, C1pa, C2a, C3a,
   C4a,
-  alp1, cbet1, sbet1, phi, eps,
+  cbet1, sbet1, eps,
   e2, cchi1, A4, B41, E0, D0, H0, E1, D1, H1, C4a, E],
   lat1:bfloat(lat1),lon1:bfloat(lon1), azi1:bfloat(azi1),
   a : g[g_a],
@@ -285,23 +305,19 @@ geod_lineinit(g,lat1,lon1,azi1):=block([a, f,
   c2 : g[g_c2],
   f1 : g[g_f1],
   e2 : g[g_e2],
+  lat1 : lat1,
   /* If caps is 0 assume the standard direct calculation
   caps = (caps ? caps : GEOD_DISTANCE_IN | GEOD_LONGITUDE) |
   GEOD_LATITUDE | GEOD_AZIMUTH, Always allow latitude and azimuth
   Guard against underflow in salp0 */
-  azi1 : AngRound(AngNormalize(azi1)),
-  /* Don't normalizing lon1... */
-  /* alp1 is in [0, pi] */
-  alp1 : azi1 * degree,
-  /* Enforce sin(pi) == 0 and cos(pi/2) == 0.  Better to face the ensuing
-  problems directly than to skirt them. */
-  salp1 : if azi1  = -180b0 then 0b0 else sin(alp1),
-  calp1 : if abs(azi1) = 90b0 then 0b0 else cos(alp1),
-  phi : lat1 * degree,
+  azi1 : AngNormalize(azi1),
+  /* Don't normalize lon1... */
+  block([t:sincosdx(AngRound(azi1))], salp1:t[1], calp1:t[2]),
+  block([t:sincosdx(AngRound(lat1))],
+        sbet1:t[1], cbet1:t[2]), sbet1 : f1 * sbet1,
+  block([t:norm2(sbet1, cbet1)], sbet1:t[1], cbet1:t[2]),
   /* Ensure cbet1 = +epsilon at poles */
-  sbet1 : f1 * sin(phi),
-  cbet1 : if abs(lat1) = 90b0 then tiny else cos(phi),
-  block([t:SinCosNorm(sbet1, cbet1)], sbet1:t[1], cbet1:t[2]),
+  cbet1 = max(tiny, cbet1),
   dn1 : sqrt(1 + g[g_ep2] * sq(sbet1)),
   /* Evaluate alp0 from sin(alp1) * cos(bet1) = sin(alp0), */
   salp0 : salp1 * cbet1, /* alp0 in [0, pi/2 - |bet1|] */
@@ -322,9 +338,9 @@ geod_lineinit(g,lat1,lon1,azi1):=block([a, f,
   /* Without normalization we have schi1 = somg1. */
   cchi1 : f1 * dn1 * comg1,
   /* sig1 in (-pi, pi] */
-  block([t:SinCosNorm(ssig1, csig1)], ssig1:t[1], csig1:t[2]),
-  /* SinCosNorm (somg1, comg1); -- don't need to normalize!
-  SinCosNorm (schi1, cchi1); -- don't need to normalize! */
+  block([t:norm2(ssig1, csig1)], ssig1:t[1], csig1:t[2]),
+  /* norm2 (somg1, comg1); -- don't need to normalize!
+  norm2 (schi1, cchi1); -- don't need to normalize! */
   k2 : sq(calp0) * g[g_ep2],
   eps : k2 / (2 * (1 + sqrt(1 + k2)) + k2),
   E:Ef(-k2,-g[g_ep2]),
@@ -383,13 +399,10 @@ geod_genposition(l, arcmode,  s12_a12):=block(
   omg12, lam12, lon12,
   ssig2, csig2, sbet2, cbet2, somg2, comg2, salp2, calp2, dn2, E],
   s12_a12 : bfloat(s12_a12),
-  if (arcmode) then block([s12a],
+  if (arcmode) then (
     /* Interpret s12_a12 as spherical arc length */
     sig12 : s12_a12 * degree,
-    s12a : abs(s12_a12),
-    s12a : s12a - 180 * floor(s12a / 180),
-    ssig12 : if s12a =  0b0 then 0b0 else sin(sig12),
-    csig12 : if s12a = 90b0 then 0b0 else cos(sig12))
+    block([t:sincosdx(s12_a12)], ssig12:t[1], csig12:t[2]))
   else block([tau12 : s12_a12 / (l[l_b] *
       (if exact then l[l_E0] else (1 + l[l_A1m1]))),s,c],
     /* Interpret s12_a12 as distance */
@@ -459,7 +472,7 @@ geod_genposition(l, arcmode,  s12_a12):=block(
     somg2 : l[l_salp0] * ssig2, comg2 : csig2),  /* No need to normalize */
   /* tan(alp0) = cos(sig2)*tan(alp2) */
   salp2 : l[l_salp0], calp2 : l[l_calp0] * csig2, /* No need to normalize */
-  E = if l[l_salp0] < 0b0 then -1 else 1,
+  E : if l[l_salp0] < 0b0 then -1 else 1,
   if not exact then
   /* omg12 = omg2 - omg1 */
   omg12 : E * (sig12
@@ -483,9 +496,9 @@ geod_genposition(l, arcmode,  s12_a12):=block(
   lon12 : lam12 / degree,
   /* Don't normalize lon2... */
   lon2 : l[l_lon1] + lon12,
-  lat2 : atan2x(sbet2, l[l_f1] * cbet2) / degree,
+  lat2 : atan2dx(sbet2, l[l_f1] * cbet2),
   /* minus signs give range [-180, 180). 0- converts -0 to +0. */
-  azi2 : 0 - atan2x(-salp2, calp2) / degree,
+  azi2 : atan2dx(salp2, calp2),
   block([B22, AB2, J12],
     if exact then J12 : l[l_k2] * l[l_D0] *
     (sig12 + deltad(ssig2, csig2, dn2, l[l_E][e_k2], l[l_E][e_dc]) - l[l_D1])
@@ -544,11 +557,9 @@ geod_geninverse(g, lat1, lon1, lat2, lon2):=block(
   [s12 : 0b0, azi1 : 0b0, azi2 : 0b0,
   m12 : 0b0, M12 : 0b0, M21 : 0b0, S12 : 0b0,
   lon12, latsign, lonsign, swapp,
-  phi, sbet1, cbet1, sbet2, cbet2, s12x : 0b0, m12x : 0b0,
+  sbet1, cbet1, sbet2, cbet2, s12x : 0b0, m12x : 0b0,
   dn1, dn2, lam12, slam12, clam12,
   a12 : 0b0, sig12, calp1 : 0b0, salp1 : 0b0, calp2 : 0b0, salp2 : 0b0,
-  /* index zero elements of these arrays are unused */
-  C1a, C2a, C3a,
   meridian,  omg12 : 0b0,
   /* Initialize for the meridian.  No longitude calculation is done in this
   case to let the parameter default to 0. */
@@ -558,7 +569,7 @@ geod_geninverse(g, lat1, lon1, lat2, lon2):=block(
   /* Compute longitude difference (AngDiff does this carefully).  Result is
   in [-180, 180] but -180 is only for west-going geodesics.  180 is for
   east-going and meridional geodesics. */
-  lon12 : AngDiff(AngNormalize(lon1), AngNormalize(lon2)),
+  lon12 : AngDiff(lon1, lon2),
   /* If very close to being on the same half-meridian, then make it so. */
   lon12 : AngRound(lon12),
   /* Make longitude difference positive. */
@@ -584,16 +595,14 @@ geod_geninverse(g, lat1, lon1, lat2, lon2):=block(
   made.  We make these transformations so that there are few cases to
   check, e.g., on verifying quadrants in atan2.  In addition, this
   enforces some symmetries in the results returned. */
-  phi : lat1 * degree,
+  block([t:sincosdx(lat1)], sbet1:t[1], cbet1:t[2]), sbet1 : g[g_f1] * sbet1,
+  block([t:norm2(sbet1, cbet1)], sbet1:t[1], cbet1:t[2]),
   /* Ensure cbet1 = +epsilon at poles */
-  sbet1 : g[g_f1] * sin(phi),
-  cbet1 : if lat1 = -90b0 then tiny else cos(phi),
-  block([t:SinCosNorm(sbet1, cbet1)], sbet1:t[1], cbet1:t[2]),
-  phi : lat2 * degree,
+  cbet1 = max(tiny, cbet1),
+  block([t:sincosdx(lat2)], sbet2:t[1], cbet2:t[2]), sbet2 : g[g_f1] * sbet2,
+  block([t:norm2(sbet2, cbet2)], sbet2:t[1], cbet2:t[2]),
   /* Ensure cbet2 = +epsilon at poles */
-  sbet2 : g[g_f1] * sin(phi),
-  cbet2 : if abs(lat2) = 90b0 then tiny else cos(phi),
-  block([t:SinCosNorm(sbet2, cbet2)], sbet2:t[1], cbet2:t[2]),
+  cbet2 = max(tiny, cbet2),
   /* If cbet1 < -sbet1, then cbet2 - cbet1 is a sensitive measure of the
   |bet1| - |bet2|.  Alternatively (cbet1 >= -sbet1), abs(sbet2) + sbet1 is
   a better measure.  This logic is used in assigning calp2 in Lambda12.
@@ -607,8 +616,7 @@ geod_geninverse(g, lat1, lon1, lat2, lon2):=block(
   dn1 : sqrt(1 + g[g_ep2] * sq(sbet1)),
   dn2 : sqrt(1 + g[g_ep2] * sq(sbet2)),
   lam12 : lon12 * degree,
-  slam12 : if lon12 = 180b0 then 0b0 else sin(lam12),
-  clam12 : cos(lam12),      /* lon12 == 90 isn't interesting */
+  block([t:sincosdx(lon12)], slam12:t[1], clam12:t[2]),
   meridian : is(lat1 = -90b0 or slam12 = 0b0),
   if meridian then block(
     /* Endpoints are on a single full meridian, so the geodesic might lie on
@@ -632,6 +640,7 @@ geod_geninverse(g, lat1, lon1, lat2, lon2):=block(
     In fact, we will have sig12 > pi/2 for meridional geodesic which is
     not a shortest path. */
     if sig12 < 1b0 or m12x >= 0b0 then (
+      if sig12 < 3 * tiny then sig12 : m12x : s12x : 0b0,
       m12x : m12x * g[g_b],
       s12x : s12x * g[g_b],
       a12 : sig12 / degree )
@@ -710,7 +719,7 @@ geod_geninverse(g, lat1, lon1, lat2, lon2):=block(
           if nsalp1 > 0b0 and abs(dalp1) < pi then (
             calp1 : calp1 * cdalp1 - salp1 * sdalp1,
             salp1 : nsalp1,
-            block([t:SinCosNorm(salp1, calp1)], salp1:t[1], calp1:t[2]),
+            block([t:norm2(salp1, calp1)], salp1:t[1], calp1:t[2]),
             /* In some regimes we don't get quadratic convergence because
             slope -> 0.  So use convergence conditions based on epsilon
             instead of sqrt(epsilon). */
@@ -727,7 +736,7 @@ geod_geninverse(g, lat1, lon1, lat2, lon2):=block(
           WGS84 and random input: mean = 4.74, sd = 0.99 */
           salp1 : (salp1a + salp1b)/2,
           calp1 : (calp1a + calp1b)/2,
-          block([t:SinCosNorm(salp1, calp1)], salp1:t[1], calp1:t[2]),
+          block([t:norm2(salp1, calp1)], salp1:t[1], calp1:t[2]),
           tripn : false,
           tripb : is(abs(salp1a - salp1) + (calp1a - calp1) < tolb or
             abs(salp1 - salp1b) + (calp1 - calp1b) < tolb)) ),
@@ -753,13 +762,13 @@ geod_geninverse(g, lat1, lon1, lat2, lon2):=block(
       k2 : sq(calp0) * g[g_ep2], eps,
       /* Multiplier = a^2 * e^2 * cos(alpha0) * sin(alpha0). */
       A4 : sq(g[g_a]) * calp0 * salp0 * g[g_e2],
-      C4a, B41, B42],
+      Ca, B41, B42],
       eps : k2 / (2 * (1 + sqrt(1 + k2)) + k2),
-      block([t:SinCosNorm(ssig1, csig1)], ssig1:t[1], csig1:t[2]),
-      block([t:SinCosNorm(ssig2, csig2)], ssig2:t[1], csig2:t[2]),
-      C4a : C4f(g, eps),
-      B41 : SinCosSeries(false, ssig1, csig1, C4a),
-      B42 : SinCosSeries(false, ssig2, csig2, C4a),
+      block([t:norm2(ssig1, csig1)], ssig1:t[1], csig1:t[2]),
+      block([t:norm2(ssig2, csig2)], ssig2:t[1], csig2:t[2]),
+      Ca : C4f(g, eps),
+      B41 : SinCosSeries(false, ssig1, csig1, Ca),
+      B42 : SinCosSeries(false, ssig2, csig2, Ca),
       S12 : A4 * (B42 - B41))
     else S12 : 0, /* Avoid problems with indeterminate sig1, sig2 on equator */
     if not meridian and
@@ -795,9 +804,8 @@ geod_geninverse(g, lat1, lon1, lat2, lon2):=block(
     block([t:swapx(M12, M21)], M12:t[1], M21:t[2])),
   salp1 : salp1 * swapp * lonsign, calp1 : calp1 * swapp * latsign,
   salp2 : salp2 * swapp * lonsign, calp2 : calp2 * swapp * latsign,
-  /* minus signs give range [-180, 180). 0- converts -0 to +0. */
-  azi1 : 0b0 - atan2x(-salp1, calp1) / degree,
-  azi2 : 0b0 - atan2x(-salp2, calp2) / degree,
+  azi1 : atan2dx(salp1, calp1),
+  azi2 : atan2dx(salp2, calp2),
   [a12, s12, azi1, azi2, m12, M12, M21, S12]
 )$
 
@@ -827,7 +835,7 @@ SinCosSeries(sinp, sinx, cosx, c):=block([n:length(c), ar, y0, y1, n2, k],
 
 /* Return [s12b, m12b, m0, M12, M21] */
 Lengths(g, eps, E, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2, cbet1, cbet2):=
-block([scalep:true, C1a, C2a,
+block([Ca,
   s12b : 0b0, m12b : 0b0, m0 : 0b0, M12 : 0b0, M21 : 0b0,
   A1m1, AB1, A2m1, AB2, J12],
   /* Return m12b = (reduced length)/b; also calculate s12b = distance/b,
@@ -837,13 +845,13 @@ block([scalep:true, C1a, C2a,
     J12 : m0 *
       (sig12 + deltad(ssig2, csig2, dn2, E[e_k2], E[e_dc])
       - deltad(ssig1, csig1, dn1, E[e_k2], E[e_dc])) )
-  else (C1a : C1f(eps), C2a : C2f(eps),
-    A1m1 : A1m1f(eps),
-    AB1 : (1 + A1m1) * (SinCosSeries(true, ssig2, csig2, C1a) -
-      SinCosSeries(true, ssig1, csig1, C1a)),
-    A2m1 : A2m1f(eps),
-    AB2 : (1 + A2m1) * (SinCosSeries(true, ssig2, csig2, C2a) -
-      SinCosSeries(true, ssig1, csig1, C2a)),
+  else (
+    A1m1 : A1m1f(eps), Ca : C1f(eps),
+    AB1 : (1 + A1m1) * (SinCosSeries(true, ssig2, csig2, Ca) -
+      SinCosSeries(true, ssig1, csig1, Ca)),
+    A2m1 : A2m1f(eps), Ca : C2f(eps),
+    AB2 : (1 + A2m1) * (SinCosSeries(true, ssig2, csig2, Ca) -
+      SinCosSeries(true, ssig1, csig1, Ca)),
     m0 : A1m1 - A2m1,
     J12 : m0 * sig12 + (AB1 - AB2)),
   /* Missing a factor of b.
@@ -856,7 +864,7 @@ block([scalep:true, C1a, C2a,
   (sig12 + deltae(ssig2, csig2, dn2, E[e_k2], E[e_ec])
   - deltae(ssig1, csig1, dn1, E[e_k2], E[e_ec]))
   else (1 + A1m1) * sig12 + AB1,
-  if scalep then block([csig12 : csig1 * csig2 + ssig1 * ssig2,
+  block([csig12 : csig1 * csig2 + ssig1 * ssig2,
     t : g[g_ep2] * (cbet1 - cbet2) * (cbet1 + cbet2) / (dn1 + dn2)],
     M12 : csig12 + (t * ssig2 - csig2 * J12) * ssig1 / dn1,
     M21 : csig12 - (t * ssig1 - csig1 * J12) * ssig2 / dn2 ),
@@ -874,7 +882,7 @@ Astroid(x, y):= block(
     r2 : sq(r),
     r3, disc, u, v, uv, w],
     r3 : r * r2,
-    /* The discrimant of the quadratic equation for T3.  This is zero on
+    /* The discriminant of the quadratic equation for T3.  This is zero on
     the evolute curve p^(1/3)+q^(1/3) = 1 */
     disc : S * (S + 2 * r3),
     u : r,
@@ -940,7 +948,7 @@ InverseStart(g, sbet1, cbet1, dn1, sbet2, cbet2, dn2, lam12):=block(
     salp2 : cbet1 * somg12,
     calp2 : sbet12 - cbet1 * sbet2 *
     (if comg12 >= 0 then sq(somg12) / (1 + comg12) else 1 - comg12),
-    block([t:SinCosNorm(salp2, calp2)], salp2:t[1], calp2:t[2]),
+    block([t:norm2(salp2, calp2)], salp2:t[1], calp2:t[2]),
     /* Set return value */
     sig12 : atan2x(ssig12, csig12))
   else if abs(g[g_n]) > 0.1b0 or /* No astroid calc if too eccentric */
@@ -1022,7 +1030,7 @@ InverseStart(g, sbet1, cbet1, dn1, sbet2, cbet2, dn2, lam12):=block(
       salp1 : cbet2 * somg12,
       calp1 : sbet12a - cbet2 * sbet1 * sq(somg12) / (1 - comg12))),
   if salp1 > 0 then              /* Sanity check on starting guess */
-  block([t:SinCosNorm(salp1, calp1)], salp1:t[1], calp1:t[2])
+  block([t:norm2(salp1, calp1)], salp1:t[1], calp1:t[2])
   else ( salp1 : 1b0, calp1 : 0b0 ),
   [sig12, salp1, calp1, salp2, calp2, dnm]
   )$
@@ -1036,7 +1044,7 @@ block([salp2 : 0b0, calp2 : 0b0, sig12 : 0b0,
   domg12 : 0b0, dlam12 : 0b0,
   salp0, calp0,
   somg1, comg1, somg2, comg2, cchi1, cchi2, omg12:0, lam12,
-  B312, h0, k2],
+  B312, h0, k2, Ca],
   if sbet1 = 0b0 and calp1 = 0b0 then
   /* Break degeneracy of equatorial line.  This case has already been
   handled. */
@@ -1050,8 +1058,8 @@ block([salp2 : 0b0, calp2 : 0b0, sig12 : 0b0,
   csig1 : comg1 : calp1 * cbet1,
   /* Without normalization we have schi1 = somg1. */
   if exact then cchi1 : g[g_f1] * dn1 * comg1,
-  block([t:SinCosNorm(ssig1, csig1)], ssig1:t[1], csig1:t[2]),
-  /* SinCosNorm (&somg1, &comg1); -- don't need to normalize! */
+  block([t:norm2(ssig1, csig1)], ssig1:t[1], csig1:t[2]),
+  /* norm2 (&somg1, &comg1); -- don't need to normalize! */
   /* Enforce symmetries in the case abs(bet2) = -bet1.  Need to be careful
   about this case, since this can yield singularities in the Newton
   iteration.
@@ -1073,8 +1081,8 @@ block([salp2 : 0b0, calp2 : 0b0, sig12 : 0b0,
   csig2 : comg2 : calp2 * cbet2,
   /* Without normalization we have schi2 = somg2. */
   if exact then cchi2 : g[g_f1] * dn2 * comg2,
-  block([t:SinCosNorm(ssig2, csig2)], ssig2:t[1], csig2:t[2]),
-  /* SinCosNorm (&somg2, &comg2); -- don't need to normalize! */
+  block([t:norm2(ssig2, csig2)], ssig2:t[1], csig2:t[2]),
+  /* norm2(&somg2, &comg2); -- don't need to normalize! */
   /* sig12 = sig2 - sig1, limit to [0, pi] */
   sig12 : atan2x(max(csig1 * ssig2 - ssig1 * csig2, 0b0),
     csig1 * csig2 + ssig1 * ssig2),
@@ -1091,9 +1099,9 @@ block([salp2 : 0b0, calp2 : 0b0, sig12 : 0b0,
       (sig12 + deltah(ssig2, csig2, dn2, E[e_k2], E[e_alpha2], E[e_hc]) -
        deltah(ssig1, csig1, dn1, E[e_k2], E[e_alpha2], E[e_hc]) ) )
   else (eps : k2 / (2 * (1 + sqrt(1 + k2)) + k2),
-    C3a : C3f(g, eps),
-    B312 : (SinCosSeries(true, ssig2, csig2, C3a) -
-      SinCosSeries(true, ssig1, csig1, C3a)),
+    Ca : C3f(g, eps),
+    B312 : (SinCosSeries(true, ssig2, csig2, Ca) -
+      SinCosSeries(true, ssig1, csig1, Ca)),
     h0 : -g[g_f] * A3f(g, eps),
     domg12 : salp0 * h0 * (sig12 + B312),
     lam12 : omg12 + domg12),
diff --git a/pom.xml b/pom.xml
index c546646..3319b01 100644
--- a/pom.xml
+++ b/pom.xml
@@ -13,7 +13,7 @@
 
   <groupId>com.sri.vt</groupId>
   <artifactId>geographiclib</artifactId>
-  <version>1.43-SNAPSHOT</version>
+  <version>1.44-SNAPSHOT</version>
   <packaging>majic-cmake</packaging>
   <name>GeographicLib</name>
 
diff --git a/python/README.txt b/python/README.txt
index 22f9c17..28a18e8 100644
--- a/python/README.txt
+++ b/python/README.txt
@@ -5,7 +5,7 @@ GeographicLib.  This contains implementations of the classes
 - GeographicLib::Accumulator
 - GeographicLib::Geodesic
 - GeographicLib::GeodesicLine
-- GeographicLib::PolygonArea
+- GeographicLib::PolygonAreaT<Geodesic>
 
 For more information on GeographicLib, see
 
diff --git a/python/geographiclib/__init__.py b/python/geographiclib/__init__.py
index 1e89458..d6c610d 100644
--- a/python/geographiclib/__init__.py
+++ b/python/geographiclib/__init__.py
@@ -1 +1,4 @@
 """geographiclib: geodesic routines from GeographicLib"""
+
+__version_info__ = (1, 44, 0)
+__version__ = "1.44"
diff --git a/python/geographiclib/geodesic.py b/python/geographiclib/geodesic.py
index a525168..8858bb0 100644
--- a/python/geographiclib/geodesic.py
+++ b/python/geographiclib/geodesic.py
@@ -13,7 +13,7 @@
 #    https://dx.doi.org/10.1007/s00190-012-0578-z
 #    Addenda: http://geographiclib.sf.net/geod-addenda.html
 #
-# Copyright (c) Charles Karney (2011-2014) <charles at karney.com> and licensed
+# Copyright (c) Charles Karney (2011-2015) <charles at karney.com> and licensed
 # under the MIT/X11 License.  For more information, see
 # http://geographiclib.sourceforge.net/
 ######################################################################
@@ -56,9 +56,9 @@ class Geodesic(object):
     help(Geodesic.Area)
 
   All angles (latitudes, longitudes, azimuths, spherical arc lengths)
-  are measured in degrees.  Latitudes must lie in [-90,90]; longitudes
-  and azimuths must lie in [-540,540).  All lengths (distance, reduced
-  length) are measured in meters.  Areas are measures in square meters.
+  are measured in degrees.  Latitudes must lie in [-90,90].  All lengths
+  (distance, reduced length) are measured in meters.  Areas are measures
+  in square meters.
 
   """
 
@@ -146,11 +146,11 @@ class Geodesic(object):
       S = p * q / 4            # S = r^3 * s
       r2 = Math.sq(r)
       r3 = r * r2
-      # The discrimant of the quadratic equation for T3.  This is zero on
+      # The discriminant of the quadratic equation for T3.  This is zero on
       # the evolute curve p^(1/3)+q^(1/3) = 1
       disc = S * (S + 2 * r3)
       u = r
-      if (disc >= 0):
+      if disc >= 0:
         T3 = S + r3
         # Pick the sign on the sqrt to maximize abs(T3).  This minimizes loss
         # of precision due to cancellation.  The result is unchanged because
@@ -233,11 +233,11 @@ class Geodesic(object):
   def A2m1f(eps):
     """Private: return A2-1"""
     coeff = [
-      25, 36, 64, 0, 256,
+      -11, -28, -192, 0, 256,
     ]
     m = Geodesic.nA2_//2
     t = Math.polyval(m, coeff, 0, Math.sq(eps)) / coeff[m + 1]
-    return t * (1 - eps) - eps
+    return (t - eps) / (1 + eps)
   A2m1f = staticmethod(A2m1f)
 
   def C2f(eps, c):
@@ -409,37 +409,56 @@ class Geodesic(object):
 
   # return s12b, m12b, m0, M12, M21
   def Lengths(self, eps, sig12,
-              ssig1, csig1, dn1, ssig2, csig2, dn2, cbet1, cbet2, scalep,
+              ssig1, csig1, dn1, ssig2, csig2, dn2, cbet1, cbet2, outmask,
               # Scratch areas of the right size
               C1a, C2a):
     """Private: return a bunch of lengths"""
-    # Return m12b = (reduced length)/_b; also calculate s12b = distance/_b,
-    # and m0 = coefficient of secular term in expression for reduced length.
-    Geodesic.C1f(eps, C1a)
-    Geodesic.C2f(eps, C2a)
-    A1m1 = Geodesic.A1m1f(eps)
-    AB1 = (1 + A1m1) * (
-      Geodesic.SinCosSeries(True, ssig2, csig2, C1a) -
-      Geodesic.SinCosSeries(True, ssig1, csig1, C1a))
-    A2m1 = Geodesic.A2m1f(eps)
-    AB2 = (1 + A2m1) * (
-      Geodesic.SinCosSeries(True, ssig2, csig2, C2a) -
-      Geodesic.SinCosSeries(True, ssig1, csig1, C2a))
-    m0 = A1m1 - A2m1
-    J12 = m0 * sig12 + (AB1 - AB2)
-    # Missing a factor of _b.
-    # Add parens around (csig1 * ssig2) and (ssig1 * csig2) to ensure accurate
-    # cancellation in the case of coincident points.
-    m12b = dn2 * (csig1 * ssig2) - dn1 * (ssig1 * csig2) - csig1 * csig2 * J12
-    # Missing a factor of _b
-    s12b = (1 + A1m1) * sig12 + AB1
-    if scalep:
+    # Return s12b, m12b, m0, M12, M21, where
+    # m12b = (reduced length)/_b; s12b = distance/_b,
+    # m0 = coefficient of secular term in expression for reduced length.
+    outmask &= Geodesic.OUT_MASK
+    # outmask & DISTANCE: set s12b
+    # outmask & REDUCEDLENGTH: set m12b & m0
+    # outmask & GEODESICSCALE: set M12 & M21
+
+    s12b = m12b = m0 = M12 = M21 = Math.nan
+    if outmask & (Geodesic.DISTANCE | Geodesic.REDUCEDLENGTH |
+                  Geodesic.GEODESICSCALE):
+      A1 = Geodesic.A1m1f(eps)
+      Geodesic.C1f(eps, C1a)
+      if outmask & (Geodesic.REDUCEDLENGTH | Geodesic.GEODESICSCALE):
+        A2 = Geodesic.A2m1f(eps)
+        Geodesic.C2f(eps, C2a)
+        m0x = A1 - A2
+        A2 = 1 + A2
+      A1 = 1 + A1
+    if outmask & Geodesic.DISTANCE:
+      B1 = (Geodesic.SinCosSeries(True, ssig2, csig2, C1a) -
+            Geodesic.SinCosSeries(True, ssig1, csig1, C1a))
+      # Missing a factor of _b
+      s12b = A1 * (sig12 + B1)
+      if outmask & (Geodesic.REDUCEDLENGTH | Geodesic.GEODESICSCALE):
+        B2 = (Geodesic.SinCosSeries(True, ssig2, csig2, C2a) -
+              Geodesic.SinCosSeries(True, ssig1, csig1, C2a))
+        J12 = m0x * sig12 + (A1 * B1 - A2 * B2)
+    elif outmask & (Geodesic.REDUCEDLENGTH | Geodesic.GEODESICSCALE):
+      # Assume here that nC1_ >= nC2_
+      for l in range(1, Geodesic.nC2_):
+        C2a[l] = A1 * C1a[l] - A2 * C2a[l]
+      J12 = m0x * sig12 + (Geodesic.SinCosSeries(True, ssig2, csig2, C2a) -
+                           Geodesic.SinCosSeries(True, ssig1, csig1, C2a))
+    if outmask & Geodesic.REDUCEDLENGTH:
+      m0 = m0x
+      # Missing a factor of _b.
+      # Add parens around (csig1 * ssig2) and (ssig1 * csig2) to ensure
+      # accurate cancellation in the case of coincident points.
+      m12b = (dn2 * (csig1 * ssig2) - dn1 * (ssig1 * csig2) -
+              csig1 * csig2 * J12)
+    if outmask & Geodesic.GEODESICSCALE:
       csig12 = csig1 * csig2 + ssig1 * ssig2
       t = self._ep2 * (cbet1 - cbet2) * (cbet1 + cbet2) / (dn1 + dn2)
       M12 = csig12 + (t * ssig2 - csig2 * J12) * ssig1 / dn1
       M21 = csig12 - (t * ssig1 - csig1 * J12) * ssig2 / dn2
-    else:
-      M12 = M21 = Math.nan
     return s12b, m12b, m0, M12, M21
 
   # return sig12, salp1, calp1, salp2, calp2, dnm
@@ -519,7 +538,7 @@ class Geodesic(object):
         # Inverse.
         dummy, m12b, m0, dummy, dummy = self.Lengths(
           self._n, math.pi + bet12a, sbet1, -cbet1, dn1, sbet2, cbet2, dn2,
-          cbet1, cbet2, False, C1a, C2a)
+          cbet1, cbet2, Geodesic.REDUCEDLENGTH, C1a, C2a)
         x = -1 + m12b / (cbet1 * cbet2 * m0 * math.pi)
         betscale = (sbet12a / x if x < -0.01
                     else -self._f * Math.sq(cbet1) * math.pi)
@@ -570,7 +589,7 @@ class Geodesic(object):
         # Because omg12 is near pi, estimate work with omg12a = pi - omg12
         k = Geodesic.Astroid(x, y)
         omg12a = lamscale * ( -x * k/(1 + k) if self._f >= 0
-                               else -y * (1 + k)/k )
+                              else -y * (1 + k)/k )
         somg12 = math.sin(omg12a); comg12 = -math.cos(omg12a)
         # Update spherical estimate of alp1 using omg12 instead of lam12
         salp1 = cbet2 * somg12
@@ -648,7 +667,7 @@ class Geodesic(object):
       else:
         dummy, dlam12, dummy, dummy, dummy = self.Lengths(
           eps, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2, cbet1, cbet2,
-          False, C1a, C2a)
+          Geodesic.REDUCEDLENGTH, C1a, C2a)
         dlam12 *= self._f1 / (calp2 * cbet2)
     else:
       dlam12 = Math.nan
@@ -665,15 +684,14 @@ class Geodesic(object):
     # Compute longitude difference (AngDiff does this carefully).  Result is
     # in [-180, 180] but -180 is only for west-going geodesics.  180 is for
     # east-going and meridional geodesics.
-    lon12 = Math.AngDiff(Math.AngNormalize(lon1), Math.AngNormalize(lon2))
     # If very close to being on the same half-meridian, then make it so.
-    lon12 = Math.AngRound(lon12)
+    lon12 = Math.AngRound(Math.AngDiff(lon1, lon2))
     # Make longitude difference positive.
     lonsign = 1 if lon12 >= 0 else -1
     lon12 *= lonsign
     # If really close to the equator, treat as on equator.
-    lat1 = Math.AngRound(lat1)
-    lat2 = Math.AngRound(lat2)
+    lat1 = Math.AngRound(Math.LatFix(lat1))
+    lat2 = Math.AngRound(Math.LatFix(lat2))
     # Swap points so that point with higher (abs) latitude is point 1
     swapp = 1 if abs(lat1) >= abs(lat2) else -1
     if swapp < 0:
@@ -697,17 +715,13 @@ class Geodesic(object):
 
     # real phi, sbet1, cbet1, sbet2, cbet2, s12x, m12x
 
-    phi = lat1 * Math.degree
+    sbet1, cbet1 = Math.sincosd(lat1); sbet1 *= self._f1
     # Ensure cbet1 = +epsilon at poles
-    sbet1 = self._f1 * math.sin(phi)
-    cbet1 = Geodesic.tiny_ if lat1 == -90 else math.cos(phi)
-    sbet1, cbet1 = Math.norm(sbet1, cbet1)
+    sbet1, cbet1 = Math.norm(sbet1, cbet1); cbet1 = max(Geodesic.tiny_, cbet1)
 
-    phi = lat2 * Math.degree
+    sbet2, cbet2 = Math.sincosd(lat2); sbet2 *= self._f1
     # Ensure cbet2 = +epsilon at poles
-    sbet2 = self._f1 * math.sin(phi)
-    cbet2 = Geodesic.tiny_ if abs(lat2) == 90 else math.cos(phi)
-    sbet2, cbet2 = Math.norm(sbet2, cbet2)
+    sbet2, cbet2 = Math.norm(sbet2, cbet2); cbet2 = max(Geodesic.tiny_, cbet2)
 
     # If cbet1 < -sbet1, then cbet2 - cbet1 is a sensitive measure of the
     # |bet1| - |bet2|.  Alternatively (cbet1 >= -sbet1), abs(sbet2) + sbet1 is
@@ -727,9 +741,8 @@ class Geodesic(object):
     dn1 = math.sqrt(1 + self._ep2 * Math.sq(sbet1))
     dn2 = math.sqrt(1 + self._ep2 * Math.sq(sbet2))
 
-    lam12 = lon12 * Math.degree
-    slam12 = 0 if lon12 == 180 else math.sin(lam12)
-    clam12 = math.cos(lam12)      # lon12 == 90 isn't interesting
+    lam12 = math.radians(lon12)
+    slam12, clam12 = Math.sincosd(lon12)
 
     # real a12, sig12, calp1, salp1, calp2, salp2
     # index zero elements of these arrays are unused
@@ -757,7 +770,7 @@ class Geodesic(object):
 
       s12x, m12x, dummy, M12, M21 = self.Lengths(
         self._n, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2, cbet1, cbet2,
-        (outmask & Geodesic.GEODESICSCALE) != 0, C1a, C2a)
+        outmask | Geodesic.DISTANCE | Geodesic.REDUCEDLENGTH, C1a, C2a)
 
       # Add the check for sig12 since zero length geodesics might yield m12 <
       # 0.  Test case was
@@ -767,9 +780,11 @@ class Geodesic(object):
       # In fact, we will have sig12 > pi/2 for meridional geodesic which is
       # not a shortest path.
       if sig12 < 1 or m12x >= 0:
+        if sig12 < 3 * Geodesic.tiny_:
+          sig12 = m12x = s12x = 0
         m12x *= self._b
         s12x *= self._b
-        a12 = sig12 / Math.degree
+        a12 = math.degrees(sig12)
       else:
         # m12 < 0, i.e., prolate and too close to anti-podal
         meridian = False
@@ -805,7 +820,7 @@ class Geodesic(object):
         m12x = (Math.sq(dnm) * self._b * math.sin(sig12 / dnm))
         if outmask & Geodesic.GEODESICSCALE:
           M12 = M21 = math.cos(sig12 / dnm)
-        a12 = sig12 / Math.degree
+        a12 = math.degrees(sig12)
         omg12 = lam12 / (self._f1 * dnm)
       else:
 
@@ -832,8 +847,8 @@ class Geodesic(object):
           # WGS84 and random input: mean = 2.85, sd = 0.60
           (nlam12, salp2, calp2, sig12, ssig1, csig1, ssig2, csig2,
            eps, omg12, dv) = self.Lambda12(
-            sbet1, cbet1, dn1, sbet2, cbet2, dn2,
-            salp1, calp1, numit < Geodesic.maxit1_, C1a, C2a, C3a)
+             sbet1, cbet1, dn1, sbet2, cbet2, dn2,
+             salp1, calp1, numit < Geodesic.maxit1_, C1a, C2a, C3a)
           v = nlam12 - lam12
           # 2 * tol0 is approximately 1 ulp for a number in [0, pi].
           # Reversed test to allow escape with NaNs
@@ -875,13 +890,18 @@ class Geodesic(object):
           tripb = (abs(salp1a - salp1) + (calp1a - calp1) < Geodesic.tolb_ or
                    abs(salp1 - salp1b) + (calp1 - calp1b) < Geodesic.tolb_)
 
+        lengthmask = (outmask |
+                      (Geodesic.DISTANCE
+                       if (outmask & (Geodesic.REDUCEDLENGTH |
+                                      Geodesic.GEODESICSCALE))
+                       else Geodesic.EMPTY))
         s12x, m12x, dummy, M12, M21 = self.Lengths(
           eps, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2, cbet1, cbet2,
-          (outmask & Geodesic.GEODESICSCALE) != 0, C1a, C2a)
+          lengthmask, C1a, C2a)
 
         m12x *= self._b
         s12x *= self._b
-        a12 = sig12 / Math.degree
+        a12 = math.degrees(sig12)
         omg12 = lam12 - omg12
     # end elif not meridian
 
@@ -953,31 +973,31 @@ class Geodesic(object):
 
     if outmask & Geodesic.AZIMUTH:
       # minus signs give range [-180, 180). 0- converts -0 to +0.
-      azi1 = 0 - math.atan2(-salp1, calp1) / Math.degree
-      azi2 = 0 - math.atan2(-salp2, calp2) / Math.degree
+      azi1 = Math.atan2d(salp1, calp1)
+      azi2 = Math.atan2d(salp2, calp2)
 
     # Returned value in [0, 180]
     return a12, s12, azi1, azi2, m12, M12, M21, S12
 
   def CheckPosition(lat, lon):
     """Check that lat and lon are legal and return normalized lon"""
-    if (abs(lat) > 90):
+    if not (abs(lat) <= 90):
       raise ValueError("latitude " + str(lat) + " not in [-90, 90]")
-    if (lon < -540 or lon >= 540):
-      raise ValueError("longitude " + str(lon) + " not in [-540, 540)")
+    if not Math.isfinite(lon):
+      raise ValueError("lonitude " + str(lon) + " not a finite number")
     return Math.AngNormalize(lon)
   CheckPosition = staticmethod(CheckPosition)
 
   def CheckAzimuth(azi):
     """Check that azi is legal and return normalized value"""
-    if (azi < -540 or azi >= 540):
-      raise ValueError("azimuth " + str(azi) + " not in [-540, 540)")
+    if not Math.isfinite(azi):
+      raise ValueError("azimuth " + str(azi) + " not a finite number")
     return Math.AngNormalize(azi)
   CheckAzimuth = staticmethod(CheckAzimuth)
 
   def CheckDistance(s):
     """Check that s is a legal distance"""
-    if not (Math.isfinite(s)):
+    if not Math.isfinite(s):
       raise ValueError("distance " + str(s) + " not a finite number")
   CheckDistance = staticmethod(CheckDistance)
 
@@ -1015,6 +1035,8 @@ class Geodesic(object):
     lon1 indicates whether the geodesic is east going or west going.
     Otherwise lon1 and lon2 are both reduced to the range [-180,180).
 
+    The default value of outmask is DISTANCE | AZIMUTH.
+
     """
 
     lon1a = Geodesic.CheckPosition(lat1, lon1)
@@ -1045,7 +1067,7 @@ class Geodesic(object):
     line = GeodesicLine(
       self, lat1, lon1, azi1,
       # Automatically supply DISTANCE_IN if necessary
-      outmask | ( Geodesic.EMPTY if arcmode else Geodesic.DISTANCE_IN))
+      outmask | (Geodesic.EMPTY if arcmode else Geodesic.DISTANCE_IN))
     return line.GenPosition(arcmode, s12_a12, outmask)
 
   def Direct(self, lat1, lon1, azi1, s12,
@@ -1083,9 +1105,9 @@ class Geodesic(object):
     The LONG_UNROLL bit unrolls the longitudes (instead of reducing them
     to the range [-180,180)); the quantity lon2 - lon1 then indicates
     how many times and in what sense the geodesic encircles the
-    ellipsoid.  Because lon2 might be outside the normal allowed range
-    for longitudes, [-540,540), be sure to normalize it with
-    math.fmod(lon2,360) before using it in other calls.
+    ellipsoid.
+
+    The default value of outmask is LATITUDE | LONGITUDE | AZIMUTH.
 
     """
 
@@ -1145,6 +1167,9 @@ class Geodesic(object):
       Geodesic.ALL (all of the above)
       Geodesic.LONG_UNROLL
 
+    The default value of outmask is LATITUDE | LONGITUDE | AZIMUTH |
+    DISTANCE.
+
     """
 
     if outmask & Geodesic.LONG_UNROLL:
@@ -1172,7 +1197,7 @@ class Geodesic(object):
     """Return a GeodesicLine object to compute points along a geodesic
     starting at lat1, lon1, with azimuth azi1.  caps is an or'ed
     combination of bit the following values indicating the capabilities
-    of the return object
+    of the returned object
 
       Geodesic.LATITUDE
       Geodesic.LONGITUDE
@@ -1184,6 +1209,8 @@ class Geodesic(object):
       Geodesic.DISTANCE_IN
       Geodesic.ALL (all of the above)
 
+    The default value of caps is ALL.
+
     """
 
     from geographiclib.geodesicline import GeodesicLine
diff --git a/python/geographiclib/geodesicline.py b/python/geographiclib/geodesicline.py
index 098be5a..ca8059d 100644
--- a/python/geographiclib/geodesicline.py
+++ b/python/geographiclib/geodesicline.py
@@ -13,7 +13,7 @@
 #    https://dx.doi.org/10.1007/s00190-012-0578-z
 #    Addenda: http://geographiclib.sf.net/geod-addenda.html
 #
-# Copyright (c) Charles Karney (2011-2014) <charles at karney.com> and licensed
+# Copyright (c) Charles Karney (2011-2015) <charles at karney.com> and licensed
 # under the MIT/X11 License.  For more information, see
 # http://geographiclib.sourceforge.net/
 ######################################################################
@@ -26,6 +26,26 @@ class GeodesicLine(object):
   """Points on a geodesic path"""
 
   def __init__(self, geod, lat1, lon1, azi1, caps = GeodesicCapability.ALL):
+    """Construct a GeodesicLine object describing a geodesic line
+    starting at (lat1, lon1) with azimuth azi1.  geod is a Geodesic
+    object (which embodies the ellipsoid parameters).  caps is caps is
+    an or'ed combination of bit the following values indicating the
+    capabilities of the returned object
+
+      Geodesic.LATITUDE
+      Geodesic.LONGITUDE
+      Geodesic.AZIMUTH
+      Geodesic.DISTANCE
+      Geodesic.REDUCEDLENGTH
+      Geodesic.GEODESICSCALE
+      Geodesic.AREA
+      Geodesic.DISTANCE_IN
+      Geodesic.ALL (all of the above)
+
+    The default value of caps is ALL.
+
+    """
+
     from geographiclib.geodesic import Geodesic
     self._a = geod._a
     self._f = geod._f
@@ -36,22 +56,15 @@ class GeodesicLine(object):
                   Geodesic.LONG_UNROLL)
 
     # Guard against underflow in salp0
-    azi1 = Math.AngRound(Math.AngNormalize(azi1))
-    self._lat1 = lat1
+    self._lat1 = Math.LatFix(lat1)
     self._lon1 = lon1
-    self._azi1 = azi1
-    # alp1 is in [0, pi]
-    alp1 = azi1 * Math.degree
-    # Enforce sin(pi) == 0 and cos(pi/2) == 0.  Better to face the ensuing
-    # problems directly than to skirt them.
-    self._salp1 = 0 if     azi1  == -180 else math.sin(alp1)
-    self._calp1 = 0 if abs(azi1) ==   90 else math.cos(alp1)
-    # real cbet1, sbet1, phi
-    phi = lat1 * Math.degree
+    self._azi1 = Math.AngNormalize(azi1)
+    self._salp1, self._calp1 = Math.sincosd(Math.AngRound(azi1))
+
+    # real cbet1, sbet1
+    sbet1, cbet1 = Math.sincosd(Math.AngRound(lat1)); sbet1 *= self._f1
     # Ensure cbet1 = +epsilon at poles
-    sbet1 = self._f1 * math.sin(phi)
-    cbet1 = Geodesic.tiny_ if abs(lat1) == 90 else math.cos(phi)
-    sbet1, cbet1 = Math.norm(sbet1, cbet1)
+    sbet1, cbet1 = Math.norm(sbet1, cbet1); cbet1 = max(Geodesic.tiny_, cbet1)
     self._dn1 = math.sqrt(1 + geod._ep2 * Math.sq(sbet1))
 
     # Evaluate alp0 from sin(alp1) * cos(bet1) = sin(alp0),
@@ -133,11 +146,8 @@ class GeodesicLine(object):
     B12 = 0; AB1 = 0
     if arcmode:
       # Interpret s12_a12 as spherical arc length
-      sig12 = s12_a12 * Math.degree
-      s12a = abs(s12_a12)
-      s12a -= 180 * math.floor(s12a / 180)
-      ssig12 = 0 if s12a ==  0 else math.sin(sig12)
-      csig12 = 0 if s12a == 90 else math.cos(sig12)
+      sig12 = math.radians(s12_a12)
+      ssig12, csig12 = Math.sincosd(s12_a12)
     else:
       # Interpret s12_a12 as distance
       tau12 = s12_a12 / (self._b * (1 + self._A1m1))
@@ -220,19 +230,17 @@ class GeodesicLine(object):
       lam12 = omg12 + self._A3c * (
         sig12 + (Geodesic.SinCosSeries(True, ssig2, csig2, self._C3a)
                  - self._B31))
-      lon12 = lam12 / Math.degree
-      # Use Math.AngNormalize2 because longitude might have wrapped
-      # multiple times.
+      lon12 = math.degrees(lam12)
       lon2 = (self._lon1 + lon12 if outmask & Geodesic.LONG_UNROLL else
               Math.AngNormalize(Math.AngNormalize(self._lon1) +
-                                Math.AngNormalize2(lon12)))
+                                Math.AngNormalize(lon12)))
 
     if outmask & Geodesic.LATITUDE:
-      lat2 = math.atan2(sbet2, self._f1 * cbet2) / Math.degree
+      lat2 = Math.atan2d(sbet2, self._f1 * cbet2)
 
     if outmask & Geodesic.AZIMUTH:
       # minus signs give range [-180, 180). 0- converts -0 to +0.
-      azi2 = 0 - math.atan2(-salp2, calp2) / Math.degree
+      azi2 = Math.atan2d(salp2, calp2)
 
     if outmask & (Geodesic.REDUCEDLENGTH | Geodesic.GEODESICSCALE):
       B22 = Geodesic.SinCosSeries(True, ssig2, csig2, self._C2a)
@@ -280,7 +288,7 @@ class GeodesicLine(object):
       S12 = (self._c2 * math.atan2(salp12, calp12) +
              self._A4 * (B42 - self._B41))
 
-    a12 = s12_a12 if arcmode else sig12 / Math.degree
+    a12 = s12_a12 if arcmode else math.degrees(sig12)
     return a12, lat2, lon2, azi2, s12, m12, M12, M21, S12
 
   def Position(self, s12,
@@ -318,6 +326,8 @@ class GeodesicLine(object):
       Geodesic.ALL (all of the above)
       Geodesic.LONG_UNROLL
 
+    The default value of outmask is LATITUDE | LONGITUDE | AZIMUTH.
+
     """
 
     from geographiclib.geodesic import Geodesic
@@ -375,6 +385,9 @@ class GeodesicLine(object):
       Geodesic.ALL (all of the above)
       Geodesic.LONG_UNROLL
 
+    The default value of outmask is LATITUDE | LONGITUDE | AZIMUTH |
+    DISTANCE.
+
     """
 
     from geographiclib.geodesic import Geodesic
diff --git a/python/geographiclib/geomath.py b/python/geographiclib/geomath.py
index e136101..fcbd63a 100644
--- a/python/geographiclib/geomath.py
+++ b/python/geographiclib/geomath.py
@@ -6,8 +6,8 @@
 #
 #    http://geographiclib.sourceforge.net/html/annotated.html
 #
-# Copyright (c) Charles Karney (2011) <charles at karney.com> and licensed under
-# the MIT/X11 License.  For more information, see
+# Copyright (c) Charles Karney (2011-2015) <charles at karney.com> and
+# licensed under the MIT/X11 License.  For more information, see
 # http://geographiclib.sourceforge.net/
 ######################################################################
 
@@ -23,7 +23,6 @@ class Math(object):
     digits, the number of digits in the fraction of a real number
     minval, minimum normalized positive number
     maxval, maximum finite number
-    degree, the number of radians in a degree
     nan, not a number
     inf, infinity
   """
@@ -32,7 +31,6 @@ class Math(object):
   epsilon = math.pow(2.0, 1-digits)
   minval = math.pow(2.0, -1022)
   maxval = math.pow(2.0, 1023) * (2 - epsilon)
-  degree = math.pi/180
   inf = float("inf") if sys.version_info > (2, 6) else 2 * maxval
   nan = float("nan") if sys.version_info > (2, 6) else inf - inf
 
@@ -120,29 +118,62 @@ class Math(object):
   AngRound = staticmethod(AngRound)
 
   def AngNormalize(x):
-    """reduce angle in [-540,540) to [-180,180)"""
+    """reduce angle to [-180,180)"""
 
-    return (x - 360 if x >= 180 else
-            (x + 360 if x < -180 else x))
+    x = math.fmod(x, 360)
+    return (x + 360 if x < -180 else
+            (x if x < 180 else x - 360))
   AngNormalize = staticmethod(AngNormalize)
 
-  def AngNormalize2(x):
-    """reduce arbitrary angle to [-180,180)"""
+  def LatFix(x):
+    """replace angles outside [-90,90] by NaN"""
 
-    return Math.AngNormalize(math.fmod(x, 360))
-  AngNormalize2 = staticmethod(AngNormalize2)
+    return Math.nan if abs(x) > 90 else x
+  LatFix = staticmethod(LatFix)
 
   def AngDiff(x, y):
     """compute y - x and reduce to [-180,180] accurately"""
 
-    d, t = Math.sum(-x, y)
-    if (d - 180) + t > 0:       # y - x > 180
-      d -= 360                  # exact
-    elif (d + 180) + t <= 0:    # y - x <= -180
-      d += 360                  # exact
-    return d + t
+    d, t = Math.sum(Math.AngNormalize(x), Math.AngNormalize(-y))
+    d = - Math.AngNormalize(d)
+    return (-180 if d == 180 and t < 0 else d) - t
   AngDiff = staticmethod(AngDiff)
 
+  def sincosd(x):
+    """Compute sine and cosine of x in degrees."""
+
+    r = math.fmod(x, 360); q = int(math.floor(r / 90 + 0.5))
+    r -= 90 * q; r = math.radians(r)
+    s = math.sin(r); c = math.cos(r)
+    q = q % 4
+    if q == 1:
+      s, c =   c, 0-s
+    elif q == 2:
+      s, c = 0-s, 0-c
+    elif q == 3:
+      s, c = 0-c,   s
+    return s, c
+  sincosd = staticmethod(sincosd)
+
+  def atan2d(y, x):
+    """compute atan2(y, x) with the result in degrees"""
+
+    if abs(y) > abs(x):
+      q = 2; x, y = y, x
+    else:
+      q = 0
+    if x < 0:
+      q += 1; x = -x
+    ang = math.degrees(math.atan2(y, x))
+    if q == 1:
+      ang = (180 if y > 0 else -180) - ang
+    elif q == 2:
+      ang =  90 - ang
+    elif q == 3:
+      ang = -90 + ang
+    return ang
+  atan2d = staticmethod(atan2d)
+
   def isfinite(x):
     """Test for finiteness"""
 
diff --git a/python/setup.py b/python/setup.py
index 93306a1..cfa0727 100644
--- a/python/setup.py
+++ b/python/setup.py
@@ -15,7 +15,7 @@
 from distutils.core import setup
 
 setup(name="geographiclib",
-      version="1.43",
+      version="1.44",
       description=
         "A translation of the GeographicLib::Geodesic class to Python",
       author="Charles Karney",
diff --git a/src/AlbersEqualArea.cpp b/src/AlbersEqualArea.cpp
index aedde93..1b3ff81 100644
--- a/src/AlbersEqualArea.cpp
+++ b/src/AlbersEqualArea.cpp
@@ -2,7 +2,7 @@
  * \file AlbersEqualArea.cpp
  * \brief Implementation for GeographicLib::AlbersEqualArea class
  *
- * Copyright (c) Charles Karney (2010-2014) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2010-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -41,10 +41,8 @@ namespace GeographicLib {
       throw GeographicErr("Scale is not positive");
     if (!(abs(stdlat) <= 90))
       throw GeographicErr("Standard latitude not in [-90d, 90d]");
-    real
-      phi = stdlat * Math::degree(),
-      sphi = sin(phi),
-      cphi = abs(stdlat) != 90 ? cos(phi) : 0;
+    real sphi, cphi;
+    Math::sincosd(stdlat, sphi, cphi);
     Init(sphi, cphi, sphi, cphi, k0);
   }
 
@@ -74,11 +72,10 @@ namespace GeographicLib {
       throw GeographicErr("Standard latitude 1 not in [-90d, 90d]");
     if (!(abs(stdlat2) <= 90))
       throw GeographicErr("Standard latitude 2 not in [-90d, 90d]");
-    real
-      phi1 = stdlat1 * Math::degree(),
-      phi2 = stdlat2 * Math::degree();
-    Init(sin(phi1), abs(stdlat1) != 90 ? cos(phi1) : 0,
-         sin(phi2), abs(stdlat2) != 90 ? cos(phi2) : 0, k1);
+    real sphi1, cphi1, sphi2, cphi2;
+    Math::sincosd(stdlat1, sphi1, cphi1);
+    Math::sincosd(stdlat2, sphi2, cphi2);
+    Init(sphi1, cphi1, sphi2, cphi2, k1);
   }
 
   AlbersEqualArea::AlbersEqualArea(real a, real f,
@@ -387,12 +384,13 @@ namespace GeographicLib {
   void AlbersEqualArea::Forward(real lon0, real lat, real lon,
                                 real& x, real& y, real& gamma, real& k)
     const {
-    lon = Math::AngDiff(Math::AngNormalize(lon0), Math::AngNormalize(lon));
+    lon = Math::AngDiff(lon0, lon);
     lat *= _sign;
+    real sphi, cphi;
+    Math::sincosd(Math::LatFix(lat) * _sign, sphi, cphi);
+    cphi = max(epsx_, cphi);
     real
       lam = lon * Math::degree(),
-      phi = lat * Math::degree(),
-      sphi = sin(phi), cphi = abs(lat) != 90 ? cos(phi) : epsx_,
       tphi = sphi/cphi, txi = txif(tphi), sxi = txi/hyp(txi),
       dq = _qZ * Dsn(txi, _txi0, sxi, _sxi0) * (txi - _txi0),
       drho = - _a * dq / (sqrt(_m02 - _n0 * dq) + _nrho0 / _a),
@@ -423,11 +421,10 @@ namespace GeographicLib {
               (Math::sq(_a) * _qZ),
       txi = (_txi0 + dsxia) / sqrt(max(1 - dsxia * (2*_txi0 + dsxia), epsx2_)),
       tphi = tphif(txi),
-      phi = _sign * atan(tphi),
       theta = atan2(nx, y1),
       lam = _n0 ? theta / (_k2 * _n0) : x / (y1 * _k0);
     gamma = _sign * theta / Math::degree();
-    lat = phi / Math::degree();
+    lat = Math::atand(_sign * tphi);
     lon = lam / Math::degree();
     lon = Math::AngNormalize(lon + Math::AngNormalize(lon0));
     k = _k0 * (den ? (_nrho0 + _n0 * drho) * hyp(_fm * tphi) / _a : 1);
diff --git a/src/AzimuthalEquidistant.cpp b/src/AzimuthalEquidistant.cpp
index 387c2d5..5ccc8f8 100644
--- a/src/AzimuthalEquidistant.cpp
+++ b/src/AzimuthalEquidistant.cpp
@@ -2,7 +2,7 @@
  * \file AzimuthalEquidistant.cpp
  * \brief Implementation for GeographicLib::AzimuthalEquidistant class
  *
- * Copyright (c) Charles Karney (2009-2011) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2009-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -22,9 +22,8 @@ namespace GeographicLib {
     const {
     real sig, s, azi0, m;
     sig = _earth.Inverse(lat0, lon0, lat, lon, s, azi0, azi, m);
-    azi0 *= Math::degree();
-    x = s * sin(azi0);
-    y = s * cos(azi0);
+    Math::sincosd(azi0, x, y);
+    x *= s; y *= s;
     rk = !(sig <= eps_) ? m / s : 1;
   }
 
@@ -32,7 +31,7 @@ namespace GeographicLib {
                                      real& lat, real& lon, real& azi, real& rk)
     const {
     real
-      azi0 = atan2(x, y) / Math::degree(),
+      azi0 = Math::atan2d(x, y),
       s = Math::hypot(x, y);
     real sig, m;
     sig = _earth.Direct(lat0, lon0, azi0, s, lat, lon, azi, m);
diff --git a/src/CassiniSoldner.cpp b/src/CassiniSoldner.cpp
index f00add3..ecd0297 100644
--- a/src/CassiniSoldner.cpp
+++ b/src/CassiniSoldner.cpp
@@ -14,14 +14,10 @@ namespace GeographicLib {
   using namespace std;
 
   CassiniSoldner::CassiniSoldner(const Geodesic& earth)
-    : eps1_(real(0.01) * sqrt(numeric_limits<real>::epsilon()))
-    , tiny_(sqrt(numeric_limits<real>::min()))
-    , _earth(earth) {}
+    : _earth(earth) {}
 
   CassiniSoldner::CassiniSoldner(real lat0, real lon0, const Geodesic& earth)
-    : eps1_(real(0.01) * sqrt(numeric_limits<real>::epsilon()))
-    , tiny_(sqrt(numeric_limits<real>::min()))
-    , _earth(earth)
+    : _earth(earth)
   { Reset(lat0, lon0); }
 
   void CassiniSoldner::Reset(real lat0, real lon0) {
@@ -29,11 +25,9 @@ namespace GeographicLib {
                             Geodesic::LATITUDE | Geodesic::LONGITUDE |
                             Geodesic::DISTANCE | Geodesic::DISTANCE_IN |
                             Geodesic::AZIMUTH);
-    real
-      phi = LatitudeOrigin() * Math::degree(),
-      f = _earth.Flattening();
-    _sbet0 = (1 - f) * sin(phi);
-    _cbet0 = abs(LatitudeOrigin()) == 90 ? 0 : cos(phi);
+    real f = _earth.Flattening();
+    Math::sincosd(LatitudeOrigin(), _sbet0, _cbet0);
+    _sbet0 *= (1 - f);
     Math::norm(_sbet0, _cbet0);
   }
 
@@ -41,16 +35,13 @@ namespace GeographicLib {
                                real& azi, real& rk) const {
     if (!Init())
       return;
-    real dlon = Math::AngDiff(LongitudeOrigin(), Math::AngNormalize(lon));
+    real dlon = Math::AngDiff(LongitudeOrigin(), lon);
     real sig12, s12, azi1, azi2;
-    lat = Math::AngRound(lat);
     sig12 = _earth.Inverse(lat, -abs(dlon), lat, abs(dlon), s12, azi1, azi2);
-    if (sig12 < 100 * tiny_)
-      sig12 = s12 = 0;
     sig12 *= real(0.5);
     s12 *= real(0.5);
     if (s12 == 0) {
-      real da = (azi2 - azi1)/2;
+      real da = Math::AngDiff(azi1, azi2)/2;
       if (abs(dlon) <= 90) {
         azi1 = 90 - da;
         azi2 = 90 + da;
@@ -72,9 +63,9 @@ namespace GeographicLib {
                      Geodesic::GEODESICSCALE,
                      t, t, t, t, t, t, rk, t);
 
+    real salp0, calp0;
+    Math::sincosd(perp.EquatorialAzimuth(), salp0, calp0);
     real
-      alp0 = perp.EquatorialAzimuth() * Math::degree(),
-      calp0 = cos(alp0), salp0 = sin(alp0),
       sbet1 = lat >=0 ? calp0 : -calp0,
       cbet1 = abs(dlon) <= 90 ? abs(salp0) : -abs(salp0),
       sbet01 = sbet1 * _cbet0 - cbet1 * _sbet0,
diff --git a/src/DMS.cpp b/src/DMS.cpp
index 233e4d0..2ea30da 100644
--- a/src/DMS.cpp
+++ b/src/DMS.cpp
@@ -42,37 +42,40 @@ namespace GeographicLib {
     replace(dmsa, "\xba", 'd');          // 0xba bare alt symbol
     replace(dmsa, "\xb4", '\'');         // 0xb4 bare acute accent
     replace(dmsa, "''", '"');            // '' -> "
-    unsigned
+    string::size_type
       beg = 0,
       end = unsigned(dmsa.size());
     while (beg < end && isspace(dmsa[beg]))
       ++beg;
     while (beg < end && isspace(dmsa[end - 1]))
       --end;
-    unsigned bega = beg;
-    if (end > bega && Utility::lookup(hemispheres_, dmsa[bega]) >= 0)
-      ++bega;
-    if (end > bega && Utility::lookup(signs_, dmsa[bega]) >= 0)
-      ++bega;
-    string::size_type p = dmsa.find_first_of(signs_, bega);
+    // The trimmed string in [beg, end)
+    real v = 0;
+    int i = 0;
     flag ind1 = NONE;
-    real v = InternalDecode(dmsa.substr(beg,
-                                        (p == string::npos ? end : p) - beg),
-                            ind1);
-    if (p == string::npos)
-      ind = ind1;
-    else {
+    // p is pointer to the next piece that needs decoding
+    for (string::size_type p = beg, pb; p < end; p = pb, ++i) {
+      string::size_type pa = p;
+      // Skip over initial hemisphere letter (for i == 0)
+      if (i == 0 && Utility::lookup(hemispheres_, dmsa[pa]) >= 0)
+        ++pa;
+      // Skip over initial sign (checking for it if i == 0)
+      if (i > 0 || (pa < end && Utility::lookup(signs_, dmsa[pa]) >= 0))
+        ++pa;
+      // Find next sign
+      pb = min(dmsa.find_first_of(signs_, pa), end);
       flag ind2 = NONE;
-      v += InternalDecode(dmsa.substr(p, end - p), ind2);
-      if (ind2 == NONE)
-        ind = ind1;
-      else if (ind1 == NONE || ind1 == ind2)
-        ind = ind2;
-      else
+      v += InternalDecode(dmsa.substr(p, pb - p), ind2);
+      if (ind1 == NONE)
+        ind1 = ind2;
+      else if (!(ind2 == NONE || ind1 == ind2))
         throw GeographicErr("Incompatible hemisphere specifies in " +
-                            dmsa.substr(beg, p - beg) + " and " +
-                            dmsa.substr(p, end - p));
+                            dmsa.substr(beg, pb - beg));
     }
+    if (i == 0)
+      throw GeographicErr("Empty or incomplete DMS string " +
+                          dmsa.substr(beg, end - beg));
+    ind = ind1;
     return v;
   }
 
@@ -169,7 +172,7 @@ namespace GeographicLib {
               " component of " + dmsa.substr(beg, end - beg);
             break;
           }
-          if (digcount > 1) {
+          if (digcount > 0) {
             istringstream s(dmsa.substr(p - intcount - digcount - 1,
                                         intcount + digcount));
             s >> fcurrent;
@@ -205,7 +208,7 @@ namespace GeographicLib {
             + dmsa.substr(beg, end - beg);
           break;
         }
-        if (digcount > 1) {
+        if (digcount > 0) {
           istringstream s(dmsa.substr(p - intcount - digcount,
                                       intcount + digcount));
           s >> fcurrent;
@@ -220,12 +223,12 @@ namespace GeographicLib {
         break;
       }
       // Note that we accept 59.999999... even though it rounds to 60.
-      if (ipieces[1] >= 60) {
+      if (ipieces[1] >= 60 || fpieces[1] > 60 ) {
         errormsg = "Minutes " + Utility::str(fpieces[1])
           + " not in range [0, 60)";
         break;
       }
-      if (ipieces[2] >= 60) {
+      if (ipieces[2] >= 60 || fpieces[2] > 60) {
         errormsg = "Seconds " + Utility::str(fpieces[2])
           + " not in range [0, 60)";
         break;
@@ -233,7 +236,9 @@ namespace GeographicLib {
       ind = ind1;
       // Assume check on range of result is made by calling routine (which
       // might be able to offer a better diagnostic).
-      return real(sign) * (fpieces[0] + (fpieces[1] + fpieces[2] / 60) / 60);
+      return real(sign) *
+        ( fpieces[2] ? (60*(60*fpieces[0] + fpieces[1]) + fpieces[2]) / 3600 :
+          ( fpieces[1] ? (60*fpieces[0] + fpieces[1]) / 60 : fpieces[0] ) );
     } while (false);
     real val = Utility::nummatch<real>(dmsa);
     if (val == 0)
@@ -245,15 +250,15 @@ namespace GeographicLib {
 
   void DMS::DecodeLatLon(const std::string& stra, const std::string& strb,
                          real& lat, real& lon,
-                         bool swaplatlong) {
+                         bool longfirst) {
     real a, b;
     flag ia, ib;
     a = Decode(stra, ia);
     b = Decode(strb, ib);
     if (ia == NONE && ib == NONE) {
-      // Default to lat, long unless swaplatlong
-      ia = swaplatlong ? LONGITUDE : LATITUDE;
-      ib = swaplatlong ? LATITUDE : LONGITUDE;
+      // Default to lat, long unless longfirst
+      ia = longfirst ? LONGITUDE : LATITUDE;
+      ib = longfirst ? LATITUDE : LONGITUDE;
     } else if (ia == NONE)
       ia = flag(LATITUDE + LONGITUDE - ib);
     else if (ib == NONE)
@@ -268,9 +273,6 @@ namespace GeographicLib {
     if (abs(lat1) > 90)
       throw GeographicErr("Latitude " + Utility::str(lat1)
                           + "d not in [-90d, 90d]");
-    if (lon1 < -540 || lon1 >= 540)
-      throw GeographicErr("Longitude " + Utility::str(lon1)
-                          + "d not in [-540d, 540d)");
     lat = lat1;
     lon = lon1;
   }
@@ -290,8 +292,6 @@ namespace GeographicLib {
     if (ind == LATITUDE)
       throw GeographicErr("Azimuth " + azistr
                           + " has a latitude hemisphere, N/S");
-    if (azi < -540 || azi >= 540)
-      throw GeographicErr("Azimuth " + azistr + " not in range [-540d, 540d)");
     return Math::AngNormalize(azi);
   }
 
@@ -320,7 +320,13 @@ namespace GeographicLib {
     // fractional part.
     real
       idegree = floor(angle),
-      fdegree = floor((angle - idegree) * scale + real(0.5)) / scale;
+      fdegree = (angle - idegree) * scale + real(0.5);
+    {
+      // Implement the "round ties to even" rule
+      real f = floor(fdegree);
+      fdegree = (f == fdegree && fmod(f, real(2)) == 1) ? f - 1 : f;
+    }
+    fdegree /= scale;
     if (fdegree >= 1) {
       idegree += 1;
       fdegree -= 1;
diff --git a/src/Ellipsoid.cpp b/src/Ellipsoid.cpp
index 2734170..ee0ebf5 100644
--- a/src/Ellipsoid.cpp
+++ b/src/Ellipsoid.cpp
@@ -46,16 +46,16 @@ namespace GeographicLib {
   }
 
   Math::real Ellipsoid::ParametricLatitude(real phi) const
-  { return Math::atand(_f1 * Math::tand(phi)); }
+  { return Math::atand(_f1 * Math::tand(Math::LatFix(phi))); }
 
   Math::real Ellipsoid::InverseParametricLatitude(real beta) const
-  { return Math::atand(Math::tand(beta) / _f1); }
+  { return Math::atand(Math::tand(Math::LatFix(beta)) / _f1); }
 
   Math::real Ellipsoid::GeocentricLatitude(real phi) const
-  { return Math::atand(_f12 * Math::tand(phi)); }
+  { return Math::atand(_f12 * Math::tand(Math::LatFix(phi))); }
 
   Math::real Ellipsoid::InverseGeocentricLatitude(real theta) const
-  { return Math::atand(Math::tand(theta) / _f12); }
+  { return Math::atand(Math::tand(Math::LatFix(theta)) / _f12); }
 
   Math::real Ellipsoid::RectifyingLatitude(real phi) const {
     return abs(phi) == 90 ? phi:
@@ -70,19 +70,20 @@ namespace GeographicLib {
   }
 
   Math::real Ellipsoid::AuthalicLatitude(real phi) const
-  { return Math::atand(_au.txif(Math::tand(phi))); }
+  { return Math::atand(_au.txif(Math::tand(Math::LatFix(phi)))); }
 
   Math::real Ellipsoid::InverseAuthalicLatitude(real xi) const
-  { return Math::atand(_au.tphif(Math::tand(xi))); }
+  { return Math::atand(_au.tphif(Math::tand(Math::LatFix(xi)))); }
 
   Math::real Ellipsoid::ConformalLatitude(real phi) const
-  { return Math::atand(Math::taupf(Math::tand(phi), _es)); }
+  { return Math::atand(Math::taupf(Math::tand(Math::LatFix(phi)), _es)); }
 
   Math::real Ellipsoid::InverseConformalLatitude(real chi) const
-  { return Math::atand(Math::tauf(Math::tand(chi), _es)); }
+  { return Math::atand(Math::tauf(Math::tand(Math::LatFix(chi)), _es)); }
 
   Math::real Ellipsoid::IsometricLatitude(real phi) const
-  { return Math::asinh(Math::taupf(Math::tand(phi), _es)) / Math::degree(); }
+  { return Math::asinh(Math::taupf(Math::tand(Math::LatFix(phi)), _es)) /
+      Math::degree(); }
 
   Math::real Ellipsoid::InverseIsometricLatitude(real psi) const
   { return Math::atand(Math::tauf(sinh(psi * Math::degree()), _es)); }
@@ -90,35 +91,35 @@ namespace GeographicLib {
   Math::real Ellipsoid::CircleRadius(real phi) const {
     return abs(phi) == 90 ? 0 :
       // a * cos(beta)
-      _a / Math::hypot(real(1), _f1 * Math::tand(phi));
+      _a / Math::hypot(real(1), _f1 * Math::tand(Math::LatFix(phi)));
   }
 
   Math::real Ellipsoid::CircleHeight(real phi) const {
     real tbeta = _f1 * Math::tand(phi);
     // b * sin(beta)
-    return _b * tbeta / Math::hypot(real(1), _f1 * Math::tand(phi));
+    return _b * tbeta / Math::hypot(real(1),
+                                    _f1 * Math::tand(Math::LatFix(phi)));
   }
 
   Math::real Ellipsoid::MeridianDistance(real phi) const
   { return _b * _ell.Ed( ParametricLatitude(phi) ); }
 
   Math::real Ellipsoid::MeridionalCurvatureRadius(real phi) const {
-    real v = 1 - _e2 * Math::sq(sin(phi * Math::degree()));
+    real v = 1 - _e2 * Math::sq(Math::sind(Math::LatFix(phi)));
     return _a * (1 - _e2) / (v * sqrt(v));
   }
 
   Math::real Ellipsoid::TransverseCurvatureRadius(real phi) const {
-    real v = 1 - _e2 * Math::sq(sin(phi * Math::degree()));
+    real v = 1 - _e2 * Math::sq(Math::sind(Math::LatFix(phi)));
     return _a / sqrt(v);
   }
 
   Math::real Ellipsoid::NormalCurvatureRadius(real phi, real azi)
     const {
-    real
-      alpha = azi * Math::degree(),
-      v = 1 - _e2 * Math::sq(sin(phi * Math::degree()));
-    return _a / (sqrt(v) *
-                 (Math::sq(cos(alpha)) * v / (1 - _e2) + Math::sq(sin(alpha))));
+    real calp, salp,
+      v = 1 - _e2 * Math::sq(Math::sind(Math::LatFix(phi)));
+    Math::sincosd(azi, salp, calp);
+    return _a / (sqrt(v) * (Math::sq(calp) * v / (1 - _e2) + Math::sq(salp)));
   }
 
 } // namespace GeographicLib
diff --git a/src/EllipticFunction.cpp b/src/EllipticFunction.cpp
index 7540cc0..3c0650d 100644
--- a/src/EllipticFunction.cpp
+++ b/src/EllipticFunction.cpp
@@ -2,7 +2,7 @@
  * \file EllipticFunction.cpp
  * \brief Implementation for GeographicLib::EllipticFunction class
  *
- * Copyright (c) Charles Karney (2008-2012) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2008-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -456,10 +456,8 @@ namespace GeographicLib {
   Math::real EllipticFunction::Ed(real ang) const {
     real n = ceil(ang/360 - real(0.5));
     ang -= 360 * n;
-    real
-      phi = ang * Math::degree(),
-      sn = abs(ang) == 180 ? 0 : sin(phi),
-      cn = abs(ang) ==  90 ? 0 : cos(phi);
+    real sn, cn;
+    Math::sincosd(ang, sn, cn);
     return E(sn, cn, Delta(sn, cn)) + 4 * E() * n;
   }
 
diff --git a/src/GARS.cpp b/src/GARS.cpp
new file mode 100644
index 0000000..d846250
--- /dev/null
+++ b/src/GARS.cpp
@@ -0,0 +1,122 @@
+/**
+ * \file GARS.cpp
+ * \brief Implementation for GeographicLib::GARS class
+ *
+ * Copyright (c) Charles Karney (2015) <charles at karney.com> and licensed under
+ * the MIT/X11 License.  For more information, see
+ * http://geographiclib.sourceforge.net/
+ **********************************************************************/
+
+#include <GeographicLib/GARS.hpp>
+#include <GeographicLib/Utility.hpp>
+
+namespace GeographicLib {
+
+  using namespace std;
+
+  const string GARS::digits_ = "0123456789";
+  const string GARS::letters_ = "ABCDEFGHJKLMNPQRSTUVWXYZ";
+
+  void GARS::Forward(real lat, real lon, int prec, std::string& gars) {
+    if (abs(lat) > 90)
+      throw GeographicErr("Latitude " + Utility::str(lat)
+                          + "d not in [-90d, 90d]");
+    if (Math::isnan(lat) || Math::isnan(lon)) {
+      gars = "INVALID";
+      return;
+    }
+    lon = Math::AngNormalize(lon); // lon in [-180,180)
+    if (lat == 90) lat *= (1 - numeric_limits<real>::epsilon() / 2);
+    prec = max(0, min(int(maxprec_), prec));
+    int
+      x = int(floor(lon * m_)) - lonorig_ * m_,
+      y = int(floor(lat * m_)) - latorig_ * m_,
+      ilon = x * mult1_ / m_,
+      ilat = y * mult1_ / m_;
+    x -= ilon * m_ / mult1_; y -= ilat * m_ / mult1_;
+    char gars1[maxlen_];
+    ++ilon;
+    for (int c = lonlen_; c--;) {
+      gars1[c] = digits_[ ilon % baselon_]; ilon /= baselon_;
+    }
+    for (int c = latlen_; c--;) {
+      gars1[lonlen_ + c] = letters_[ilat % baselat_]; ilat /= baselat_;
+    }
+    if (prec > 0) {
+      ilon = x / mult3_; ilat = y / mult3_;
+      gars1[baselen_] = digits_[mult2_ * (mult2_ - 1 - ilat) + ilon + 1];
+      if (prec > 1) {
+        ilon = x % mult3_; ilat = y % mult3_;
+        gars1[baselen_ + 1] = digits_[mult3_ * (mult3_ - 1 - ilat) + ilon + 1];
+      }
+    }
+    gars.resize(baselen_ + prec);
+    copy(gars1, gars1 + baselen_ + prec, gars.begin());
+  }
+
+  void GARS::Reverse(const std::string& gars, real& lat, real& lon,
+                        int& prec, bool centerp) {
+    int len = int(gars.length());
+    if (len >= 3 &&
+        toupper(gars[0]) == 'I' &&
+        toupper(gars[1]) == 'N' &&
+        toupper(gars[2]) == 'V') {
+      lat = lon = Math::NaN();
+      return;
+    }
+    if (len < baselen_)
+      throw GeographicErr("GARS must have at least 5 characters " + gars);
+    if (len > maxlen_)
+      throw GeographicErr("GARS can have at most 7 characters " + gars);
+    int prec1 = len - baselen_;
+    int ilon = 0;
+    for (int c = 0; c < lonlen_; ++c) {
+      int k = Utility::lookup(digits_, gars[c]);
+      if (k < 0)
+        throw GeographicErr("GARS must start with 3 digits " + gars);
+      ilon = ilon * baselon_ + k;
+    }
+    if (!(ilon >= 1 && ilon <= 720))
+        throw GeographicErr("Initial digits in GARS must lie in [1, 720] " +
+                            gars);
+    --ilon;
+    int ilat = 0;
+    for (int c = 0; c < latlen_; ++c) {
+      int k = Utility::lookup(letters_, gars[lonlen_ + c]);
+      if (k < 0)
+        throw GeographicErr("Illegal letters in GARS " + gars.substr(3,2));
+      ilat = ilat * baselat_ + k;
+    }
+    if (!(ilat < 360))
+      throw  GeographicErr("GARS letters must lie in [AA, QZ] " + gars);
+    real
+      unit = mult1_,
+      lat1 = ilat + latorig_ * unit,
+      lon1 = ilon + lonorig_ * unit;
+    if (prec1 > 0) {
+      int k = Utility::lookup(digits_, gars[baselen_]);
+      if (!(k >= 1 && k <= mult2_ * mult2_))
+        throw GeographicErr("6th character in GARS must [1, 4] " + gars);
+      --k;
+      unit *= mult2_;
+      lat1 = mult2_ * lat1 + (mult2_ - 1 - k / mult2_);
+      lon1 = mult2_ * lon1 + (k % mult2_);
+      if (prec1 > 1) {
+        k = Utility::lookup(digits_, gars[baselen_ + 1]);
+        if (!(k >= 1 /* && k <= mult3_ * mult3_ */))
+          throw GeographicErr("7th character in GARS must [1, 9] " + gars);
+        --k;
+        unit *= mult3_;
+        lat1 = mult3_ * lat1 + (mult3_ - 1 - k / mult3_);
+        lon1 = mult3_ * lon1 + (k % mult3_);
+      }
+    }
+    if (centerp) {
+      unit *= 2; lat1 = 2 * lat1 + 1; lon1 = 2 * lon1 + 1;
+    }
+    lat = lat1 / unit;
+    lon = lon1 / unit;
+    prec = prec1;
+  }
+
+} // namespace GeographicLib
diff --git a/src/GeoCoords.cpp b/src/GeoCoords.cpp
index 5a937e3..bc89c61 100644
--- a/src/GeoCoords.cpp
+++ b/src/GeoCoords.cpp
@@ -16,7 +16,7 @@ namespace GeographicLib {
 
   using namespace std;
 
-  void GeoCoords::Reset(const std::string& s, bool centerp, bool swaplatlong) {
+  void GeoCoords::Reset(const std::string& s, bool centerp, bool longfirst) {
     vector<string> sa;
     const char* spaces = " \t\n\v\f\r,"; // Include comma as a space
     for (string::size_type pos0 = 0, pos1; pos0 != string::npos;) {
@@ -32,7 +32,7 @@ namespace GeographicLib {
       UTMUPS::Reverse(_zone, _northp, _easting, _northing,
                       _lat, _long, _gamma, _k);
     } else if (sa.size() == 2) {
-      DMS::DecodeLatLon(sa[0], sa[1], _lat, _long, swaplatlong);
+      DMS::DecodeLatLon(sa[0], sa[1], _lat, _long, longfirst);
       _long = Math::AngNormalize(_long);
       UTMUPS::Forward( _lat, _long,
                        _zone, _northp, _easting, _northing, _gamma, _k);
@@ -59,12 +59,12 @@ namespace GeographicLib {
     CopyToAlt();
   }
 
-  string GeoCoords::GeoRepresentation(int prec, bool swaplatlong) const {
+  string GeoCoords::GeoRepresentation(int prec, bool longfirst) const {
     prec = max(0, min(9 + Math::extra_digits(), prec) + 5);
     ostringstream os;
     os << fixed << setprecision(prec);
-    real a = swaplatlong ? _long : _lat;
-    real b = swaplatlong ? _lat : _long;
+    real a = longfirst ? _long : _lat;
+    real b = longfirst ? _lat : _long;
     if (!Math::isnan(a))
       os << a;
     else
@@ -77,13 +77,13 @@ namespace GeographicLib {
     return os.str();
   }
 
-  string GeoCoords::DMSRepresentation(int prec, bool swaplatlong,
+  string GeoCoords::DMSRepresentation(int prec, bool longfirst,
                                       char dmssep) const {
     prec = max(0, min(10 + Math::extra_digits(), prec) + 5);
-    return DMS::Encode(swaplatlong ? _long : _lat, unsigned(prec),
-                       swaplatlong ? DMS::LONGITUDE : DMS::LATITUDE, dmssep) +
-      " " + DMS::Encode(swaplatlong ? _lat : _long, unsigned(prec),
-                        swaplatlong ? DMS::LATITUDE : DMS::LONGITUDE, dmssep);
+    return DMS::Encode(longfirst ? _long : _lat, unsigned(prec),
+                       longfirst ? DMS::LONGITUDE : DMS::LATITUDE, dmssep) +
+      " " + DMS::Encode(longfirst ? _lat : _long, unsigned(prec),
+                        longfirst ? DMS::LATITUDE : DMS::LONGITUDE, dmssep);
   }
 
   string GeoCoords::MGRSRepresentation(int prec) const {
diff --git a/src/Geocentric.cpp b/src/Geocentric.cpp
index e3f670f..c9b76c5 100644
--- a/src/Geocentric.cpp
+++ b/src/Geocentric.cpp
@@ -36,15 +36,10 @@ namespace GeographicLib {
   void Geocentric::IntForward(real lat, real lon, real h,
                               real& X, real& Y, real& Z,
                               real M[dim2_]) const {
-    lon = Math::AngNormalize(lon);
-    real
-      phi = lat * Math::degree(),
-      lam = lon * Math::degree(),
-      sphi = sin(phi),
-      cphi = abs(lat) == 90 ? 0 : cos(phi),
-      n = _a/sqrt(1 - _e2 * Math::sq(sphi)),
-      slam = lon == -180 ? 0 : sin(lam),
-      clam = abs(lon) == 90 ? 0 : cos(lam);
+    real sphi, cphi, slam, clam;
+    Math::sincosd(Math::LatFix(lat), sphi, cphi);
+    Math::sincosd(lon, slam, clam);
+    real n = _a/sqrt(1 - _e2 * Math::sq(sphi));
     Z = (_e2m * n + h) * sphi;
     X = (n + h) * cphi;
     Y = X * slam;
@@ -151,7 +146,7 @@ namespace GeographicLib {
         h = - _a * (_f >= 0 ? _e2m : 1) * H / _e2a;
       }
     }
-    lat = atan2(sphi, cphi) / Math::degree();
+    lat = Math::atan2d(sphi, cphi);
     lon = Math::atan2d(slam, clam);
     if (M)
       Rotation(sphi, cphi, slam, clam, M);
diff --git a/src/Geodesic.cpp b/src/Geodesic.cpp
index 557a400..65ef554 100644
--- a/src/Geodesic.cpp
+++ b/src/Geodesic.cpp
@@ -142,16 +142,14 @@ namespace GeographicLib {
     // Compute longitude difference (AngDiff does this carefully).  Result is
     // in [-180, 180] but -180 is only for west-going geodesics.  180 is for
     // east-going and meridional geodesics.
-    real lon12 = Math::AngDiff(Math::AngNormalize(lon1),
-                               Math::AngNormalize(lon2));
     // If very close to being on the same half-meridian, then make it so.
-    lon12 = Math::AngRound(lon12);
+    real lon12 = Math::AngRound(Math::AngDiff(lon1, lon2));
     // Make longitude difference positive.
     int lonsign = lon12 >= 0 ? 1 : -1;
     lon12 *= lonsign;
     // If really close to the equator, treat as on equator.
-    lat1 = Math::AngRound(lat1);
-    lat2 = Math::AngRound(lat2);
+    lat1 = Math::AngRound(Math::LatFix(lat1));
+    lat2 = Math::AngRound(Math::LatFix(lat2));
     // Swap points so that point with higher (abs) latitude is point 1
     int swapp = abs(lat1) >= abs(lat2) ? 1 : -1;
     if (swapp < 0) {
@@ -174,19 +172,16 @@ namespace GeographicLib {
     // check, e.g., on verifying quadrants in atan2.  In addition, this
     // enforces some symmetries in the results returned.
 
-    real phi, sbet1, cbet1, sbet2, cbet2, s12x, m12x;
+    real sbet1, cbet1, sbet2, cbet2, s12x, m12x;
 
-    phi = lat1 * Math::degree();
-    // Ensure cbet1 = +epsilon at poles
-    sbet1 = _f1 * sin(phi);
-    cbet1 = lat1 == -90 ? tiny_ : cos(phi);
-    Math::norm(sbet1, cbet1);
+    Math::sincosd(lat1, sbet1, cbet1); sbet1 *= _f1;
+    // Ensure cbet1 = +epsilon at poles; doing the fix on beta means that sig12
+    // will be <= 2*tiny for two points at the same pole.
+    Math::norm(sbet1, cbet1); cbet1 = max(tiny_, cbet1);
 
-    phi = lat2 * Math::degree();
+    Math::sincosd(lat2, sbet2, cbet2); sbet2 *= _f1;
     // Ensure cbet2 = +epsilon at poles
-    sbet2 = _f1 * sin(phi);
-    cbet2 = abs(lat2) == 90 ? tiny_ : cos(phi);
-    Math::norm(sbet2, cbet2);
+    Math::norm(sbet2, cbet2); cbet2 = max(tiny_, cbet2);
 
     // If cbet1 < -sbet1, then cbet2 - cbet1 is a sensitive measure of the
     // |bet1| - |bet2|.  Alternatively (cbet1 >= -sbet1), abs(sbet2) + sbet1 is
@@ -209,14 +204,13 @@ namespace GeographicLib {
       dn2 = sqrt(1 + _ep2 * Math::sq(sbet2));
 
     real
-      lam12 = lon12 * Math::degree(),
-      slam12 = abs(lon12) == 180 ? 0 : sin(lam12),
-      clam12 = cos(lam12);      // lon12 == 90 isn't interesting
+      lam12 = lon12 * Math::degree(), slam12, clam12;
+    Math::sincosd(lon12, slam12, clam12);
 
     // initial values to suppress warning
     real a12, sig12, calp1, salp1, calp2 = 0, salp2 = 0;
-    // index zero elements of these arrays are unused
-    real C1a[nC1_ + 1], C2a[nC2_ + 1], C3a[nC3_];
+    // index zero element of this array is unused
+    real Ca[nC_];
 
     bool meridian = lat1 == -90 || slam12 == 0;
 
@@ -238,9 +232,9 @@ namespace GeographicLib {
                     csig1 * csig2 + ssig1 * ssig2);
       {
         real dummy;
-        Lengths(_n, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2,
-                cbet1, cbet2, s12x, m12x, dummy,
-                (outmask & GEODESICSCALE) != 0U, M12, M21, C1a, C2a);
+        Lengths(_n, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2, cbet1, cbet2,
+                outmask | DISTANCE | REDUCEDLENGTH,
+                s12x, m12x, dummy, M12, M21, Ca);
       }
       // Add the check for sig12 since zero length geodesics might yield m12 <
       // 0.  Test case was
@@ -250,6 +244,9 @@ namespace GeographicLib {
       // In fact, we will have sig12 > pi/2 for meridional geodesic which is
       // not a shortest path.
       if (sig12 < 1 || m12x >= 0) {
+        // Need at least 2, to handle 90 0 90 180
+        if (sig12 < 3 * tiny_)
+          sig12 = m12x = s12x = 0;
         m12x *= _b;
         s12x *= _b;
         a12 = sig12 / Math::degree();
@@ -283,7 +280,7 @@ namespace GeographicLib {
       sig12 = InverseStart(sbet1, cbet1, dn1, sbet2, cbet2, dn2,
                            lam12,
                            salp1, calp1, salp2, calp2, dnm,
-                           C1a, C2a);
+                           Ca);
 
       if (sig12 >= 0) {
         // Short lines (InverseStart sets salp2, calp2, dnm)
@@ -320,7 +317,7 @@ namespace GeographicLib {
           real dv;
           real v = Lambda12(sbet1, cbet1, dn1, sbet2, cbet2, dn2, salp1, calp1,
                             salp2, calp2, sig12, ssig1, csig1, ssig2, csig2,
-                            eps, omg12, numit < maxit1_, dv, C1a, C2a, C3a)
+                            eps, omg12, numit < maxit1_, dv, Ca)
             - lam12;
           // 2 * tol0 is approximately 1 ulp for a number in [0, pi].
           // Reversed test to allow escape with NaNs
@@ -364,9 +361,12 @@ namespace GeographicLib {
         }
         {
           real dummy;
+          // Ensure that the reduced length and geodesic scale are computed in
+          // a "canonical" way, with the I2 integral.
+          unsigned lengthmask = outmask |
+            (outmask & (REDUCEDLENGTH | GEODESICSCALE) ? DISTANCE : NONE);
           Lengths(eps, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2,
-                  cbet1, cbet2, s12x, m12x, dummy,
-                  (outmask & GEODESICSCALE) != 0U, M12, M21, C1a, C2a);
+                  cbet1, cbet2, lengthmask, s12x, m12x, dummy, M12, M21, Ca);
         }
         m12x *= _b;
         s12x *= _b;
@@ -398,11 +398,10 @@ namespace GeographicLib {
           A4 = Math::sq(_a) * calp0 * salp0 * _e2;
         Math::norm(ssig1, csig1);
         Math::norm(ssig2, csig2);
-        real C4a[nC4_];
-        C4f(eps, C4a);
+        C4f(eps, Ca);
         real
-          B41 = SinCosSeries(false, ssig1, csig1, C4a, nC4_),
-          B42 = SinCosSeries(false, ssig2, csig2, C4a, nC4_);
+          B41 = SinCosSeries(false, ssig1, csig1, Ca, nC4_),
+          B42 = SinCosSeries(false, ssig2, csig2, Ca, nC4_);
         S12 = A4 * (B42 - B41);
       } else
         // Avoid problems with indeterminate sig1, sig2 on equator
@@ -463,31 +462,57 @@ namespace GeographicLib {
   void Geodesic::Lengths(real eps, real sig12,
                          real ssig1, real csig1, real dn1,
                          real ssig2, real csig2, real dn2,
-                         real cbet1, real cbet2,
-                         real& s12b, real& m12b, real& m0,
-                         bool scalep, real& M12, real& M21,
-                         // Scratch areas of the right size
-                         real C1a[], real C2a[]) const {
+                         real cbet1, real cbet2, unsigned outmask,
+                         real& s12b, real& m12b, real& m0, real& M12, real& M21,
+                         // Scratch area of the right size
+                         real Ca[]) const {
     // Return m12b = (reduced length)/_b; also calculate s12b = distance/_b,
     // and m0 = coefficient of secular term in expression for reduced length.
-    C1f(eps, C1a);
-    C2f(eps, C2a);
-    real
-      A1m1 = A1m1f(eps),
-      AB1 = (1 + A1m1) * (SinCosSeries(true, ssig2, csig2, C1a, nC1_) -
-                          SinCosSeries(true, ssig1, csig1, C1a, nC1_)),
-      A2m1 = A2m1f(eps),
-      AB2 = (1 + A2m1) * (SinCosSeries(true, ssig2, csig2, C2a, nC2_) -
-                          SinCosSeries(true, ssig1, csig1, C2a, nC2_));
-    m0 = A1m1 - A2m1;
-    real J12 = m0 * sig12 + (AB1 - AB2);
-    // Missing a factor of _b.
-    // Add parens around (csig1 * ssig2) and (ssig1 * csig2) to ensure accurate
-    // cancellation in the case of coincident points.
-    m12b = dn2 * (csig1 * ssig2) - dn1 * (ssig1 * csig2) - csig1 * csig2 * J12;
-    // Missing a factor of _b
-    s12b = (1 + A1m1) * sig12 + AB1;
-    if (scalep) {
+
+    outmask &= OUT_MASK;
+    // outmask & DISTANCE: set s12b
+    // outmask & REDUCEDLENGTH: set m12b & m0
+    // outmask & GEODESICSCALE: set M12 & M21
+
+    real m0x = 0, J12 = 0, A1 = 0, A2 = 0;
+    real Cb[nC2_ + 1];
+    if (outmask & (DISTANCE | REDUCEDLENGTH | GEODESICSCALE)) {
+      A1 = A1m1f(eps);
+      C1f(eps, Ca);
+      if (outmask & (REDUCEDLENGTH | GEODESICSCALE)) {
+        A2 = A2m1f(eps);
+        C2f(eps, Cb);
+        m0x = A1 - A2;
+        A2 = 1 + A2;
+      }
+      A1 = 1 + A1;
+    }
+    if (outmask & DISTANCE) {
+      real B1 = SinCosSeries(true, ssig2, csig2, Ca, nC1_) -
+        SinCosSeries(true, ssig1, csig1, Ca, nC1_);
+      // Missing a factor of _b
+      s12b = A1 * (sig12 + B1);
+      if (outmask & (REDUCEDLENGTH | GEODESICSCALE)) {
+        real B2 = SinCosSeries(true, ssig2, csig2, Cb, nC2_) -
+          SinCosSeries(true, ssig1, csig1, Cb, nC2_);
+        J12 = m0x * sig12 + (A1 * B1 - A2 * B2);
+      }
+    } else if (outmask & (REDUCEDLENGTH | GEODESICSCALE)) {
+      // Assume here that nC1_ >= nC2_
+      for (int l = 1; l <= nC2_; ++l)
+        Cb[l] = A1 * Ca[l] - A2 * Cb[l];
+      J12 = m0x * sig12 + (SinCosSeries(true, ssig2, csig2, Cb, nC2_) -
+                           SinCosSeries(true, ssig1, csig1, Cb, nC2_));
+    }
+    if (outmask & REDUCEDLENGTH) {
+      m0 = m0x;
+      // Missing a factor of _b.
+      // Add parens around (csig1 * ssig2) and (ssig1 * csig2) to ensure
+      // accurate cancellation in the case of coincident points.
+      m12b = dn2 * (csig1 * ssig2) - dn1 * (ssig1 * csig2) -
+        csig1 * csig2 * J12;
+    }
+    if (outmask & GEODESICSCALE) {
       real csig12 = csig1 * csig2 + ssig1 * ssig2;
       real t = _ep2 * (cbet1 - cbet2) * (cbet1 + cbet2) / (dn1 + dn2);
       M12 = csig12 + (t * ssig2 - csig2 * J12) * ssig1 / dn1;
@@ -510,7 +535,7 @@ namespace GeographicLib {
         S = p * q / 4,            // S = r^3 * s
         r2 = Math::sq(r),
         r3 = r * r2,
-        // The discrimant of the quadratic equation for T3.  This is zero on
+        // The discriminant of the quadratic equation for T3.  This is zero on
         // the evolute curve p^(1/3)+q^(1/3) = 1
         disc = S * (S + 2 * r3);
       real u = r;
@@ -555,8 +580,8 @@ namespace GeographicLib {
                                     real& salp2, real& calp2,
                                     // Only updated for short lines
                                     real& dnm,
-                                    // Scratch areas of the right size
-                                    real C1a[], real C2a[]) const {
+                                    // Scratch area of the right size
+                                    real Ca[]) const {
     // Return a starting point for Newton's method in salp1 and calp1 (function
     // value is -1).  If Newton's method doesn't need to be used, return also
     // salp2 and calp2 and function value is sig12.
@@ -646,8 +671,7 @@ namespace GeographicLib {
         // Inverse.
         Lengths(_n, Math::pi() + bet12a,
                 sbet1, -cbet1, dn1, sbet2, cbet2, dn2,
-                cbet1, cbet2, dummy, m12b, m0, false,
-                dummy, dummy, C1a, C2a);
+                cbet1, cbet2, REDUCEDLENGTH, dummy, m12b, m0, dummy, dummy, Ca);
         x = -1 + m12b / (cbet1 * cbet2 * m0 * Math::pi());
         betscale = x < -real(0.01) ? sbet12a / x :
           -_f * Math::sq(cbet1) * Math::pi();
@@ -726,8 +750,8 @@ namespace GeographicLib {
                                 real& ssig2, real& csig2,
                                 real& eps, real& domg12,
                                 bool diffp, real& dlam12,
-                                // Scratch areas of the right size
-                                real C1a[], real C2a[], real C3a[]) const {
+                                // Scratch area of the right size
+                                real Ca[]) const {
 
     if (sbet1 == 0 && calp1 == 0)
       // Break degeneracy of equatorial line.  This case has already been
@@ -779,9 +803,9 @@ namespace GeographicLib {
     real B312, h0;
     real k2 = Math::sq(calp0) * _ep2;
     eps = k2 / (2 * (1 + sqrt(1 + k2)) + k2);
-    C3f(eps, C3a);
-    B312 = (SinCosSeries(true, ssig2, csig2, C3a, nC3_-1) -
-            SinCosSeries(true, ssig1, csig1, C3a, nC3_-1));
+    C3f(eps, Ca);
+    B312 = (SinCosSeries(true, ssig2, csig2, Ca, nC3_-1) -
+            SinCosSeries(true, ssig1, csig1, Ca, nC3_-1));
     h0 = -_f * A3f(eps);
     domg12 = salp0 * h0 * (sig12 + B312);
     lam12 = omg12 + domg12;
@@ -792,8 +816,8 @@ namespace GeographicLib {
       else {
         real dummy;
         Lengths(eps, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2,
-                cbet1, cbet2, dummy, dlam12, dummy,
-                false, dummy, dummy, C1a, C2a);
+                cbet1, cbet2, REDUCEDLENGTH,
+                dummy, dlam12, dummy, dummy, dummy, Ca);
         dlam12 *= _f1 / (calp2 * cbet2);
       }
     }
@@ -1104,27 +1128,27 @@ namespace GeographicLib {
 
   // The scale factor A2-1 = mean value of (d/dsigma)I2 - 1
   Math::real Geodesic::A2m1f(real eps) {
-    // Generated by Maxima on 2015-05-05 18:08:12-04:00
+    // Generated by Maxima on 2015-05-29 08:09:47-04:00
 #if GEOGRAPHICLIB_GEODESIC_ORDER/2 == 1
     static const real coeff[] = {
-      // A2/(1-eps)-1, polynomial in eps2 of order 1
-      1, 0, 4,
-    };
+      // (eps+1)*A2-1, polynomial in eps2 of order 1
+      -3, 0, 4,
+    };  // count = 3
 #elif GEOGRAPHICLIB_GEODESIC_ORDER/2 == 2
     static const real coeff[] = {
-      // A2/(1-eps)-1, polynomial in eps2 of order 2
-      9, 16, 0, 64,
-    };
+      // (eps+1)*A2-1, polynomial in eps2 of order 2
+      -7, -48, 0, 64,
+    };  // count = 4
 #elif GEOGRAPHICLIB_GEODESIC_ORDER/2 == 3
     static const real coeff[] = {
-      // A2/(1-eps)-1, polynomial in eps2 of order 3
-      25, 36, 64, 0, 256,
-    };
+      // (eps+1)*A2-1, polynomial in eps2 of order 3
+      -11, -28, -192, 0, 256,
+    };  // count = 5
 #elif GEOGRAPHICLIB_GEODESIC_ORDER/2 == 4
     static const real coeff[] = {
-      // A2/(1-eps)-1, polynomial in eps2 of order 4
-      1225, 1600, 2304, 4096, 0, 16384,
-    };
+      // (eps+1)*A2-1, polynomial in eps2 of order 4
+      -375, -704, -1792, -12288, 0, 16384,
+    };  // count = 6
 #else
 #error "Bad value for GEOGRAPHICLIB_GEODESIC_ORDER"
 #endif
@@ -1132,7 +1156,7 @@ namespace GeographicLib {
                                 "Coefficient array size mismatch in A2m1f");
     int m = nA2_/2;
     real t = Math::polyval(m, coeff, Math::sq(eps)) / coeff[m + 1];
-    return t * (1 - eps) - eps;
+    return (t - eps) / (1 + eps);
   }
 
   // The coefficients C2[l] in the Fourier expansion of B2
diff --git a/src/GeodesicExact.cpp b/src/GeodesicExact.cpp
index c677d2f..888b08b 100644
--- a/src/GeodesicExact.cpp
+++ b/src/GeodesicExact.cpp
@@ -147,16 +147,14 @@ namespace GeographicLib {
     // Compute longitude difference (AngDiff does this carefully).  Result is
     // in [-180, 180] but -180 is only for west-going geodesics.  180 is for
     // east-going and meridional geodesics.
-    real lon12 = Math::AngDiff(Math::AngNormalize(lon1),
-                               Math::AngNormalize(lon2));
     // If very close to being on the same half-meridian, then make it so.
-    lon12 = Math::AngRound(lon12);
+    real lon12 = Math::AngRound(Math::AngDiff(lon1, lon2));
     // Make longitude difference positive.
     int lonsign = lon12 >= 0 ? 1 : -1;
     lon12 *= lonsign;
     // If really close to the equator, treat as on equator.
-    lat1 = Math::AngRound(lat1);
-    lat2 = Math::AngRound(lat2);
+    lat1 = Math::AngRound(Math::LatFix(lat1));
+    lat2 = Math::AngRound(Math::LatFix(lat2));
     // Swap points so that point with higher (abs) latitude is point 1
     int swapp = abs(lat1) >= abs(lat2) ? 1 : -1;
     if (swapp < 0) {
@@ -179,22 +177,19 @@ namespace GeographicLib {
     // check, e.g., on verifying quadrants in atan2.  In addition, this
     // enforces some symmetries in the results returned.
 
-    real phi, sbet1, cbet1, sbet2, cbet2, s12x, m12x;
+    real sbet1, cbet1, sbet2, cbet2, s12x, m12x;
     // Initialize for the meridian.  No longitude calculation is done in this
     // case to let the parameter default to 0.
     EllipticFunction E(-_ep2);
 
-    phi = lat1 * Math::degree();
-    // Ensure cbet1 = +epsilon at poles
-    sbet1 = _f1 * sin(phi);
-    cbet1 = lat1 == -90 ? tiny_ : cos(phi);
-    Math::norm(sbet1, cbet1);
+    Math::sincosd(lat1, sbet1, cbet1); sbet1 *= _f1;
+    // Ensure cbet1 = +epsilon at poles; doing the fix on beta means that sig12
+    // will be <= 2*tiny for two points at the same pole.
+    Math::norm(sbet1, cbet1); cbet1 = max(tiny_, cbet1);
 
-    phi = lat2 * Math::degree();
+    Math::sincosd(lat2, sbet2, cbet2); sbet2 *= _f1;
     // Ensure cbet2 = +epsilon at poles
-    sbet2 = _f1 * sin(phi);
-    cbet2 = abs(lat2) == 90 ? tiny_ : cos(phi);
-    Math::norm(sbet2, cbet2);
+    Math::norm(sbet2, cbet2); cbet2 = max(tiny_, cbet2);
 
     // If cbet1 < -sbet1, then cbet2 - cbet1 is a sensitive measure of the
     // |bet1| - |bet2|.  Alternatively (cbet1 >= -sbet1), abs(sbet2) + sbet1 is
@@ -219,9 +214,8 @@ namespace GeographicLib {
              sqrt(1 - _e2 * Math::sq(cbet2)) / _f1);
 
     real
-      lam12 = lon12 * Math::degree(),
-      slam12 = abs(lon12) == 180 ? 0 : sin(lam12),
-      clam12 = cos(lam12);      // lon12 == 90 isn't interesting
+      lam12 = lon12 * Math::degree(), slam12, clam12;
+    Math::sincosd(lon12, slam12, clam12);
 
     // initial values to suppress warning
     real a12, sig12, calp1, salp1, calp2 = 0, salp2 = 0;
@@ -247,8 +241,8 @@ namespace GeographicLib {
       {
         real dummy;
         Lengths(E, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2,
-                cbet1, cbet2, s12x, m12x, dummy,
-                (outmask & GEODESICSCALE) != 0U, M12, M21);
+                cbet1, cbet2, outmask | REDUCEDLENGTH,
+                s12x, m12x, dummy, M12, M21);
       }
       // Add the check for sig12 since zero length geodesics might yield m12 <
       // 0.  Test case was
@@ -258,6 +252,9 @@ namespace GeographicLib {
       // In fact, we will have sig12 > pi/2 for meridional geodesic which is
       // not a shortest path.
       if (sig12 < 1 || m12x >= 0) {
+        // Need at least 2, to handle 90 0 90 180
+        if (sig12 < 3 * tiny_)
+          sig12 = m12x = s12x = 0;
         m12x *= _b;
         s12x *= _b;
         a12 = sig12 / Math::degree();
@@ -390,8 +387,7 @@ namespace GeographicLib {
         {
           real dummy;
           Lengths(E, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2,
-                  cbet1, cbet2, s12x, m12x, dummy,
-                  (outmask & GEODESICSCALE) != 0U, M12, M21);
+                  cbet1, cbet2, outmask, s12x, m12x, dummy, M12, M21);
         }
         m12x *= _b;
         s12x *= _b;
@@ -488,29 +484,43 @@ namespace GeographicLib {
                               real sig12,
                               real ssig1, real csig1, real dn1,
                               real ssig2, real csig2, real dn2,
-                              real cbet1, real cbet2,
+                              real cbet1, real cbet2, unsigned outmask,
                               real& s12b, real& m12b, real& m0,
-                              bool scalep, real& M12, real& M21) const {
+                              real& M12, real& M21) const {
     // Return m12b = (reduced length)/_b; also calculate s12b = distance/_b,
     // and m0 = coefficient of secular term in expression for reduced length.
 
+    outmask &= OUT_ALL;
+    // outmask & DISTANCE: set s12b
+    // outmask & REDUCEDLENGTH: set m12b & m0
+    // outmask & GEODESICSCALE: set M12 & M21
+
     // It's OK to have repeated dummy arguments,
     // e.g., s12b = m0 = M12 = M21 = dummy
-    m0 = - E.k2() * E.D() / (Math::pi() / 2);
-    real J12 = m0 *
-      (sig12 + E.deltaD(ssig2, csig2, dn2) - E.deltaD(ssig1, csig1, dn1));
-    // Missing a factor of _b.
-    // Add parens around (csig1 * ssig2) and (ssig1 * csig2) to ensure accurate
-    // cancellation in the case of coincident points.
-    m12b = dn2 * (csig1 * ssig2) - dn1 * (ssig1 * csig2) - csig1 * csig2 * J12;
-    // Missing a factor of _b
-    s12b = E.E() / (Math::pi() / 2) *
-      (sig12 + E.deltaE(ssig2, csig2, dn2) - E.deltaE(ssig1, csig1, dn1));
-    if (scalep) {
-      real csig12 = csig1 * csig2 + ssig1 * ssig2;
-      real t = _ep2 * (cbet1 - cbet2) * (cbet1 + cbet2) / (dn1 + dn2);
-      M12 = csig12 + (t * ssig2 - csig2 * J12) * ssig1 / dn1;
-      M21 = csig12 - (t * ssig1 - csig1 * J12) * ssig2 / dn2;
+
+    if (outmask & DISTANCE)
+      // Missing a factor of _b
+      s12b = E.E() / (Math::pi() / 2) *
+        (sig12 + (E.deltaE(ssig2, csig2, dn2) - E.deltaE(ssig1, csig1, dn1)));
+    if (outmask & (REDUCEDLENGTH | GEODESICSCALE)) {
+      real
+        m0x = - E.k2() * E.D() / (Math::pi() / 2),
+        J12 = m0x *
+        (sig12 + (E.deltaD(ssig2, csig2, dn2) - E.deltaD(ssig1, csig1, dn1)));
+      if (outmask & REDUCEDLENGTH) {
+        m0 = m0x;
+        // Missing a factor of _b.  Add parens around (csig1 * ssig2) and
+        // (ssig1 * csig2) to ensure accurate cancellation in the case of
+        // coincident points.
+        m12b = dn2 * (csig1 * ssig2) - dn1 * (ssig1 * csig2) -
+          csig1 * csig2 * J12;
+      }
+      if (outmask & GEODESICSCALE) {
+        real csig12 = csig1 * csig2 + ssig1 * ssig2;
+        real t = _ep2 * (cbet1 - cbet2) * (cbet1 + cbet2) / (dn1 + dn2);
+        M12 = csig12 + (t * ssig2 - csig2 * J12) * ssig1 / dn1;
+        M21 = csig12 - (t * ssig1 - csig1 * J12) * ssig2 / dn2;
+      }
     }
   }
 
@@ -529,7 +539,7 @@ namespace GeographicLib {
         S = p * q / 4,            // S = r^3 * s
         r2 = Math::sq(r),
         r3 = r * r2,
-        // The discrimant of the quadratic equation for T3.  This is zero on
+        // The discriminant of the quadratic equation for T3.  This is zero on
         // the evolute curve p^(1/3)+q^(1/3) = 1
         disc = S * (S + 2 * r3);
       real u = r;
@@ -664,8 +674,7 @@ namespace GeographicLib {
         // Inverse.
         Lengths(E, Math::pi() + bet12a,
                 sbet1, -cbet1, dn1, sbet2, cbet2, dn2,
-                cbet1, cbet2, dummy, m12b, m0, false,
-                dummy, dummy);
+                cbet1, cbet2, REDUCEDLENGTH, dummy, m12b, m0, dummy, dummy);
         x = -1 + m12b / (cbet1 * cbet2 * m0 * Math::pi());
         betscale = x < -real(0.01) ? sbet12a / x :
           -_f * Math::sq(cbet1) * Math::pi();
@@ -806,7 +815,7 @@ namespace GeographicLib {
                        cchi1 * cchi2 + somg1 * somg2);
     lam12 = chi12 -
       _e2/_f1 * salp0 * E.H() / (Math::pi() / 2) *
-      (sig12 + E.deltaH(ssig2, csig2, dn2) - E.deltaH(ssig1, csig1, dn1) );
+      (sig12 + (E.deltaH(ssig2, csig2, dn2) - E.deltaH(ssig1, csig1, dn1)));
 
     if (diffp) {
       if (calp2 == 0)
@@ -814,8 +823,8 @@ namespace GeographicLib {
       else {
         real dummy;
         Lengths(E, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2,
-                cbet1, cbet2, dummy, dlam12, dummy,
-                false, dummy, dummy);
+                cbet1, cbet2, REDUCEDLENGTH,
+                dummy, dlam12, dummy, dummy, dummy);
         dlam12 *= _f1 / (calp2 * cbet2);
       }
     }
diff --git a/src/GeodesicLine.cpp b/src/GeodesicLine.cpp
index 0a3d686..a9ad1a5 100644
--- a/src/GeodesicLine.cpp
+++ b/src/GeodesicLine.cpp
@@ -36,10 +36,9 @@ namespace GeographicLib {
                              real lat1, real lon1, real azi1,
                              unsigned caps)
     : tiny_(g.tiny_)
-    , _lat1(lat1)
+    , _lat1(Math::LatFix(lat1))
     , _lon1(lon1)
-    // Guard against underflow in salp0.  Also -0 is converted to +0.
-    , _azi1(Math::AngRound(Math::AngNormalize(azi1)))
+    , _azi1(Math::AngNormalize(azi1))
     , _a(g._a)
     , _f(g._f)
     , _b(g._b)
@@ -48,17 +47,12 @@ namespace GeographicLib {
       // Always allow latitude and azimuth and unrolling of longitude
     , _caps(caps | LATITUDE | AZIMUTH | LONG_UNROLL)
   {
-    real alp1 = _azi1 * Math::degree();
-    // Enforce sin(pi) == 0 and cos(pi/2) == 0.  Better to face the ensuing
-    // problems directly than to skirt them.
-    _salp1 =     _azi1  == -180 ? 0 : sin(alp1);
-    _calp1 = abs(_azi1) ==   90 ? 0 : cos(alp1);
-    real cbet1, sbet1, phi;
-    phi = lat1 * Math::degree();
+    // Guard against underflow in salp0.  Also -0 is converted to +0.
+    Math::sincosd(Math::AngRound(_azi1), _salp1, _calp1);
+    real cbet1, sbet1;
+    Math::sincosd(Math::AngRound(_lat1), sbet1, cbet1); sbet1 *= _f1;
     // Ensure cbet1 = +epsilon at poles
-    sbet1 = _f1 * sin(phi);
-    cbet1 = abs(lat1) == 90 ? tiny_ : cos(phi);
-    Math::norm(sbet1, cbet1);
+    Math::norm(sbet1, cbet1); cbet1 = max(tiny_, cbet1);
     _dn1 = sqrt(1 + g._ep2 * Math::sq(sbet1));
 
     // Evaluate alp0 from sin(alp1) * cos(bet1) = sin(alp0),
@@ -135,10 +129,7 @@ namespace GeographicLib {
     if (arcmode) {
       // Interpret s12_a12 as spherical arc length
       sig12 = s12_a12 * Math::degree();
-      real s12a = abs(s12_a12);
-      s12a -= 180 * floor(s12a / 180);
-      ssig12 = s12a ==  0 ? 0 : sin(sig12);
-      csig12 = s12a == 90 ? 0 : cos(sig12);
+      Math::sincosd(s12_a12, ssig12, csig12);
     } else {
       // Interpret s12_a12 as distance
       real
@@ -223,15 +214,13 @@ namespace GeographicLib {
         ( sig12 + (Geodesic::SinCosSeries(true, ssig2, csig2, _C3a, nC3_-1)
                    - _B31));
       real lon12 = lam12 / Math::degree();
-      // Use Math::AngNormalize2 because longitude might have wrapped
-      // multiple times.
       lon2 = outmask & LONG_UNROLL ? _lon1 + lon12 :
         Math::AngNormalize(Math::AngNormalize(_lon1) +
-                           Math::AngNormalize2(lon12));
+                           Math::AngNormalize(lon12));
     }
 
     if (outmask & LATITUDE)
-      lat2 = atan2(sbet2, _f1 * cbet2) / Math::degree();
+      lat2 = Math::atan2d(sbet2, _f1 * cbet2);
 
     if (outmask & AZIMUTH)
       azi2 = Math::atan2d(salp2, calp2);
diff --git a/src/GeodesicLineExact.cpp b/src/GeodesicLineExact.cpp
index bb78a57..7df4e66 100644
--- a/src/GeodesicLineExact.cpp
+++ b/src/GeodesicLineExact.cpp
@@ -36,10 +36,9 @@ namespace GeographicLib {
                                        real lat1, real lon1, real azi1,
                                        unsigned caps)
     : tiny_(g.tiny_)
-    , _lat1(lat1)
+    , _lat1(Math::LatFix(lat1))
     , _lon1(lon1)
-    // Guard against underflow in salp0
-    , _azi1(Math::AngRound(Math::AngNormalize(azi1)))
+    , _azi1(Math::AngNormalize(azi1))
     , _a(g._a)
     , _f(g._f)
     , _b(g._b)
@@ -50,17 +49,12 @@ namespace GeographicLib {
       // Always allow latitude and azimuth and unrolling of longitude
     , _caps(caps | LATITUDE | AZIMUTH | LONG_UNROLL)
   {
-    real alp1 = _azi1 * Math::degree();
-    // Enforce sin(pi) == 0 and cos(pi/2) == 0.  Better to face the ensuing
-    // problems directly than to skirt them.
-    _salp1 =     _azi1  == -180 ? 0 : sin(alp1);
-    _calp1 = abs(_azi1) ==   90 ? 0 : cos(alp1);
-    real cbet1, sbet1, phi;
-    phi = lat1 * Math::degree();
+    // Guard against underflow in salp0
+    Math::sincosd(Math::AngRound(_azi1), _salp1, _calp1);
+    real cbet1, sbet1;
+    Math::sincosd(Math::AngRound(_lat1), sbet1, cbet1); sbet1 *= _f1;
     // Ensure cbet1 = +epsilon at poles
-    sbet1 = _f1 * sin(phi);
-    cbet1 = abs(lat1) == 90 ? tiny_ : cos(phi);
-    Math::norm(sbet1, cbet1);
+    Math::norm(sbet1, cbet1); cbet1 = max(tiny_, cbet1);
     _dn1 = (_f >= 0 ? sqrt(1 + g._ep2 * Math::sq(sbet1)) :
             sqrt(1 - _e2 * Math::sq(cbet1)) / _f1);
 
@@ -189,23 +183,21 @@ namespace GeographicLib {
         : atan2(somg2 * _cchi1 - cchi2 * _somg1,
                 cchi2 * _cchi1 + somg2 * _somg1);
       real lam12 = chi12 -
-        _e2/_f1 * _salp0 * _H0 * (sig12 + _E.deltaH(ssig2, csig2, dn2) - _H1 );
+        _e2/_f1 * _salp0 * _H0 * (sig12 + (_E.deltaH(ssig2, csig2, dn2) - _H1));
       real lon12 = lam12 / Math::degree();
-      // Use Math::AngNormalize2 because longitude might have wrapped
-      // multiple times.
       lon2 = outmask & LONG_UNROLL ? _lon1 + lon12 :
         Math::AngNormalize(Math::AngNormalize(_lon1) +
-                           Math::AngNormalize2(lon12));
+                           Math::AngNormalize(lon12));
     }
 
     if (outmask & LATITUDE)
-      lat2 = atan2(sbet2, _f1 * cbet2) / Math::degree();
+      lat2 = Math::atan2d(sbet2, _f1 * cbet2);
 
     if (outmask & AZIMUTH)
       azi2 = Math::atan2d(salp2, calp2);
 
     if (outmask & (REDUCEDLENGTH | GEODESICSCALE)) {
-      real J12 = _k2 * _D0 * (sig12 + _E.deltaD(ssig2, csig2, dn2) - _D1);
+      real J12 = _k2 * _D0 * (sig12 + (_E.deltaD(ssig2, csig2, dn2) - _D1));
       if (outmask & REDUCEDLENGTH)
         // Add parens around (_csig1 * ssig2) and (_ssig1 * csig2) to ensure
         // accurate cancellation in the case of coincident points.
diff --git a/src/GeographicLib.pro b/src/GeographicLib.pro
index d26018b..b9d4a3c 100644
--- a/src/GeographicLib.pro
+++ b/src/GeographicLib.pro
@@ -1,4 +1,4 @@
-VERSION = 14.1.0
+VERSION = 14.2.0
 
 TEMPLATE = lib
 
@@ -13,6 +13,7 @@ SOURCES += CircularEngine.cpp
 SOURCES += DMS.cpp
 SOURCES += Ellipsoid.cpp
 SOURCES += EllipticFunction.cpp
+SOURCES += GARS.cpp
 SOURCES += GeoCoords.cpp
 SOURCES += Geocentric.cpp
 SOURCES += Geodesic.cpp
@@ -22,6 +23,7 @@ SOURCES += GeodesicLine.cpp
 SOURCES += GeodesicLineExact.cpp
 SOURCES += Geohash.cpp
 SOURCES += Geoid.cpp
+SOURCES += Georef.cpp
 SOURCES += Gnomonic.cpp
 SOURCES += GravityCircle.cpp
 SOURCES += GravityModel.cpp
@@ -51,6 +53,7 @@ HEADERS += $$INCLUDEDIR/Constants.hpp
 HEADERS += $$INCLUDEDIR/DMS.hpp
 HEADERS += $$INCLUDEDIR/Ellipsoid.hpp
 HEADERS += $$INCLUDEDIR/EllipticFunction.hpp
+HEADERS += $$INCLUDEDIR/GARS.hpp
 HEADERS += $$INCLUDEDIR/GeoCoords.hpp
 HEADERS += $$INCLUDEDIR/Geocentric.hpp
 HEADERS += $$INCLUDEDIR/Geodesic.hpp
@@ -59,6 +62,7 @@ HEADERS += $$INCLUDEDIR/GeodesicLine.hpp
 HEADERS += $$INCLUDEDIR/GeodesicLineExact.hpp
 HEADERS += $$INCLUDEDIR/Geohash.hpp
 HEADERS += $$INCLUDEDIR/Geoid.hpp
+HEADERS += $$INCLUDEDIR/Georef.hpp
 HEADERS += $$INCLUDEDIR/Gnomonic.hpp
 HEADERS += $$INCLUDEDIR/GravityCircle.hpp
 HEADERS += $$INCLUDEDIR/GravityModel.hpp
diff --git a/src/Geohash.cpp b/src/Geohash.cpp
index 9b56b76..6e510f7 100644
--- a/src/Geohash.cpp
+++ b/src/Geohash.cpp
@@ -2,7 +2,7 @@
  * \file Geohash.cpp
  * \brief Implementation for GeographicLib::Geohash class
  *
- * Copyright (c) Charles Karney (2012-2014) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2012-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -14,30 +14,28 @@ namespace GeographicLib {
 
   using namespace std;
 
-  const int Geohash::decprec_[] = {-2, -1, 0, 0, 1, 2, 3, 3, 4, 5,
-                                   6, 6, 7, 8, 9, 9, 10, 11, 12};
   const string Geohash::lcdigits_ = "0123456789bcdefghjkmnpqrstuvwxyz";
   const string Geohash::ucdigits_ = "0123456789BCDEFGHJKMNPQRSTUVWXYZ";
 
   void Geohash::Forward(real lat, real lon, int len, std::string& geohash) {
+    static const real shift = pow(real(2), 45);
+    static const real loneps = 180 / shift;
+    static const real lateps =  90 / shift;
     if (abs(lat) > 90)
       throw GeographicErr("Latitude " + Utility::str(lat)
                           + "d not in [-90d, 90d]");
-    if (lon < -540 || lon >= 540)
-      throw GeographicErr("Longitude " + Utility::str(lon)
-                          + "d not in [-540d, 540d)");
     if (Math::isnan(lat) || Math::isnan(lon)) {
-      geohash = "nan";
+      geohash = "invalid";
       return;
     }
-    if (lat == 90) lat -= lateps() / 2;
+    if (lat == 90) lat -= lateps / 2;
     lon = Math::AngNormalize(lon); // lon in [-180,180)
     // lon/loneps in [-2^45,2^45); lon/loneps + shift in [0,2^46)
     // similarly for lat
     len = max(0, min(int(maxlen_), len));
     unsigned long long
-      ulon = (unsigned long long)(floor(lon/loneps()) + shift()),
-      ulat = (unsigned long long)(floor(lat/lateps()) + shift());
+      ulon = (unsigned long long)(floor(lon/loneps) + shift),
+      ulat = (unsigned long long)(floor(lat/lateps) + shift);
     char geohash1[maxlen_];
     unsigned byte = 0;
     for (unsigned i = 0; i < 5 * unsigned(len);) {
@@ -60,16 +58,23 @@ namespace GeographicLib {
 
   void Geohash::Reverse(const std::string& geohash, real& lat, real& lon,
                         int& len, bool centerp) {
-    len = min(int(maxlen_), int(geohash.length()));
-    if (len >= 3 &&
-        toupper(geohash[0]) == 'N' &&
-        toupper(geohash[1]) == 'A' &&
-        toupper(geohash[2]) == 'N') {
+    static const real shift = pow(real(2), 45);
+    static const real loneps = 180 / shift;
+    static const real lateps =  90 / shift;
+    int len1 = min(int(maxlen_), int(geohash.length()));
+    if (len1 >= 3 &&
+        ((toupper(geohash[0]) == 'I' &&
+          toupper(geohash[1]) == 'N' &&
+          toupper(geohash[2]) == 'V') ||
+         // Check A first because it is not in a standard geohash
+         (toupper(geohash[1]) == 'A' &&
+          toupper(geohash[0]) == 'N' &&
+          toupper(geohash[2]) == 'N'))) {
       lat = lon = Math::NaN();
       return;
     }
     unsigned long long ulon = 0, ulat = 0;
-    for (unsigned k = 0, j = 0; k < unsigned(len); ++k) {
+    for (unsigned k = 0, j = 0; k < unsigned(len1); ++k) {
       int byte = Utility::lookup(ucdigits_, geohash[k]);
       if (byte < 0)
         throw GeographicErr("Illegal character in geohash " + geohash);
@@ -86,11 +91,12 @@ namespace GeographicLib {
       ulon += 1;
       ulat += 1;
     }
-    int s = 5 * (maxlen_ - len);
+    int s = 5 * (maxlen_ - len1);
     ulon <<=     (s / 2);
     ulat <<= s - (s / 2);
-    lon = ulon * loneps() - 180;
-    lat = ulat * lateps() - 90;
+    lon = ulon * loneps - 180;
+    lat = ulat * lateps - 90;
+    len = len1;
   }
 
 } // namespace GeographicLib
diff --git a/src/Geoid.cpp b/src/Geoid.cpp
index 0ebe3ca..2302ab1 100644
--- a/src/Geoid.cpp
+++ b/src/Geoid.cpp
@@ -2,7 +2,7 @@
  * \file Geoid.cpp
  * \brief Implementation for GeographicLib::Geoid class
  *
- * Copyright (c) Charles Karney (2009-2012) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2009-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -305,6 +305,7 @@ namespace GeographicLib {
 
   Math::real Geoid::height(real lat, real lon, bool gradp,
                            real& gradn, real& grade) const {
+    lat = Math::LatFix(lat);
     if (Math::isnan(lat) || Math::isnan(lon)) {
       if (gradp) gradn = grade = Math::NaN();
       return Math::NaN();
@@ -370,11 +371,9 @@ namespace GeographicLib {
         c = (1 - fy) * a + fy * b,
         h = _offset + _scale * c;
       if (gradp) {
-        real
-          phi = lat * _degree,
-          cosphi = cos(phi),
-          sinphi = sin(phi),
-          n = 1/sqrt(1 - _e2 * sinphi * sinphi);
+        real cosphi, sinphi;
+        Math::sincosd(lat, sinphi, cosphi);
+        real n = 1/sqrt(1 - _e2 * Math::sq(sinphi));
         gradn = ((1 - fx) * (v00 - v10) + fx * (v01 - v11)) *
           _rlatres / (_degree * _a * (1 - _e2) * n * n * n);
         grade = (cosphi > _eps ?
@@ -405,11 +404,9 @@ namespace GeographicLib {
         lat = max(lat, -90 + 1/(100 * _rlatres));
         fy = (90 - lat) * _rlatres;
         fy -= int(fy);
-        real
-          phi = lat * _degree,
-          cosphi = cos(phi),
-          sinphi = sin(phi),
-          n = 1/sqrt(1 - _e2 * sinphi * sinphi);
+        real cosphi, sinphi;
+        Math::sincosd(lat, sinphi, cosphi);
+        real n = 1/sqrt(1 - _e2 * Math::sq(sinphi));
         gradn = t[2] + fx * (t[4] + fx * t[7]) +
           fy * (2 * t[5] + fx * 2 * t[8] + 3 * fy * t[9]);
         grade = t[1] + fx * (2 * t[3] + fx * 3 * t[6]) +
@@ -446,6 +443,8 @@ namespace GeographicLib {
       CacheClear();
       return;
     }
+    south = Math::LatFix(south);
+    north = Math::LatFix(north);
     west = Math::AngNormalize(west); // west in [-180, 180)
     east = Math::AngNormalize(east);
     if (east <= west)
diff --git a/src/Georef.cpp b/src/Georef.cpp
new file mode 100644
index 0000000..fd1155e
--- /dev/null
+++ b/src/Georef.cpp
@@ -0,0 +1,135 @@
+/**
+ * \file Georef.cpp
+ * \brief Implementation for GeographicLib::Georef class
+ *
+ * Copyright (c) Charles Karney (2015) <charles at karney.com> and licensed under
+ * the MIT/X11 License.  For more information, see
+ * http://geographiclib.sourceforge.net/
+ **********************************************************************/
+
+#include <GeographicLib/Georef.hpp>
+#include <GeographicLib/Utility.hpp>
+
+namespace GeographicLib {
+
+  using namespace std;
+
+  const string Georef::digits_ = "0123456789";
+  const string Georef::lontile_ = "ABCDEFGHJKLMNPQRSTUVWXYZ";
+  const string Georef::lattile_ = "ABCDEFGHJKLM";
+  const string Georef::degrees_ = "ABCDEFGHJKLMNPQ";
+
+  void Georef::Forward(real lat, real lon, int prec, std::string& georef) {
+    if (abs(lat) > 90)
+      throw GeographicErr("Latitude " + Utility::str(lat)
+                          + "d not in [-90d, 90d]");
+    if (Math::isnan(lat) || Math::isnan(lon)) {
+      georef = "INVALID";
+      return;
+    }
+    lon = Math::AngNormalize(lon); // lon in [-180,180)
+    if (lat == 90) lat *= (1 - numeric_limits<real>::epsilon() / 2);
+    prec = max(-1, min(int(maxprec_), prec));
+    if (prec == 1) ++prec;      // Disallow prec = 1
+    // The C++ standard mandates 64 bits for long long.  But
+    // check, to make sure.
+    GEOGRAPHICLIB_STATIC_ASSERT(numeric_limits<long long>::digits >= 45,
+                                "long long not wide enough to store 21600e9");
+    const long long m = 60000000000LL;
+    long long
+      x = (long long)(floor(lon * m)) - lonorig_ * m,
+      y = (long long)(floor(lat * m)) - latorig_ * m;
+    int ilon = int(x / m); int ilat = int(y / m);
+    char georef1[maxlen_];
+    georef1[0] = lontile_[ilon / tile_];
+    georef1[1] = lattile_[ilat / tile_];
+    if (prec >= 0) {
+      georef1[2] = degrees_[ilon % tile_];
+      georef1[3] = degrees_[ilat % tile_];
+      if (prec > 0) {
+        x -= m * ilon; y -= m * ilat;
+        long long d = (long long)pow(real(base_), maxprec_ - prec);
+        x /= d; y /= d;
+        for (int c = prec; c--;) {
+          georef1[baselen_ + c       ] = digits_[x % base_]; x /= base_;
+          georef1[baselen_ + c + prec] = digits_[y % base_]; y /= base_;
+        }
+      }
+    }
+    georef.resize(baselen_ + 2 * prec);
+    copy(georef1, georef1 + baselen_ + 2 * prec, georef.begin());
+  }
+
+  void Georef::Reverse(const std::string& georef, real& lat, real& lon,
+                        int& prec, bool centerp) {
+    int len = int(georef.length());
+    if (len >= 3 &&
+        toupper(georef[0]) == 'I' &&
+        toupper(georef[1]) == 'N' &&
+        toupper(georef[2]) == 'V') {
+      lat = lon = Math::NaN();
+      return;
+    }
+    if (len < baselen_ - 2)
+      throw GeographicErr("Georef must start with at least 2 letters "
+                          + georef);
+    int prec1 = (2 + len - baselen_) / 2 - 1;
+    int k;
+    k = Utility::lookup(lontile_, georef[0]);
+    if (k < 0)
+      throw GeographicErr("Bad longitude tile letter in georef " + georef);
+    real lon1 = k + lonorig_ / tile_;
+    k = Utility::lookup(lattile_, georef[1]);
+    if (k < 0)
+      throw GeographicErr("Bad latitude tile letter in georef " + georef);
+    real lat1 = k + latorig_ / tile_;
+    real unit = 1;
+    if (len > 2) {
+      unit *= tile_;
+      k = Utility::lookup(degrees_, georef[2]);
+      if (k < 0)
+        throw GeographicErr("Bad longitude degree letter in georef " + georef);
+      lon1 = lon1 * tile_ + k;
+      if (len < 4)
+        throw GeographicErr("Missing latitude degree letter in georef "
+                            + georef);
+      k = Utility::lookup(degrees_, georef[3]);
+      if (k < 0)
+        throw GeographicErr("Bad latitude degree letter in georef " + georef);
+      lat1 = lat1 * tile_ + k;
+      if (prec1 > 0) {
+        if (georef.find_first_not_of(digits_, baselen_) != string::npos)
+          throw GeographicErr("Non digits in trailing portion of georef "
+                              + georef.substr(baselen_));
+        if (len % 2)
+          throw GeographicErr("Georef must end with an even number of digits "
+                              + georef.substr(baselen_));
+        if (prec1 == 1)
+          throw GeographicErr("Georef needs at least 4 digits for minutes "
+                              + georef.substr(baselen_));
+        if (prec1 > maxprec_)
+          throw GeographicErr("More than " + Utility::str(2*maxprec_)
+                              + " digits in georef " + georef.substr(baselen_));
+        for (int i = 0; i < prec1; ++i) {
+          int m = i ? base_ : 6;
+          unit *= m;
+          int
+            x = Utility::lookup(digits_, georef[baselen_ + i]),
+            y = Utility::lookup(digits_, georef[baselen_ + i + prec1]);
+          if (!(i || (x < m && y < m)))
+            throw GeographicErr("Minutes terms in georef must be less than 60 "
+                                + georef.substr(baselen_));
+          lon1 = m * lon1 + x;
+          lat1 = m * lat1 + y;
+        }
+      }
+    }
+    if (centerp) {
+      unit *= 2; lat1 = 2 * lat1 + 1; lon1 = 2 * lon1 + 1;
+    }
+    lat = (tile_ * lat1) / unit;
+    lon = (tile_ * lon1) / unit;
+    prec = prec1;
+  }
+
+} // namespace GeographicLib
diff --git a/src/Gnomonic.cpp b/src/Gnomonic.cpp
index 7f22823..e93ef6c 100644
--- a/src/Gnomonic.cpp
+++ b/src/Gnomonic.cpp
@@ -2,7 +2,7 @@
  * \file Gnomonic.cpp
  * \brief Implementation for GeographicLib::Gnomonic class
  *
- * Copyright (c) Charles Karney (2010-2011) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2010-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -39,9 +39,8 @@ namespace GeographicLib {
       x = y = Math::NaN();
     else {
       real rho = m/M;
-      azi0 *= Math::degree();
-      x = rho * sin(azi0);
-      y = rho * cos(azi0);
+      Math::sincosd(azi0, x, y);
+      x *= rho; y *= rho;
     }
   }
 
@@ -49,7 +48,7 @@ namespace GeographicLib {
                          real& lat, real& lon, real& azi, real& rk)
     const {
     real
-      azi0 = atan2(x, y) / Math::degree(),
+      azi0 = Math::atan2d(x, y),
       rho = Math::hypot(x, y),
       s = _a * atan(rho/_a);
     bool little = rho <= _a;
diff --git a/src/GravityCircle.cpp b/src/GravityCircle.cpp
index 4ba32d0..6c833f5 100644
--- a/src/GravityCircle.cpp
+++ b/src/GravityCircle.cpp
@@ -2,8 +2,8 @@
  * \file GravityCircle.cpp
  * \brief Implementation for GeographicLib::GravityCircle class
  *
- * Copyright (c) Charles Karney (2011) <charles at karney.com> and licensed under
- * the MIT/X11 License.  For more information, see
+ * Copyright (c) Charles Karney (2011-2015) <charles at karney.com> and licensed
+ * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
 
@@ -19,7 +19,7 @@ namespace GeographicLib {
   Math::real GravityCircle::Gravity(real lon, real& gx, real& gy, real& gz)
     const {
     real clam, slam, M[Geocentric::dim2_];
-    CircularEngine::cossin(lon, clam, slam);
+    Math::sincosd(lon, slam, clam);
     real Wres = W(clam, slam, gx, gy, gz);
     Geocentric::Rotation(_sphi, _cphi, slam, clam, M);
     Geocentric::Unrotate(M, gx, gy, gz, gx, gy, gz);
@@ -29,7 +29,7 @@ namespace GeographicLib {
   Math::real GravityCircle::Disturbance(real lon, real& deltax, real& deltay,
                                         real& deltaz) const {
     real clam, slam, M[Geocentric::dim2_];
-    CircularEngine::cossin(lon, clam, slam);
+    Math::sincosd(lon, slam, clam);
     real Tres = InternalT(clam, slam, deltax, deltay, deltaz, true, true);
     Geocentric::Rotation(_sphi, _cphi, slam, clam, M);
     Geocentric::Unrotate(M, deltax, deltay, deltaz, deltax, deltay, deltaz);
@@ -40,7 +40,7 @@ namespace GeographicLib {
     if ((_caps & GEOID_HEIGHT) != GEOID_HEIGHT)
       return Math::NaN();
     real clam, slam, dummy;
-    CircularEngine::cossin(lon, clam, slam);
+    Math::sincosd(lon, slam, clam);
     real T = InternalT(clam, slam, dummy, dummy, dummy, false, false);
     real correction = _corrmult * _correction(clam, slam);
     return T/_gamma0 + correction;
@@ -54,7 +54,7 @@ namespace GeographicLib {
       return;
     }
     real clam, slam;
-    CircularEngine::cossin(lon, clam, slam);
+    Math::sincosd(lon, slam, clam);
     real
       deltax, deltay, deltaz,
       T = InternalT(clam, slam, deltax, deltay, deltaz, true, false);
diff --git a/src/GravityModel.cpp b/src/GravityModel.cpp
index 0523924..d552620 100644
--- a/src/GravityModel.cpp
+++ b/src/GravityModel.cpp
@@ -62,7 +62,9 @@ namespace GeographicLib {
         throw GeographicErr("ID mismatch: " + _id + " vs " + id);
       int N, M;
       SphericalEngine::coeff::readcoeffs(coeffstr, N, M, _Cx, _Sx);
-      if (!(M < 0 || _Cx[0] == 0))
+      if (!(N >= 0 && M >= 0))
+        throw GeographicErr("Degree and order must be at least 0");
+      if (_Cx[0] != 0)
         throw GeographicErr("A degree 0 term should be zero");
       _Cx[0] = 1;               // Include the 1/r term in the sum
       _gravitational = SphericalHarmonic(_Cx, _Sx, N, N, M, _amodel, _norm);
diff --git a/src/LambertConformalConic.cpp b/src/LambertConformalConic.cpp
index 98fbe53..ce44811 100644
--- a/src/LambertConformalConic.cpp
+++ b/src/LambertConformalConic.cpp
@@ -32,10 +32,8 @@ namespace GeographicLib {
       throw GeographicErr("Scale is not positive");
     if (!(abs(stdlat) <= 90))
       throw GeographicErr("Standard latitude not in [-90d, 90d]");
-    real
-      phi = stdlat * Math::degree(),
-      sphi = sin(phi),
-      cphi = abs(stdlat) != 90 ? cos(phi) : 0;
+    real sphi, cphi;
+    Math::sincosd(stdlat, sphi, cphi);
     Init(sphi, cphi, sphi, cphi, k0);
   }
 
@@ -61,11 +59,10 @@ namespace GeographicLib {
       throw GeographicErr("Standard latitude 1 not in [-90d, 90d]");
     if (!(abs(stdlat2) <= 90))
       throw GeographicErr("Standard latitude 2 not in [-90d, 90d]");
-    real
-      phi1 = stdlat1 * Math::degree(),
-      phi2 = stdlat2 * Math::degree();
-    Init(sin(phi1), abs(stdlat1) != 90 ? cos(phi1) : 0,
-         sin(phi2), abs(stdlat2) != 90 ? cos(phi2) : 0, k1);
+    real sphi1, cphi1, sphi2, cphi2;
+    Math::sincosd(stdlat1, sphi1, cphi1);
+    Math::sincosd(stdlat2, sphi2, cphi2);
+    Init(sphi1, cphi1, sphi2, cphi2, k1);
   }
 
   LambertConformalConic::LambertConformalConic(real a, real f,
@@ -334,7 +331,7 @@ namespace GeographicLib {
   void LambertConformalConic::Forward(real lon0, real lat, real lon,
                                       real& x, real& y, real& gamma, real& k)
     const {
-    lon = Math::AngDiff(Math::AngNormalize(lon0), Math::AngNormalize(lon));
+    lon = Math::AngDiff(lon0, lon);
     // From Snyder, we have
     //
     // theta = n * lambda
@@ -345,10 +342,11 @@ namespace GeographicLib {
     //
     // where nrho0 = n * rho0, drho = rho - rho0
     // and drho is evaluated with divided differences
+    real sphi, cphi;
+    Math::sincosd(Math::LatFix(lat) * _sign, sphi, cphi);
+    cphi = max(epsx_, cphi);
     real
       lam = lon * Math::degree(),
-      phi = _sign * lat * Math::degree(),
-      sphi = sin(phi), cphi = abs(lat) != 90 ? cos(phi) : epsx_,
       tphi = sphi/cphi, scbet = hyp(_fm * tphi),
       scphi = 1/cphi, shxi = sinh(Math::eatanhe(sphi, _es)),
       tchi = hyp(shxi) * tphi - shxi * scphi, scchi = hyp(tchi),
@@ -430,10 +428,9 @@ namespace GeographicLib {
     gamma = atan2(nx, y1);
     real
       tphi = Math::tauf(tchi, _es),
-      phi = _sign * atan(tphi),
       scbet = hyp(_fm * tphi), scchi = hyp(tchi),
       lam = _n ? gamma / _n : x / y1;
-    lat = phi / Math::degree();
+    lat = Math::atand(_sign * tphi);
     lon = lam / Math::degree();
     lon = Math::AngNormalize(lon + Math::AngNormalize(lon0));
     k = _k0 * (scbet/_scbet0) /
diff --git a/src/LocalCartesian.cpp b/src/LocalCartesian.cpp
index 6749172..a914463 100644
--- a/src/LocalCartesian.cpp
+++ b/src/LocalCartesian.cpp
@@ -2,7 +2,7 @@
  * \file LocalCartesian.cpp
  * \brief Implementation for GeographicLib::LocalCartesian class
  *
- * Copyright (c) Charles Karney (2008-2011) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2008-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -14,17 +14,13 @@ namespace GeographicLib {
   using namespace std;
 
   void LocalCartesian::Reset(real lat0, real lon0, real h0) {
-    _lat0 = lat0;
+    _lat0 = Math::LatFix(lat0);
     _lon0 = Math::AngNormalize(lon0);
     _h0 = h0;
     _earth.Forward(_lat0, _lon0, _h0, _x0, _y0, _z0);
-    real
-      phi = lat0 * Math::degree(),
-      sphi = sin(phi),
-      cphi = abs(_lat0) == 90 ? 0 : cos(phi),
-      lam = lon0 * Math::degree(),
-      slam = _lon0 == -180 ? 0 : sin(lam),
-      clam = abs(_lon0) == 90 ? 0 : cos(lam);
+    real sphi, cphi, slam, clam;
+    Math::sincosd(_lat0, sphi, cphi);
+    Math::sincosd(_lon0, slam, clam);
     Geocentric::Rotation(sphi, cphi, slam, clam, _r);
   }
 
diff --git a/src/MGRS.cpp b/src/MGRS.cpp
index d801e17..50c31bf 100644
--- a/src/MGRS.cpp
+++ b/src/MGRS.cpp
@@ -38,6 +38,9 @@ namespace GeographicLib {
 
   void MGRS::Forward(int zone, bool northp, real x, real y, real lat,
                      int prec, std::string& mgrs) {
+    // The smallest angle s.t., 90 - angeps() < 90 (approx 50e-12 arcsec)
+    // 7 = ceil(log_2(90))
+    static const real angeps = pow(real(0.5), Math::digits() - 7);
     if (zone == UTMUPS::INVALID ||
         Math::isnan(x) || Math::isnan(y) || Math::isnan(lat)) {
       mgrs = "INVALID";
@@ -64,16 +67,19 @@ namespace GeographicLib {
       // This isn't necessary...!  Keep y non-neg
       // if (!northp) y -= maxutmSrow_ * tile_;
     }
-    int
-      xh = int(floor(x)) / tile_,
-      yh = int(floor(y)) / tile_;
-    real
-      xf = x - tile_ * xh,
-      yf = y - tile_ * yh;
+    // The C++ standard mandates 64 bits for long long.  But
+    // check, to make sure.
+    GEOGRAPHICLIB_STATIC_ASSERT(numeric_limits<long long>::digits >= 44,
+                                "long long not wide enough to store 10e12");
+    long long
+      ix = (long long)(floor(x * mult_)),
+      iy = (long long)(floor(y * mult_)),
+      m = (long long)(mult_) * (long long)(tile_);
+    int xh = int(ix / m), yh = int(iy / m);
     if (utmp) {
       int
         // Correct fuzziness in latitude near equator
-        iband = abs(lat) > angeps() ? LatitudeBand(lat) : (northp ? 0 : -1),
+        iband = abs(lat) > angeps ? LatitudeBand(lat) : (northp ? 0 : -1),
         icol = xh - minutmcol_,
         irow = UTMRow(iband, icol, yh % utmrowperiod_);
       if (irow != yh - (northp ? minutmNrow_ : maxutmSrow_))
@@ -92,28 +98,12 @@ namespace GeographicLib {
       mgrs1[z++] = upsrows_[northp][yh - (northp ? minupsNind_ : minupsSind_)];
     }
     if (prec > 0) {
-      real mult = pow(real(base_), max(tilelevel_ - prec, 0));
-      int
-        ix = int(floor(xf / mult)),
-        iy = int(floor(yf / mult));
-      for (int c = min(prec, int(tilelevel_)); c--;) {
-        mgrs1[z + c] = digits_[ ix % base_ ];
-        ix /= base_;
-        mgrs1[z + c + prec] = digits_[ iy % base_ ];
-        iy /= base_;
-      }
-      if (prec > tilelevel_) {
-        xf -= floor(xf / mult);
-        yf -= floor(yf / mult);
-        mult = pow(real(base_), prec - tilelevel_);
-        ix = int(floor(xf * mult));
-        iy = int(floor(yf * mult));
-        for (int c = prec - tilelevel_; c--;) {
-          mgrs1[z + c + tilelevel_] = digits_[ ix % base_ ];
-          ix /= base_;
-          mgrs1[z + c + tilelevel_ + prec] = digits_[ iy % base_ ];
-          iy /= base_;
-        }
+      ix -= m * xh; iy -= m * yh;
+      long long d = (long long)(pow(real(base_), maxprec_ - prec));
+      ix /= d; iy /= d;
+      for (int c = prec; c--;) {
+        mgrs1[z + c       ] = digits_[ix % base_]; ix /= base_;
+        mgrs1[z + c + prec] = digits_[iy % base_]; iy /= base_;
       }
     }
     mgrs.resize(mlen);
@@ -160,7 +150,7 @@ namespace GeographicLib {
                      int& prec, bool centerp) {
     int
       p = 0,
-      len = int(mgrs.size());
+      len = int(mgrs.length());
     if (len >= 3 &&
         toupper(mgrs[0]) == 'I' &&
         toupper(mgrs[1]) == 'N' &&
@@ -182,7 +172,7 @@ namespace GeographicLib {
     if (p > 0 && !(zone1 >= UTMUPS::MINUTMZONE && zone1 <= UTMUPS::MAXUTMZONE))
       throw GeographicErr("Zone " + Utility::str(zone1) + " not in [1,60]");
     if (p > 2)
-      throw GeographicErr("More than 2 digits_ at start of MGRS "
+      throw GeographicErr("More than 2 digits at start of MGRS "
                           + mgrs.substr(0, p));
     if (len - p < 1)
       throw GeographicErr("MGRS string too short " + mgrs);
@@ -249,38 +239,36 @@ namespace GeographicLib {
     }
     int prec1 = (len - p)/2;
     real
-      unit = tile_,
-      x1 = unit * icol,
-      y1 = unit * irow;
+      unit = 1,
+      x1 = icol,
+      y1 = irow;
     for (int i = 0; i < prec1; ++i) {
-      unit /= base_;
+      unit *= base_;
       int
         ix = Utility::lookup(digits_, mgrs[p + i]),
         iy = Utility::lookup(digits_, mgrs[p + i + prec1]);
       if (ix < 0 || iy < 0)
         throw GeographicErr("Encountered a non-digit in " + mgrs.substr(p));
-      x1 += unit * ix;
-      y1 += unit * iy;
+      x1 = base_ * x1 + ix;
+      y1 = base_ * y1 + iy;
     }
     if ((len - p) % 2) {
       if (Utility::lookup(digits_, mgrs[len - 1]) < 0)
         throw GeographicErr("Encountered a non-digit in " + mgrs.substr(p));
       else
-        throw GeographicErr("Not an even number of digits_ in "
+        throw GeographicErr("Not an even number of digits in "
                             + mgrs.substr(p));
     }
     if (prec1 > maxprec_)
       throw GeographicErr("More than " + Utility::str(2*maxprec_)
-                          + " digits_ in "
-                          + mgrs.substr(p));
+                          + " digits in " + mgrs.substr(p));
     if (centerp) {
-      x1 += unit/2;
-      y1 += unit/2;
+      unit *= 2; x1 = 2 * x1 + 1; y1 = 2 * y1 + 1;
     }
     zone = zone1;
     northp = northp1;
-    x = x1;
-    y = y1;
+    x = (tile_ * x1) / unit;
+    y = (tile_ * y1) / unit;
     prec = prec1;
   }
 
@@ -288,15 +276,20 @@ namespace GeographicLib {
     // Limits are all multiples of 100km and are all closed on the lower end
     // and open on the upper end -- and this is reflected in the error
     // messages.  However if a coordinate lies on the excluded upper end (e.g.,
-    // after rounding), it is shifted down by eps().  This also folds UTM
+    // after rounding), it is shifted down by eps.  This also folds UTM
     // northings to the correct N/S hemisphere.
+
+    // The smallest length s.t., 1.0e7 - eps() < 1.0e7 (approx 1.9 nm)
+    // 25 = ceil(log_2(2e7)) -- use half circumference here because
+    // northing 195e5 is a legal in the "southern" hemisphere.
+    static const real eps = pow(real(0.5), Math::digits() - 25);
     int
       ix = int(floor(x / tile_)),
       iy = int(floor(y / tile_)),
       ind = (utmp ? 2 : 0) + (northp ? 1 : 0);
     if (! (ix >= mineasting_[ind] && ix < maxeasting_[ind]) ) {
       if (ix == maxeasting_[ind] && x == maxeasting_[ind] * tile_)
-        x -= eps();
+        x -= eps;
       else
         throw GeographicErr("Easting " + Utility::str(int(floor(x/1000)))
                             + "km not in MGRS/"
@@ -309,7 +302,7 @@ namespace GeographicLib {
     }
     if (! (iy >= minnorthing_[ind] && iy < maxnorthing_[ind]) ) {
       if (iy == maxnorthing_[ind] && y == maxnorthing_[ind] * tile_)
-        y -= eps();
+        y -= eps;
       else
         throw GeographicErr("Northing " + Utility::str(int(floor(y/1000)))
                             + "km not in MGRS/"
@@ -329,7 +322,7 @@ namespace GeographicLib {
       } else if (!northp && iy >= maxutmSrow_) {
         if (y == maxutmSrow_ * tile_)
           // If on equator retain S hemisphere
-          y -= eps();
+          y -= eps;
         else {
           northp = true;
           y -= utmNshift_;
diff --git a/src/MagneticCircle.cpp b/src/MagneticCircle.cpp
index 714204d..afb9940 100644
--- a/src/MagneticCircle.cpp
+++ b/src/MagneticCircle.cpp
@@ -20,7 +20,7 @@ namespace GeographicLib {
                              real& Bx, real& By, real& Bz,
                              real& Bxt, real& Byt, real& Bzt) const {
     real clam, slam;
-    CircularEngine::cossin(lon, clam, slam);
+    Math::sincosd(lon, slam, clam);
     real M[Geocentric::dim2_];
     Geocentric::Rotation(_sphi, _cphi, slam, clam, M);
     real BX0, BY0, BZ0, BX1, BY1, BZ1; // Components in geocentric basis
diff --git a/src/Makefile.am b/src/Makefile.am
index 911acc8..e85e08f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -17,6 +17,7 @@ libGeographic_la_SOURCES = Accumulator.cpp \
 		DMS.cpp \
 		Ellipsoid.cpp \
 		EllipticFunction.cpp \
+		GARS.cpp \
 		GeoCoords.cpp \
 		Geocentric.cpp \
 		Geodesic.cpp \
@@ -26,6 +27,7 @@ libGeographic_la_SOURCES = Accumulator.cpp \
 		GeodesicLineExact.cpp \
 		Geohash.cpp \
 		Geoid.cpp \
+		Georef.cpp \
 		Gnomonic.cpp \
 		GravityCircle.cpp \
 		GravityModel.cpp \
@@ -54,6 +56,7 @@ libGeographic_la_SOURCES = Accumulator.cpp \
 		../include/GeographicLib/DMS.hpp \
 		../include/GeographicLib/Ellipsoid.hpp \
 		../include/GeographicLib/EllipticFunction.hpp \
+		../include/GeographicLib/GARS.hpp \
 		../include/GeographicLib/GeoCoords.hpp \
 		../include/GeographicLib/Geocentric.hpp \
 		../include/GeographicLib/Geodesic.hpp \
@@ -62,6 +65,7 @@ libGeographic_la_SOURCES = Accumulator.cpp \
 		../include/GeographicLib/GeodesicLineExact.hpp \
 		../include/GeographicLib/Geohash.hpp \
 		../include/GeographicLib/Geoid.hpp \
+		../include/GeographicLib/Georef.hpp \
 		../include/GeographicLib/Gnomonic.hpp \
 		../include/GeographicLib/GravityCircle.hpp \
 		../include/GeographicLib/GravityModel.hpp \
diff --git a/src/Makefile.in b/src/Makefile.in
index c17b475..7caa38b 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -130,10 +130,10 @@ LTLIBRARIES = $(lib_LTLIBRARIES)
 libGeographic_la_LIBADD =
 am_libGeographic_la_OBJECTS = Accumulator.lo AlbersEqualArea.lo \
 	AzimuthalEquidistant.lo CassiniSoldner.lo CircularEngine.lo \
-	DMS.lo Ellipsoid.lo EllipticFunction.lo GeoCoords.lo \
+	DMS.lo Ellipsoid.lo EllipticFunction.lo GARS.lo GeoCoords.lo \
 	Geocentric.lo Geodesic.lo GeodesicExact.lo GeodesicExactC4.lo \
 	GeodesicLine.lo GeodesicLineExact.lo Geohash.lo Geoid.lo \
-	Gnomonic.lo GravityCircle.lo GravityModel.lo \
+	Georef.lo Gnomonic.lo GravityCircle.lo GravityModel.lo \
 	LambertConformalConic.lo LocalCartesian.lo MGRS.lo \
 	MagneticCircle.lo MagneticModel.lo Math.lo NormalGravity.lo \
 	OSGB.lo PolarStereographic.lo PolygonArea.lo Rhumb.lo \
@@ -374,6 +374,7 @@ libGeographic_la_SOURCES = Accumulator.cpp \
 		DMS.cpp \
 		Ellipsoid.cpp \
 		EllipticFunction.cpp \
+		GARS.cpp \
 		GeoCoords.cpp \
 		Geocentric.cpp \
 		Geodesic.cpp \
@@ -383,6 +384,7 @@ libGeographic_la_SOURCES = Accumulator.cpp \
 		GeodesicLineExact.cpp \
 		Geohash.cpp \
 		Geoid.cpp \
+		Georef.cpp \
 		Gnomonic.cpp \
 		GravityCircle.cpp \
 		GravityModel.cpp \
@@ -411,6 +413,7 @@ libGeographic_la_SOURCES = Accumulator.cpp \
 		../include/GeographicLib/DMS.hpp \
 		../include/GeographicLib/Ellipsoid.hpp \
 		../include/GeographicLib/EllipticFunction.hpp \
+		../include/GeographicLib/GARS.hpp \
 		../include/GeographicLib/GeoCoords.hpp \
 		../include/GeographicLib/Geocentric.hpp \
 		../include/GeographicLib/Geodesic.hpp \
@@ -419,6 +422,7 @@ libGeographic_la_SOURCES = Accumulator.cpp \
 		../include/GeographicLib/GeodesicLineExact.hpp \
 		../include/GeographicLib/Geohash.hpp \
 		../include/GeographicLib/Geoid.hpp \
+		../include/GeographicLib/Georef.hpp \
 		../include/GeographicLib/Gnomonic.hpp \
 		../include/GeographicLib/GravityCircle.hpp \
 		../include/GeographicLib/GravityModel.hpp \
@@ -532,6 +536,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/DMS.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/Ellipsoid.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/EllipticFunction.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/GARS.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/GeoCoords.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/Geocentric.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/Geodesic.Plo at am__quote@
@@ -541,6 +546,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/GeodesicLineExact.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/Geohash.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/Geoid.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/Georef.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/Gnomonic.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/GravityCircle.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/GravityModel.Plo at am__quote@
diff --git a/src/Makefile.mk b/src/Makefile.mk
index c970889..dbc3668 100644
--- a/src/Makefile.mk
+++ b/src/Makefile.mk
@@ -16,6 +16,7 @@ MODULES = Accumulator \
 	DMS \
 	Ellipsoid \
 	EllipticFunction \
+	GARS \
 	GeoCoords \
 	Geocentric \
 	Geodesic \
@@ -24,6 +25,7 @@ MODULES = Accumulator \
 	GeodesicLineExact \
 	Geohash \
 	Geoid \
+	Georef \
 	Gnomonic \
 	GravityCircle \
 	GravityModel \
@@ -88,6 +90,7 @@ DMS.o: Config.h Constants.hpp DMS.hpp Math.hpp Utility.hpp
 Ellipsoid.o: Config.h Constants.hpp Ellipsoid.hpp AlbersEqualArea.hpp \
 	EllipticFunction.hpp Math.hpp TransverseMercator.hpp
 EllipticFunction.o: Config.h Constants.hpp EllipticFunction.hpp Math.hpp
+GARS.o: Config.h Constants.hpp GARS.hpp Utility.hpp
 GeoCoords.o: Config.h Constants.hpp DMS.hpp GeoCoords.hpp MGRS.hpp Math.hpp \
 	UTMUPS.hpp Utility.hpp
 Geocentric.o: Config.h Constants.hpp Geocentric.hpp Math.hpp
@@ -100,6 +103,7 @@ GeodesicLineExact.o: Config.h Constants.hpp GeodesicExact.hpp \
 	GeodesicLineExact.hpp Math.hpp
 Geohash.o: Config.h Constants.hpp Geohash.hpp Utility.hpp
 Geoid.o: Config.h Constants.hpp Geoid.hpp Math.hpp
+Georef.o: Config.h Constants.hpp Georef.hpp Utility.hpp
 Gnomonic.o: Config.h Constants.hpp Geodesic.hpp GeodesicLine.hpp Gnomonic.hpp \
 	Math.hpp
 GravityCircle.o: CircularEngine.hpp Config.h Constants.hpp Geocentric.hpp \
diff --git a/src/NormalGravity.cpp b/src/NormalGravity.cpp
index b673dcd..3c96c16 100644
--- a/src/NormalGravity.cpp
+++ b/src/NormalGravity.cpp
@@ -2,7 +2,7 @@
  * \file NormalGravity.cpp
  * \brief Implementation for GeographicLib::NormalGravity class
  *
- * Copyright (c) Charles Karney (2011-2014) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2011-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -30,7 +30,7 @@ namespace GeographicLib {
       if (!(Math::isfinite(_a) && _a > 0))
         throw GeographicErr("Major radius is not positive");
       if (!(Math::isfinite(_GM) && _GM > 0))
-        throw GeographicErr("Gravitational constants is not positive");
+        throw GeographicErr("Gravitational constant is not positive");
       if (!(_omega == 0 && _f == 0 && _J2 == 0)) {
         bool flatp = _f > 0 && Math::isfinite(_f);
         if (_J2 > 0 && Math::isfinite(_J2) && flatp)
@@ -40,22 +40,23 @@ namespace GeographicLib {
         if (!(Math::isfinite(_omega) && _omega != 0))
           throw GeographicErr("Angular velocity is not non-zero");
         if (flatp)
-          _J2 = FlatteningToJ2(a, GM, omega, f);
+          _J2 = FlatteningToJ2(_a, _GM, _omega, _f);
         else
-          _f = J2ToFlattening(a, GM, omega, J2);
+          _f = J2ToFlattening(_a, _GM, _omega, _J2);
       } // else we have a sphere: omega = f = J2 = 0
       _e2 = _f * (2 - _f);
       _ep2 = _e2 / (1 - _e2);
       _q0 = qf(_ep2);
       _earth = Geocentric(_a, _f);
       _b = _a * (1 - _f);
-      _E = a * sqrt(_e2);                               // H+M, Eq 2-54
-      _U0 = _GM / _E * atan(sqrt(_ep2)) + _aomega2 / 3; // H+M, Eq 2-61
+      _E = _a * sqrt(_e2);      // H+M, Eq 2-54
+      // H+M, Eq 2-61
+      _U0 = _GM / (_E ? _E / atan(sqrt(_ep2)) : _b) + _aomega2 / 3;
       // The approximate ratio of the centrifugal acceleration (at the equator)
       // to gravity.
-      _m = _aomega2 * _b / _GM;                         // H+M, Eq 2-70
+      _m = _aomega2 * _b / _GM; // H+M, Eq 2-70
       real
-        Q = _m * sqrt(_ep2) * qpf(_ep2) / (3 * _q0),
+        Q = _m * (_q0 ? sqrt(_ep2) * qpf(_ep2) / (3 * _q0) : 1),
         G = (1 - _m - Q / 2);
       _gammae = _GM / (_a * _b) * G;       // H+M, Eq 2-73
       _gammap = _GM / (_a * _a) * (1 + Q); // H+M, Eq 2-74
@@ -146,11 +147,9 @@ namespace GeographicLib {
   }
 
   Math::real NormalGravity::SurfaceGravity(real lat) const {
-    real
-      phi = lat * Math::degree(),
-      sphi2 = abs(lat) == 90 ? 1 : Math::sq(sin(phi));
+    real sphi = Math::sind(Math::LatFix(lat));
     // H+M, Eq 2-78
-    return _gammae * (1 + _k * sphi2) / sqrt(1 - _e2 * sphi2);
+    return _gammae * (1 + _k * Math::sq(sphi)) / sqrt(1 - _e2 * Math::sq(sphi));
   }
 
   Math::real NormalGravity::V0(real X, real Y, real Z,
@@ -179,14 +178,14 @@ namespace GeographicLib {
       invw = uE / Math::hypot(u, _E * sbet), // H+M, Eq 2-63
       ep = _E/u,
       ep2 = Math::sq(ep),
-      q = qf(ep2) / _q0,
+      q = _q0 ? qf(ep2) / _q0 : pow(_a / u, 3),
       qp = qpf(ep2) / _q0,
       // H+M, Eqs 2-62 + 6-9, but omitting last (rotational) term .
-      Vres = (_GM / _E * atan(_E / u)
+      Vres = (_GM / (_E ? _E / atan(_E / u) : u)
               + _aomega2 * q * (Math::sq(sbet) - 1/real(3)) / 2),
       // H+M, Eq 6-10
       gamu = - invw * (_GM
-                       + (_aomega2 * _E * qp
+                       + (_aomega2 * (_q0 ? _E * qp : 3 * q * u)
                           * (Math::sq(sbet) - 1/real(3)) / 2)) / Math::sq(uE),
       gamb = _aomega2 * q * sbet * cbet * invw / uE,
       t = u * invw / uE;
diff --git a/src/PolarStereographic.cpp b/src/PolarStereographic.cpp
index 482251f..0f29322 100644
--- a/src/PolarStereographic.cpp
+++ b/src/PolarStereographic.cpp
@@ -61,6 +61,7 @@ namespace GeographicLib {
   void PolarStereographic::Forward(bool northp, real lat, real lon,
                                    real& x, real& y, real& gamma, real& k)
     const {
+    lat = Math::LatFix(lat);
     lat *= northp ? 1 : -1;
     real
       tau = Math::tand(lat),
@@ -71,12 +72,10 @@ namespace GeographicLib {
     rho *= 2 * _k0 * _a / _c;
     k = lat != 90 ? (rho / _a) * secphi * sqrt(_e2m + _e2 / Math::sq(secphi)) :
       _k0;
-    lon = Math::AngNormalize(lon);
-    real
-      lam = lon * Math::degree();
-    x = rho * (lon == -180 ? 0 : sin(lam));
-    y = (northp ? -rho : rho) * (abs(lon) == 90 ? 0 : cos(lam));
-    gamma = northp ? lon : -lon;
+    Math::sincosd(lon, x, y);
+    x *= rho;
+    y *= (northp ? -rho : rho);
+    gamma = Math::AngNormalize(northp ? lon : -lon);
   }
 
   void PolarStereographic::Reverse(bool northp, real x, real y,
@@ -84,15 +83,15 @@ namespace GeographicLib {
     const {
     real
       rho = Math::hypot(x, y),
-      t = rho / (2 * _k0 * _a / _c),
+      t = rho ? rho / (2 * _k0 * _a / _c) :
+      Math::sq(numeric_limits<real>::epsilon()),
       taup = (1 / t - t) / 2,
       tau = Math::tauf(taup, _es),
-      phi = atan(tau),
       secphi = Math::hypot(real(1), tau);
     k = rho ? (rho / _a) * secphi * sqrt(_e2m + _e2 / Math::sq(secphi)) : _k0;
-    lat = (northp ? 1 : -1) * (rho ? phi / Math::degree() : 90);
-    lon = 0 - atan2( -x, northp ? -y : y ) / Math::degree();
-    gamma = northp ? lon : -lon;
+    lat = (northp ? 1 : -1) * Math::atand(tau);
+    lon = Math::atan2d(x, northp ? -y : y );
+    gamma = Math::AngNormalize(northp ? lon : -lon);
   }
 
   void PolarStereographic::SetScale(real lat, real k) {
diff --git a/src/PolygonArea.cpp b/src/PolygonArea.cpp
index df0d7d3..66cd77e 100644
--- a/src/PolygonArea.cpp
+++ b/src/PolygonArea.cpp
@@ -2,7 +2,7 @@
  * \file PolygonArea.cpp
  * \brief Implementation for GeographicLib::PolygonAreaT class
  *
- * Copyright (c) Charles Karney (2010-2014) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2010-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -15,6 +15,7 @@ namespace GeographicLib {
 
   template <class GeodType>
   void PolygonAreaT<GeodType>::AddPoint(real lat, real lon) {
+    lat = Math::LatFix(lat);
     lon = Math::AngNormalize(lon);
     if (_num == 0) {
       _lat0 = _lat1 = lat;
@@ -42,7 +43,7 @@ namespace GeographicLib {
       if (!_polyline) {
         _areasum += S12;
         _crossings += transitdirect(_lon1, lon);
-        lon = Math::AngNormalize2(lon);
+        lon = Math::AngNormalize(lon);
       }
       _lat1 = lat; _lon1 = lon;
       ++_num;
@@ -167,7 +168,7 @@ namespace GeographicLib {
                        lat, lon, t, t, t, t, t, S12);
       tempsum += S12;
       crossings += transitdirect(_lon1, lon);
-      lon = Math::AngNormalize2(lon);
+      lon = Math::AngNormalize(lon);
       _earth.GenInverse(lat, lon, _lat0, _lon0, _mask, s12, t, t, t, t, t, S12);
       perimeter += s12;
       tempsum += S12;
diff --git a/src/Rhumb.cpp b/src/Rhumb.cpp
index 03f6069..711e7fd 100644
--- a/src/Rhumb.cpp
+++ b/src/Rhumb.cpp
@@ -148,7 +148,7 @@ namespace GeographicLib {
                          unsigned outmask,
                          real& s12, real& azi12, real& S12) const {
     real
-      lon12 = Math::AngDiff(Math::AngNormalize(lon1), Math::AngNormalize(lon2)),
+      lon12 = Math::AngDiff(lon1, lon2),
       psi1 = _ell.IsometricLatitude(lat1),
       psi2 = _ell.IsometricLatitude(lat2),
       psi12 = psi2 - psi1,
@@ -331,7 +331,7 @@ namespace GeographicLib {
                        bool exact)
     : _rh(rh)
     , _exact(exact)
-    , _lat1(lat1)
+    , _lat1(Math::LatFix(lat1))
     , _lon1(lon1)
     , _azi12(Math::AngNormalize(azi12))
   {
@@ -365,10 +365,10 @@ namespace GeographicLib {
         S12 = _rh._c2 * lon2x *
           _rh.MeanSinXi(_psi1 * Math::degree(), psi2 * Math::degree());
       lon2x = outmask & LONG_UNROLL ? _lon1 + lon2x :
-        Math::AngNormalize2(Math::AngNormalize(_lon1) + lon2x);
+        Math::AngNormalize(Math::AngNormalize(_lon1) + lon2x);
     } else {
       // Reduce to the interval [-180, 180)
-      mu2 = Math::AngNormalize2(mu2);
+      mu2 = Math::AngNormalize(mu2);
       // Deal with points on the anti-meridian
       if (abs(mu2) > 90) mu2 = Math::AngNormalize(180 - mu2);
       lat2x = _rh._ell.InverseRectifyingLatitude(mu2);
diff --git a/src/TransverseMercator.cpp b/src/TransverseMercator.cpp
index 6f477c4..b8adb8b 100644
--- a/src/TransverseMercator.cpp
+++ b/src/TransverseMercator.cpp
@@ -353,7 +353,8 @@ namespace GeographicLib {
   void TransverseMercator::Forward(real lon0, real lat, real lon,
                                    real& x, real& y, real& gamma, real& k)
     const {
-    lon = Math::AngDiff(Math::AngNormalize(lon0), Math::AngNormalize(lon));
+    lat = Math::LatFix(lat);
+    lon = Math::AngDiff(lon0, lon);
     // Explicitly enforce the parity
     int
       latsign = lat < 0 ? -1 : 1,
@@ -366,9 +367,9 @@ namespace GeographicLib {
         latsign = -1;
       lon = 180 - lon;
     }
-    real
-      phi = lat * Math::degree(),
-      lam = lon * Math::degree();
+    real sphi, cphi, slam, clam;
+    Math::sincosd(lat, sphi, cphi);
+    Math::sincosd(lon, slam, clam);
     // phi = latitude
     // phi' = conformal latitude
     // psi = isometric latitude
@@ -389,18 +390,17 @@ namespace GeographicLib {
     real etap, xip;
     if (lat != 90) {
       real
-        c = max(real(0), cos(lam)), // cos(pi/2) might be negative
-        tau = tan(phi),
+        tau = sphi / cphi,
         taup = Math::taupf(tau, _es);
-      xip = atan2(taup, c);
+      xip = atan2(taup, clam);
       // Used to be
       //   etap = Math::atanh(sin(lam) / cosh(psi));
-      etap = Math::asinh(sin(lam) / Math::hypot(taup, c));
+      etap = Math::asinh(slam / Math::hypot(taup, clam));
       // convergence and scale for Gauss-Schreiber TM (xip, etap) -- gamma0 =
       // atan(tan(xip) * tanh(etap)) = atan(tan(lam) * sin(phi'));
       // sin(phi') = tau'/sqrt(1 + tau'^2)
-      gamma = atan(Math::tand(lon) *
-                   taup / Math::hypot(real(1), taup)); // Krueger p 22 (44)
+      // Krueger p 22 (44)
+      gamma = Math::atan2d(slam * taup, clam * Math::hypot(real(1), taup));
       // k0 = sqrt(1 - _e2 * sin(phi)^2) * (cos(phi') / cos(phi)) * cosh(etap)
       // Note 1/cos(phi) = cosh(psip);
       // and cos(phi') * cosh(etap) = 1/hypot(sinh(psi), cos(lam))
@@ -408,12 +408,12 @@ namespace GeographicLib {
       // This form has cancelling errors.  This property is lost if cosh(psip)
       // is replaced by 1/cos(phi), even though it's using "primary" data (phi
       // instead of psip).
-      k = sqrt(_e2m + _e2 * Math::sq(cos(phi))) * Math::hypot(real(1), tau)
-        / Math::hypot(taup, c);
+      k = sqrt(_e2m + _e2 * Math::sq(cphi)) * Math::hypot(real(1), tau)
+        / Math::hypot(taup, clam);
     } else {
       xip = Math::pi()/2;
       etap = 0;
-      gamma = lam;
+      gamma = lon;
       k = _c;
     }
     // {xi',eta'} is {northing,easting} for Gauss-Schreiber transverse Mercator
@@ -501,14 +501,14 @@ namespace GeographicLib {
       eta = etap + ai * xi0 + ar * eta0;
     // Fold in change in convergence and scale for Gauss-Schreiber TM to
     // Gauss-Krueger TM.
-    gamma -= atan2(yi1, yr1);
+    gamma -= Math::atan2d(yi1, yr1);
     k *= _b1 * Math::hypot(yr1, yi1);
-    gamma /= Math::degree();
     y = _a1 * _k0 * (backside ? Math::pi() - xi : xi) * latsign;
     x = _a1 * _k0 * eta * lonsign;
     if (backside)
       gamma = 180 - gamma;
     gamma *= latsign * lonsign;
+    gamma = Math::AngNormalize(gamma);
     k *= _k0;
   }
 
@@ -561,44 +561,42 @@ namespace GeographicLib {
       xip  = xi  + ar * xip0 - ai * etap0,
       etap = eta + ai * xip0 + ar * etap0;
     // Convergence and scale for Gauss-Schreiber TM to Gauss-Krueger TM.
-    gamma = atan2(yi1, yr1);
+    gamma = Math::atan2d(yi1, yr1);
     k = _b1 / Math::hypot(yr1, yi1);
     // JHS 154 has
     //
     //   phi' = asin(sin(xi') / cosh(eta')) (Krueger p 17 (25))
     //   lam = asin(tanh(eta') / cos(phi')
     //   psi = asinh(tan(phi'))
-    real lam, phi;
     real
       s = sinh(etap),
       c = max(real(0), cos(xip)), // cos(pi/2) might be negative
       r = Math::hypot(s, c);
     if (r != 0) {
-      lam = atan2(s, c);        // Krueger p 17 (25)
+      lon = Math::atan2d(s, c); // Krueger p 17 (25)
       // Use Newton's method to solve for tau
       real
         sxip = sin(xip),
         tau = Math::tauf(sxip/r, _es);
-      gamma += atan2(sxip * tanh(etap), c); // Krueger p 19 (31)
-      phi = atan(tau);
+      gamma += Math::atan2d(sxip * tanh(etap), c); // Krueger p 19 (31)
+      lat = Math::atand(tau);
       // Note cos(phi') * cosh(eta') = r
-      k *= sqrt(_e2m + _e2 * Math::sq(cos(phi))) *
+      k *= sqrt(_e2m + _e2 / (1 + Math::sq(tau))) *
         Math::hypot(real(1), tau) * r;
     } else {
-      phi = Math::pi()/2;
-      lam = 0;
+      lat = 90;
+      lon = 0;
       k *= _c;
     }
-    lat = phi / Math::degree() * xisign;
-    lon = lam / Math::degree();
+    lat *= xisign;
     if (backside)
       lon = 180 - lon;
     lon *= etasign;
-    lon = Math::AngNormalize(lon + Math::AngNormalize(lon0));
-    gamma /= Math::degree();
+    lon = Math::AngNormalize(lon + lon0);
     if (backside)
       gamma = 180 - gamma;
     gamma *= xisign * etasign;
+    gamma = Math::AngNormalize(gamma);
     k *= _k0;
   }
 
diff --git a/src/TransverseMercatorExact.cpp b/src/TransverseMercatorExact.cpp
index d5c0765..5092e8b 100644
--- a/src/TransverseMercatorExact.cpp
+++ b/src/TransverseMercatorExact.cpp
@@ -90,12 +90,15 @@ namespace GeographicLib {
     // atanh(snu * dnv) = asinh(snu * dnv / sqrt(cnu^2 + _mv * snu^2 * snv^2))
     // atanh(_e * snu / dnv) =
     //         asinh(_e * snu / sqrt(_mu * cnu^2 + _mv * cnv^2))
+    // Overflow value s.t. atan(overflow) = pi/2
+    static const real
+      overflow = 1 / Math::sq(std::numeric_limits<real>::epsilon());
     real
       d1 = sqrt(Math::sq(cnu) + _mv * Math::sq(snu * snv)),
       d2 = sqrt(_mu * Math::sq(cnu) + _mv * Math::sq(cnv)),
-      t1 = (d1 ? snu * dnv / d1 : (snu < 0 ? -overflow() : overflow())),
+      t1 = (d1 ? snu * dnv / d1 : (snu < 0 ? -overflow : overflow)),
       t2 = (d2 ? sinh( _e * Math::asinh(_e * snu / d2) ) :
-            (snu < 0 ? -overflow() : overflow()));
+            (snu < 0 ? -overflow : overflow));
     // psi = asinh(t1) - asinh(t2)
     // taup = sinh(psi)
     taup = t1 * Math::hypot(real(1), t2) - t2 * Math::hypot(real(1), t1);
@@ -346,7 +349,8 @@ namespace GeographicLib {
   void TransverseMercatorExact::Forward(real lon0, real lat, real lon,
                                         real& x, real& y, real& gamma, real& k)
     const {
-    lon = Math::AngDiff(Math::AngNormalize(lon0), Math::AngNormalize(lon));
+    lat = Math::LatFix(lat);
+    lon = Math::AngDiff(lon0, lon);
     // Explicitly enforce the parity
     int
       latsign = (!_extendp && lat < 0) ? -1 : 1,
diff --git a/src/UTMUPS.cpp b/src/UTMUPS.cpp
index 494ea02..1d5d4db 100644
--- a/src/UTMUPS.cpp
+++ b/src/UTMUPS.cpp
@@ -2,7 +2,7 @@
  * \file UTMUPS.cpp
  * \brief Implementation for GeographicLib::UTMUPS class
  *
- * Copyright (c) Charles Karney (2008-2014) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2008-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -47,8 +47,7 @@ namespace GeographicLib {
     if (Math::isnan(lat) || Math::isnan(lon)) // Check if lat or lon is a NaN
       return INVALID;
     if (setzone == UTM || (lat >= -80 && lat < 84)) {
-      // Assume lon is in [-540, 540).
-      int ilon = int(floor(lon));
+      int ilon = int(floor(fmod(lon, real(360))));
       if (ilon >= 180)
         ilon -= 360;
       else if (ilon < -180)
@@ -68,7 +67,9 @@ namespace GeographicLib {
                        int& zone, bool& northp, real& x, real& y,
                        real& gamma, real& k,
                        int setzone, bool mgrslimits) {
-    CheckLatLon(lat, lon);
+    if (abs(lat) > 90)
+      throw GeographicErr("Latitude " + Utility::str(lat)
+                          + "d not in [-90d, 90d]");
     bool northp1 = lat >= 0;
     int zone1 = StandardZone(lat, lon, setzone);
     if (zone1 == INVALID) {
@@ -137,15 +138,6 @@ namespace GeographicLib {
       PolarStereographic::UPS().Reverse(northp, x, y, lat, lon, gamma, k);
   }
 
-  void UTMUPS::CheckLatLon(real lat, real lon) {
-    if (abs(lat) > 90)
-      throw GeographicErr("Latitude " + Utility::str(lat)
-                          + "d not in [-90d, 90d]");
-    if (lon < -540 || lon >= 540)
-      throw GeographicErr("Longitude " + Utility::str(lon)
-                          + "d not in [-540d, 540d)");
-    }
-
   bool UTMUPS::CheckCoords(bool utmp, bool northp, real x, real y,
                            bool mgrslimits, bool throwp) {
     // Limits are all multiples of 100km and are all closed on the both ends.
diff --git a/tools/CartConvert.cpp b/tools/CartConvert.cpp
index 0356ca2..e12c325 100644
--- a/tools/CartConvert.cpp
+++ b/tools/CartConvert.cpp
@@ -2,7 +2,7 @@
  * \file CartConvert.cpp
  * \brief Command line utility for geodetic to cartesian coordinate conversions
  *
- * Copyright (c) Charles Karney (2009-2012) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2009-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  *
@@ -32,10 +32,11 @@ int main(int argc, char* argv[]) {
     using namespace GeographicLib;
     typedef Math::real real;
     Utility::set_digits();
-    bool localcartesian = false, reverse = false;
+    bool localcartesian = false, reverse = false, longfirst = false;
     real
       a = Constants::WGS84_a(),
       f = Constants::WGS84_f();
+    int prec = 6;
     real lat0 = 0, lon0 = 0, h0 = 0;
     std::string istring, ifile, ofile, cdelim;
     char lsep = ';';
@@ -49,7 +50,7 @@ int main(int argc, char* argv[]) {
         if (m + 3 >= argc) return usage(1, true);
         try {
           DMS::DecodeLatLon(std::string(argv[m + 1]), std::string(argv[m + 2]),
-                            lat0, lon0);
+                            lat0, lon0, longfirst);
           h0 = Utility::num<real>(std::string(argv[m + 3]));
         }
         catch (const std::exception& e) {
@@ -68,7 +69,18 @@ int main(int argc, char* argv[]) {
           return 1;
         }
         m += 2;
-      } else if (arg == "--input-string") {
+      } else if (arg == "-w")
+        longfirst = true;
+      else if (arg == "-p") {
+        if (++m == argc) return usage(1, true);
+        try {
+          prec = Utility::num<int>(std::string(argv[m]));
+        }
+        catch (const std::exception&) {
+          std::cerr << "Precision " << argv[m] << " is not a number\n";
+          return 1;
+        }
+      }  else if (arg == "--input-string") {
         if (++m == argc) return usage(1, true);
         istring = argv[m];
       } else if (arg == "--input-file") {
@@ -135,11 +147,15 @@ int main(int argc, char* argv[]) {
     const Geocentric ec(a, f);
     const LocalCartesian lc(lat0, lon0, h0, ec);
 
-    std::string s;
+    // Max precision = 10: 0.1 nm in distance, 10^-15 deg (= 0.11 nm),
+    // 10^-11 sec (= 0.3 nm).
+    prec = std::min(10 + Math::extra_digits(), std::max(0, prec));
+    std::string s, eol, stra, strb, strc, strd;
+    std::istringstream str;
     int retval = 0;
     while (std::getline(*input, s)) {
       try {
-        std::string eol("\n");
+        eol = "\n";
         if (!cdelim.empty()) {
           std::string::size_type m = s.find(cdelim);
           if (m != std::string::npos) {
@@ -147,10 +163,9 @@ int main(int argc, char* argv[]) {
             s = s.substr(0, m);
           }
         }
-        std::istringstream str(s);
+        str.clear(); str.str(s);
         // initial values to suppress warnings
         real lat, lon, h, x = 0, y = 0, z = 0;
-        std::string stra, strb, strc;
         if (!(str >> stra >> strb >> strc))
           throw GeographicErr("Incomplete input: " + s);
         if (reverse) {
@@ -158,10 +173,9 @@ int main(int argc, char* argv[]) {
           y = Utility::num<real>(strb);
           z = Utility::num<real>(strc);
         } else {
-          DMS::DecodeLatLon(stra, strb, lat, lon);
+          DMS::DecodeLatLon(stra, strb, lat, lon, longfirst);
           h = Utility::num<real>(strc);
         }
-        std::string strd;
         if (str >> strd)
           throw GeographicErr("Extraneous input: " + strd);
         if (reverse) {
@@ -169,17 +183,17 @@ int main(int argc, char* argv[]) {
             lc.Reverse(x, y, z, lat, lon, h);
           else
             ec.Reverse(x, y, z, lat, lon, h);
-          *output << Utility::str(lat, 15 + Math::extra_digits()) << " "
-                  << Utility::str(lon, 15 + Math::extra_digits()) << " "
-                  << Utility::str(h, 12 + Math::extra_digits()) << eol;
+          *output << Utility::str(longfirst ? lon : lat, prec + 5) << " "
+                  << Utility::str(longfirst ? lat : lon, prec + 5) << " "
+                  << Utility::str(h, prec) << eol;
         } else {
           if (localcartesian)
             lc.Forward(lat, lon, h, x, y, z);
           else
             ec.Forward(lat, lon, h, x, y, z);
-          *output << Utility::str(x, 10 + Math::extra_digits()) << " "
-                  << Utility::str(y, 10 + Math::extra_digits()) << " "
-                  << Utility::str(z, 10 + Math::extra_digits()) << eol;
+          *output << Utility::str(x, prec) << " "
+                  << Utility::str(y, prec) << " "
+                  << Utility::str(z, prec) << eol;
         }
       }
       catch (const std::exception& e) {
diff --git a/tools/ConicProj.cpp b/tools/ConicProj.cpp
index 6b99014..e502a34 100644
--- a/tools/ConicProj.cpp
+++ b/tools/ConicProj.cpp
@@ -2,7 +2,7 @@
  * \file ConicProj.cpp
  * \brief Command line utility for conical projections
  *
- * Copyright (c) Charles Karney (2009-2012) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2009-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  *
@@ -32,7 +32,7 @@ int main(int argc, char* argv[]) {
     using namespace GeographicLib;
     typedef Math::real real;
     Utility::set_digits();
-    bool lcc = false, albers = false, reverse = false;
+    bool lcc = false, albers = false, reverse = false, longfirst = false;
     real lat1 = 0, lat2 = 0, lon0 = 0, k1 = 1;
     real
       a = Constants::WGS84_a(),
@@ -69,8 +69,6 @@ int main(int argc, char* argv[]) {
           lon0 = DMS::Decode(std::string(argv[m]), ind);
           if (ind == DMS::LATITUDE)
             throw GeographicErr("Bad hemisphere");
-          if (!(lon0 >= -540 && lon0 < 540))
-            throw GeographicErr("Bad longitude");
           lon0 = Math::AngNormalize(lon0);
         }
         catch (const std::exception& e) {
@@ -99,7 +97,9 @@ int main(int argc, char* argv[]) {
           return 1;
         }
         m += 2;
-      } else if (arg == "-p") {
+      } else if (arg == "-w")
+        longfirst = true;
+       else if (arg == "-p") {
         if (++m == argc) return usage(1, true);
         try {
           prec = Utility::num<int>(std::string(argv[m]));
@@ -188,12 +188,12 @@ int main(int argc, char* argv[]) {
     // Max precision = 10: 0.1 nm in distance, 10^-15 deg (= 0.11 nm),
     // 10^-11 sec (= 0.3 nm).
     prec = std::min(10 + Math::extra_digits(), std::max(0, prec));
-    std::string s;
+    std::string s, eol, stra, strb, strc;
+    std::istringstream str;
     int retval = 0;
-    std::cout << std::fixed;
     while (std::getline(*input, s)) {
       try {
-        std::string eol("\n");
+        eol = "\n";
         if (!cdelim.empty()) {
           std::string::size_type m = s.find(cdelim);
           if (m != std::string::npos) {
@@ -201,17 +201,15 @@ int main(int argc, char* argv[]) {
             s = s.substr(0, m);
           }
         }
-        std::istringstream str(s);
+        str.clear(); str.str(s);
         real lat, lon, x, y, gamma, k;
-        std::string stra, strb;
         if (!(str >> stra >> strb))
           throw GeographicErr("Incomplete input: " + s);
         if (reverse) {
           x = Utility::num<real>(stra);
           y = Utility::num<real>(strb);
         } else
-          DMS::DecodeLatLon(stra, strb, lat, lon);
-        std::string strc;
+          DMS::DecodeLatLon(stra, strb, lat, lon, longfirst);
         if (str >> strc)
           throw GeographicErr("Extraneous input: " + strc);
         if (reverse) {
@@ -219,8 +217,8 @@ int main(int argc, char* argv[]) {
             lproj.Reverse(lon0, x, y, lat, lon, gamma, k);
           else
             aproj.Reverse(lon0, x, y, lat, lon, gamma, k);
-          *output << Utility::str(lat, prec + 5) << " "
-                  << Utility::str(lon, prec + 5) << " "
+          *output << Utility::str(longfirst ? lon : lat, prec + 5) << " "
+                  << Utility::str(longfirst ? lat : lon, prec + 5) << " "
                   << Utility::str(gamma, prec + 6) << " "
                   << Utility::str(k, prec + 6) << eol;
         } else {
diff --git a/tools/GeoConvert.cpp b/tools/GeoConvert.cpp
index 2c8745a..67c5280 100644
--- a/tools/GeoConvert.cpp
+++ b/tools/GeoConvert.cpp
@@ -2,7 +2,7 @@
  * \file GeoConvert.cpp
  * \brief Command line utility for geographic coordinate conversions
  *
- * Copyright (c) Charles Karney (2008-2014) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2008-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  *
@@ -35,7 +35,7 @@ int main(int argc, char* argv[]) {
     int outputmode = GEOGRAPHIC;
     int prec = 0;
     int zone = UTMUPS::MATCH;
-    bool centerp = true, swaplatlong = false;
+    bool centerp = true, longfirst = false;
     std::string istring, ifile, ofile, cdelim;
     char lsep = ';', dmssep = char(0);
     bool sethemisphere = false, northp = false, abbrev = true;
@@ -58,22 +58,7 @@ int main(int argc, char* argv[]) {
         outputmode = CONVERGENCE;
       else if (arg == "-n")
         centerp = false;
-      else if (arg == "-w")
-        swaplatlong = true;
-      else if (arg == "-l")
-        abbrev = false;
-      else if (arg == "-a")
-        abbrev = true;
-      else if (arg == "-p") {
-        if (++m == argc) return usage(1, true);
-        try {
-          prec = Utility::num<int>(std::string(argv[m]));
-        }
-        catch (const std::exception&) {
-          std::cerr << "Precision " << argv[m] << " is not a number\n";
-          return 1;
-        }
-      } else if (arg == "-z") {
+      else if (arg == "-z") {
         if (++m == argc) return usage(1, true);
         std::string zonestr(argv[m]);
         try {
@@ -100,7 +85,22 @@ int main(int argc, char* argv[]) {
       } else if (arg == "-t") {
         zone = UTMUPS::UTM;
         sethemisphere = false;
-      } else if (arg == "--input-string") {
+      } else if (arg == "-w")
+        longfirst = true;
+      else if (arg == "-p") {
+        if (++m == argc) return usage(1, true);
+        try {
+          prec = Utility::num<int>(std::string(argv[m]));
+        }
+        catch (const std::exception&) {
+          std::cerr << "Precision " << argv[m] << " is not a number\n";
+          return 1;
+        }
+      } else if (arg == "-l")
+        abbrev = false;
+      else if (arg == "-a")
+        abbrev = true;
+      else if (arg == "--input-string") {
         if (++m == argc) return usage(1, true);
         istring = argv[m];
       } else if (arg == "--input-file") {
@@ -166,12 +166,12 @@ int main(int argc, char* argv[]) {
     std::ostream* output = !ofile.empty() ? &outfile : &std::cout;
 
     GeoCoords p;
-    std::string s;
+    std::string s, eol;
     std::string os;
     int retval = 0;
 
     while (std::getline(*input, s)) {
-      std::string eol("\n");
+      eol = "\n";
       try {
         if (!cdelim.empty()) {
           std::string::size_type m = s.find(cdelim);
@@ -180,14 +180,14 @@ int main(int argc, char* argv[]) {
             s = s.substr(0, m);
           }
         }
-        p.Reset(s, centerp, swaplatlong);
+        p.Reset(s, centerp, longfirst);
         p.SetAltZone(zone);
         switch (outputmode) {
         case GEOGRAPHIC:
-          os = p.GeoRepresentation(prec, swaplatlong);
+          os = p.GeoRepresentation(prec, longfirst);
           break;
         case DMS:
-          os = p.DMSRepresentation(prec, swaplatlong, dmssep);
+          os = p.DMSRepresentation(prec, longfirst, dmssep);
           break;
         case UTMUPS:
           os = (sethemisphere
diff --git a/tools/GeodSolve.cpp b/tools/GeodSolve.cpp
index 034485a..582a77e 100644
--- a/tools/GeodSolve.cpp
+++ b/tools/GeodSolve.cpp
@@ -31,19 +31,22 @@
 
 typedef GeographicLib::Math::real real;
 
-std::string LatLonString(real lat, real lon, int prec, bool dms, char dmssep) {
+std::string LatLonString(real lat, real lon, int prec, bool dms, char dmssep,
+                         bool longfirst) {
   using namespace GeographicLib;
-  return dms ?
-    DMS::Encode(lat, prec + 5, DMS::LATITUDE, dmssep) + " " +
-    DMS::Encode(lon, prec + 5, DMS::LONGITUDE, dmssep) :
-    DMS::Encode(lat, prec + 5, DMS::NUMBER) + " " +
+  std::string
+    latstr = dms ? DMS::Encode(lat, prec + 5, DMS::LATITUDE, dmssep) :
+    DMS::Encode(lat, prec + 5, DMS::NUMBER),
+    lonstr = dms ? DMS::Encode(lon, prec + 5, DMS::LONGITUDE, dmssep) :
     DMS::Encode(lon, prec + 5, DMS::NUMBER);
+  return
+    (longfirst ? lonstr : latstr) + " " + (longfirst ? latstr : lonstr);
 }
 
 std::string AzimuthString(real azi, int prec, bool dms, char dmssep) {
   using namespace GeographicLib;
   return dms ? DMS::Encode(azi, prec + 5, DMS::AZIMUTH, dmssep) :
-    DMS::Encode(azi >= 180 ? azi - 360 : azi, prec + 5, DMS::NUMBER);
+    DMS::Encode(azi, prec + 5, DMS::NUMBER);
 }
 
 std::string DistanceStrings(real s12, real a12,
@@ -69,12 +72,12 @@ int main(int argc, char* argv[]) {
     using namespace GeographicLib;
     Utility::set_digits();
     bool linecalc = false, inverse = false, arcmode = false,
-      dms = false, full = false, exact = false, unroll = false;
+      dms = false, full = false, exact = false, unroll = false,
+      longfirst = false, azi2back = false;
     real
       a = Constants::WGS84_a(),
       f = Constants::WGS84_f();
     real lat1, lon1, azi1, lat2, lon2, azi2, s12, m12, a12, M12, M21, S12;
-    real azi2sense = 0;
     int prec = 3;
     std::string istring, ifile, ofile, cdelim;
     char lsep = ';', dmssep = char(0);
@@ -92,7 +95,7 @@ int main(int argc, char* argv[]) {
         if (m + 3 >= argc) return usage(1, true);
         try {
           DMS::DecodeLatLon(std::string(argv[m + 1]), std::string(argv[m + 2]),
-                            lat1, lon1);
+                            lat1, lon1, longfirst);
           azi1 = DMS::DecodeAzimuth(std::string(argv[m + 3]));
         }
         catch (const std::exception& e) {
@@ -119,8 +122,10 @@ int main(int argc, char* argv[]) {
       } else if (arg == "-:") {
         dms = true;
         dmssep = ':';
-      } else if (arg == "-b")
-        azi2sense = 180;
+      } else if (arg == "-w")
+        longfirst = true;
+      else if (arg == "-b")
+        azi2back = true;
       else if (arg == "-f")
         full = true;
       else if (arg == "-p") {
@@ -224,11 +229,12 @@ int main(int argc, char* argv[]) {
     // Max precision = 10: 0.1 nm in distance, 10^-15 deg (= 0.11 nm),
     // 10^-11 sec (= 0.3 nm).
     prec = std::min(10 + Math::extra_digits(), std::max(0, prec));
-    std::string s;
+    std::string s, eol, slat1, slon1, slat2, slon2, sazi1, ss12, strc;
+    std::istringstream str;
     int retval = 0;
     while (std::getline(*input, s)) {
       try {
-        std::string eol("\n");
+        eol = "\n";
         if (!cdelim.empty()) {
           std::string::size_type m = s.find(cdelim);
           if (m != std::string::npos) {
@@ -236,33 +242,36 @@ int main(int argc, char* argv[]) {
             s = s.substr(0, m);
           }
         }
-        std::istringstream str(s);
+        str.clear(); str.str(s);
         if (inverse) {
-          std::string slat1, slon1, slat2, slon2;
           if (!(str >> slat1 >> slon1 >> slat2 >> slon2))
             throw GeographicErr("Incomplete input: " + s);
-          std::string strc;
           if (str >> strc)
             throw GeographicErr("Extraneous input: " + strc);
-          DMS::DecodeLatLon(slat1, slon1, lat1, lon1);
-          DMS::DecodeLatLon(slat2, slon2, lat2, lon2);
+          DMS::DecodeLatLon(slat1, slon1, lat1, lon1, longfirst);
+          DMS::DecodeLatLon(slat2, slon2, lat2, lon2, longfirst);
           a12 = exact ?
             geode.GenInverse(lat1, lon1, lat2, lon2, outmask,
                              s12, azi1, azi2, m12, M12, M21, S12) :
             geods.GenInverse(lat1, lon1, lat2, lon2, outmask,
                              s12, azi1, azi2, m12, M12, M21, S12);
           if (full) {
-            lon2 = Math::AngNormalize(lon2);
             if (unroll)
-              lon2 = lon1 + Math::AngDiff(Math::AngNormalize(lon1), lon2);
-            else
+              lon2 = lon1 + Math::AngDiff(lon1, lon2);
+            else {
               lon1 = Math::AngNormalize(lon1);
-            *output << LatLonString(lat1, lon1, prec, dms, dmssep) << " ";
+              lon2 = Math::AngNormalize(lon2);
+            }
+            *output << LatLonString(lat1, lon1, prec, dms, dmssep, longfirst)
+                    << " ";
           }
           *output << AzimuthString(azi1, prec, dms, dmssep) << " ";
           if (full)
-            *output << LatLonString(lat2, lon2, prec, dms, dmssep) << " ";
-          *output << AzimuthString(azi2 + azi2sense, prec, dms, dmssep) << " "
+            *output << LatLonString(lat2, lon2, prec, dms, dmssep, longfirst)
+                    << " ";
+          if (azi2back)
+            azi2 += azi2 >= 0 ? -180 : 180;
+          *output << AzimuthString(azi2, prec, dms, dmssep) << " "
                   << DistanceStrings(s12, a12, full, arcmode, prec, dms);
           if (full)
             *output << " " << Utility::str(m12, prec)
@@ -272,10 +281,8 @@ int main(int argc, char* argv[]) {
           *output << eol;
         } else {
           if (linecalc) {
-            std::string ss12;
             if (!(str >> ss12))
               throw GeographicErr("Incomplete input: " + s);
-            std::string strc;
             if (str >> strc)
               throw GeographicErr("Extraneous input: " + strc);
             s12 = ReadDistance(ss12, arcmode);
@@ -285,13 +292,11 @@ int main(int argc, char* argv[]) {
               ls.GenPosition(arcmode, s12, outmask,
                              lat2, lon2, azi2, s12, m12, M12, M21, S12);
           } else {
-            std::string slat1, slon1, sazi1, ss12;
             if (!(str >> slat1 >> slon1 >> sazi1 >> ss12))
               throw GeographicErr("Incomplete input: " + s);
-            std::string strc;
             if (str >> strc)
               throw GeographicErr("Extraneous input: " + strc);
-            DMS::DecodeLatLon(slat1, slon1, lat1, lon1);
+            DMS::DecodeLatLon(slat1, slon1, lat1, lon1, longfirst);
             azi1 = DMS::DecodeAzimuth(sazi1);
             s12 = ReadDistance(ss12, arcmode);
             a12 = exact ?
@@ -303,10 +308,12 @@ int main(int argc, char* argv[]) {
           if (full)
             *output
               << LatLonString(lat1, unroll ? lon1 : Math::AngNormalize(lon1),
-                              prec, dms, dmssep) << " "
-              << AzimuthString(azi1, prec, dms, dmssep) << " ";
-          *output << LatLonString(lat2, lon2, prec, dms, dmssep) << " "
-                  << AzimuthString(azi2 + azi2sense, prec, dms, dmssep);
+                              prec, dms, dmssep, longfirst)
+              << " " << AzimuthString(azi1, prec, dms, dmssep) << " ";
+          if (azi2back)
+            azi2 += azi2 >= 0 ? -180 : 180;
+          *output << LatLonString(lat2, lon2, prec, dms, dmssep, longfirst)
+                  << " " << AzimuthString(azi2, prec, dms, dmssep);
           if (full)
             *output << " "
                     << DistanceStrings(s12, a12, full, arcmode, prec, dms)
diff --git a/tools/GeodesicProj.cpp b/tools/GeodesicProj.cpp
index e13f952..3af89b6 100644
--- a/tools/GeodesicProj.cpp
+++ b/tools/GeodesicProj.cpp
@@ -2,7 +2,7 @@
  * \file GeodesicProj.cpp
  * \brief Command line utility for geodesic projections
  *
- * Copyright (c) Charles Karney (2009-2012) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2009-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  *
@@ -34,7 +34,8 @@ int main(int argc, char* argv[]) {
     using namespace GeographicLib;
     typedef Math::real real;
     Utility::set_digits();
-    bool azimuthal = false, cassini = false, gnomonic = false, reverse = false;
+    bool azimuthal = false, cassini = false, gnomonic = false, reverse = false,
+      longfirst = false;
     real lat0 = 0, lon0 = 0;
     real
       a = Constants::WGS84_a(),
@@ -54,7 +55,7 @@ int main(int argc, char* argv[]) {
         if (m + 2 >= argc) return usage(1, true);
         try {
           DMS::DecodeLatLon(std::string(argv[m + 1]), std::string(argv[m + 2]),
-                            lat0, lon0);
+                            lat0, lon0, longfirst);
         }
         catch (const std::exception& e) {
           std::cerr << "Error decoding arguments of " << arg << ": "
@@ -73,7 +74,9 @@ int main(int argc, char* argv[]) {
           return 1;
         }
         m += 2;
-      } else if (arg == "-p") {
+      } else if (arg == "-w")
+        longfirst = true;
+      else if (arg == "-p") {
         if (++m == argc) return usage(1, true);
         try {
           prec = Utility::num<int>(std::string(argv[m]));
@@ -161,12 +164,13 @@ int main(int argc, char* argv[]) {
     // Max precision = 10: 0.1 nm in distance, 10^-15 deg (= 0.11 nm),
     // 10^-11 sec (= 0.3 nm).
     prec = std::min(10 + Math::extra_digits(), std::max(0, prec));
-    std::string s;
+    std::string s, eol, stra, strb, strc;
+    std::istringstream str;
     int retval = 0;
     std::cout << std::fixed;
     while (std::getline(*input, s)) {
       try {
-        std::string eol("\n");
+        eol = "\n";
         if (!cdelim.empty()) {
           std::string::size_type m = s.find(cdelim);
           if (m != std::string::npos) {
@@ -174,17 +178,15 @@ int main(int argc, char* argv[]) {
             s = s.substr(0, m);
           }
         }
-        std::istringstream str(s);
+        str.clear(); str.str(s);
         real lat, lon, x, y, azi, rk;
-        std::string stra, strb;
         if (!(str >> stra >> strb))
           throw GeographicErr("Incomplete input: " + s);
         if (reverse) {
           x = Utility::num<real>(stra);
           y = Utility::num<real>(strb);
         } else
-          DMS::DecodeLatLon(stra, strb, lat, lon);
-        std::string strc;
+          DMS::DecodeLatLon(stra, strb, lat, lon, longfirst);
         if (str >> strc)
           throw GeographicErr("Extraneous input: " + strc);
         if (reverse) {
@@ -194,8 +196,8 @@ int main(int argc, char* argv[]) {
             az.Reverse(lat0, lon0, x, y, lat, lon, azi, rk);
           else
             gn.Reverse(lat0, lon0, x, y, lat, lon, azi, rk);
-          *output << Utility::str(lat, prec + 5) << " "
-                  << Utility::str(lon, prec + 5) << " "
+          *output << Utility::str(longfirst ? lon : lat, prec + 5) << " "
+                  << Utility::str(longfirst ? lat : lon, prec + 5) << " "
                   << Utility::str(azi, prec + 5) << " "
                   << Utility::str(rk, prec + 6) << eol;
         } else {
diff --git a/tools/GeoidEval.cpp b/tools/GeoidEval.cpp
index 6ee35b6..dcc7973 100644
--- a/tools/GeoidEval.cpp
+++ b/tools/GeoidEval.cpp
@@ -2,7 +2,7 @@
  * \file GeoidEval.cpp
  * \brief Command line utility for evaluating geoid heights
  *
- * Copyright (c) Charles Karney (2009-2012) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2009-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  *
@@ -39,7 +39,7 @@ int main(int argc, char* argv[]) {
     Geoid::convertflag heightmult = Geoid::NONE;
     std::string istring, ifile, ofile, cdelim;
     char lsep = ';';
-    bool northp = false;
+    bool northp = false, longfirst = false;
     int zonenum = UTMUPS::INVALID;
 
     for (int m = 1; m < argc; ++m) {
@@ -54,9 +54,9 @@ int main(int argc, char* argv[]) {
         cachearea = true;
         try {
           DMS::DecodeLatLon(std::string(argv[m + 1]), std::string(argv[m + 2]),
-                            caches, cachew);
+                            caches, cachew, longfirst);
           DMS::DecodeLatLon(std::string(argv[m + 3]), std::string(argv[m + 4]),
-                            cachen, cachee);
+                            cachen, cachee, longfirst);
         }
         catch (const std::exception& e) {
           std::cerr << "Error decoding argument of -c: " << e.what() << "\n";
@@ -67,6 +67,8 @@ int main(int argc, char* argv[]) {
         heightmult = Geoid::GEOIDTOELLIPSOID;
       else if (arg == "--haetomsl")
         heightmult = Geoid::ELLIPSOIDTOGEOID;
+      else if (arg == "-w")
+        longfirst = true;
       else if (arg == "-z") {
         if (++m == argc) return usage(1, true);
         std::string zone = argv[m];
@@ -192,11 +194,11 @@ int main(int argc, char* argv[]) {
       }
 
       GeoCoords p;
-      std::string s, suff;
+      std::string s, eol, suff;
       const char* spaces = " \t\n\v\f\r,"; // Include comma as space
       while (std::getline(*input, s)) {
         try {
-          std::string eol("\n");
+          eol = "\n";
           if (!cdelim.empty()) {
             std::string::size_type m = s.find(cdelim);
             if (m != std::string::npos) {
@@ -243,7 +245,7 @@ int main(int argc, char* argv[]) {
               height = Utility::num<real>(s.substr(pa + 1, pb - pa));
               s = s.substr(0, pa + 1);
             }
-            p.Reset(s);
+            p.Reset(s, true, longfirst);
           }
           if (heightmult) {
             real h = g(p.Latitude(), p.Longitude());
diff --git a/tools/Gravity.cpp b/tools/Gravity.cpp
index 0a34cfb..e16b69b 100644
--- a/tools/Gravity.cpp
+++ b/tools/Gravity.cpp
@@ -2,7 +2,7 @@
  * \file Gravity.cpp
  * \brief Command line utility for evaluating gravity fields
  *
- * Copyright (c) Charles Karney (2011-2012) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2011-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  *
@@ -31,7 +31,7 @@ int main(int argc, char* argv[]) {
     using namespace GeographicLib;
     typedef Math::real real;
     Utility::set_digits();
-    bool verbose = false;
+    bool verbose = false, longfirst = false;
     std::string dir;
     std::string model = GravityModel::DefaultGravityName();
     std::string istring, ifile, ofile, cdelim;
@@ -80,7 +80,9 @@ int main(int argc, char* argv[]) {
                     << e.what() << "\n";
           return 1;
         }
-      } else if (arg == "-p") {
+      } else if (arg == "-w")
+        longfirst = true;
+      else if (arg == "-p") {
         if (++m == argc) return usage(1, true);
         try {
           prec = Utility::num<int>(std::string(argv[m]));
@@ -196,10 +198,11 @@ int main(int argc, char* argv[]) {
                         (mode == ANOMALY ? GravityModel::SPHERICAL_ANOMALY :
                          GravityModel::GEOID_HEIGHT))); // mode == UNDULATION
       const GravityCircle c(circle ? g.Circle(lat, h, mask) : GravityCircle());
-      std::string s, stra, strb;
+      std::string s, eol, stra, strb;
+      std::istringstream str;
       while (std::getline(*input, s)) {
         try {
-          std::string eol("\n");
+          eol = "\n";
           if (!cdelim.empty()) {
             std::string::size_type m = s.find(cdelim);
             if (m != std::string::npos) {
@@ -207,7 +210,7 @@ int main(int argc, char* argv[]) {
               s = s.substr(0, m);
             }
           }
-          std::istringstream str(s);
+          str.clear(); str.str(s);
           real lon;
           if (circle) {
             if (!(str >> strb))
@@ -216,13 +219,10 @@ int main(int argc, char* argv[]) {
             lon = DMS::Decode(strb, ind);
             if (ind == DMS::LATITUDE)
               throw GeographicErr("Bad hemisphere letter on " + strb);
-            if (lon < -540 || lon >= 540)
-              throw GeographicErr("Longitude " + strb +
-                                  " not in [-540d, 540d)");
           } else {
             if (!(str >> stra >> strb))
               throw GeographicErr("Incomplete input: " + s);
-            DMS::DecodeLatLon(stra, strb, lat, lon);
+            DMS::DecodeLatLon(stra, strb, lat, lon, longfirst);
             h = 0;
             if (!(str >> h))    // h is optional
               str.clear();
diff --git a/tools/MagneticField.cpp b/tools/MagneticField.cpp
index 62ce014..1e22fac 100644
--- a/tools/MagneticField.cpp
+++ b/tools/MagneticField.cpp
@@ -2,7 +2,7 @@
  * \file MagneticField.cpp
  * \brief Command line utility for evaluating magnetic fields
  *
- * Copyright (c) Charles Karney (2011-2012) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2011-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  *
@@ -30,7 +30,7 @@ int main(int argc, char* argv[]) {
     using namespace GeographicLib;
     typedef Math::real real;
     Utility::set_digits();
-    bool verbose = false;
+    bool verbose = false, longfirst = false;
     std::string dir;
     std::string model = MagneticModel::DefaultMagneticName();
     std::string istring, ifile, ofile, cdelim;
@@ -82,6 +82,8 @@ int main(int argc, char* argv[]) {
         }
       } else if (arg == "-r")
         rate = !rate;
+      else if (arg == "-w")
+        longfirst = true;
       else if (arg == "-p") {
         if (++m == argc) return usage(1, true);
         try {
@@ -230,10 +232,11 @@ int main(int argc, char* argv[]) {
                   << m.MaxHeight()/1000 << "km]\n";
       const MagneticCircle c(circle ? m.Circle(time, lat, h) :
                              MagneticCircle());
-      std::string s, stra, strb;
+      std::string s, eol, stra, strb;
+      std::istringstream str(s);
       while (std::getline(*input, s)) {
         try {
-          std::string eol("\n");
+          eol = "\n";
           if (!cdelim.empty()) {
             std::string::size_type n = s.find(cdelim);
             if (n != std::string::npos) {
@@ -241,7 +244,7 @@ int main(int argc, char* argv[]) {
               s = s.substr(0, n);
             }
           }
-          std::istringstream str(s);
+          str.clear(); str.str(s);
           if (!(timeset || circle)) {
             if (!(str >> stra))
               throw GeographicErr("Incomplete input: " + s);
@@ -265,13 +268,10 @@ int main(int argc, char* argv[]) {
             lon = DMS::Decode(strb, ind);
             if (ind == DMS::LATITUDE)
               throw GeographicErr("Bad hemisphere letter on " + strb);
-            if (lon < -540 || lon >= 540)
-              throw GeographicErr("Longitude " + strb +
-                                  " not in [-540d, 540d)");
           } else {
             if (!(str >> stra >> strb))
               throw GeographicErr("Incomplete input: " + s);
-            DMS::DecodeLatLon(stra, strb, lat, lon);
+            DMS::DecodeLatLon(stra, strb, lat, lon, longfirst);
             h = 0;              // h is optional
             if (str >> h) {
               if (h < m.MinHeight() - hguard || h > m.MaxHeight() + hguard)
diff --git a/tools/Planimeter.cpp b/tools/Planimeter.cpp
index a175ad5..44f483d 100644
--- a/tools/Planimeter.cpp
+++ b/tools/Planimeter.cpp
@@ -2,7 +2,7 @@
  * \file Planimeter.cpp
  * \brief Command line utility for measuring the area of geodesic polygons
  *
- * Copyright (c) Charles Karney (2010-2014) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2010-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  *
@@ -35,7 +35,7 @@ int main(int argc, char* argv[]) {
     real
       a = Constants::WGS84_a(),
       f = Constants::WGS84_f();
-    bool reverse = false, sign = true, polyline = false;
+    bool reverse = false, sign = true, polyline = false, longfirst = false;
     int linetype = GEODESIC;
     int prec = 6;
     std::string istring, ifile, ofile, cdelim;
@@ -60,7 +60,9 @@ int main(int argc, char* argv[]) {
           return 1;
         }
         m += 2;
-      } else if (arg == "-p") {
+      } else if (arg == "-w")
+        longfirst = true;
+      else if (arg == "-p") {
         if (++m == argc) return usage(1, true);
         try {
           prec = Utility::num<int>(std::string(argv[m]));
@@ -158,10 +160,9 @@ int main(int argc, char* argv[]) {
     // Max precision = 10: 0.1 nm in distance, 10^-15 deg (= 0.11 nm),
     // 10^-11 sec (= 0.3 nm).
     prec = std::min(10 + Math::extra_digits(), std::max(0, prec));
-    std::string s;
+    std::string s, eol("\n");
     real perimeter, area;
     unsigned num;
-    std::string eol("\n");
     while (std::getline(*input, s)) {
       if (!cdelim.empty()) {
         std::string::size_type m = s.find(cdelim);
@@ -173,7 +174,7 @@ int main(int argc, char* argv[]) {
       bool endpoly = s.empty();
       if (!endpoly) {
         try {
-          p.Reset(s);
+          p.Reset(s, longfirst);
           if (Math::isnan(p.Latitude()) || Math::isnan(p.Longitude()))
             endpoly = true;
         }
diff --git a/tools/RhumbSolve.cpp b/tools/RhumbSolve.cpp
index 91854c9..4fb4104 100644
--- a/tools/RhumbSolve.cpp
+++ b/tools/RhumbSolve.cpp
@@ -2,7 +2,7 @@
  * \file RhumbSolve.cpp
  * \brief Command line utility for rhumb line calculations
  *
- * Copyright (c) Charles Karney (2014) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2014-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  *
@@ -31,23 +31,28 @@
 using namespace GeographicLib;
 typedef Math::real real;
 
-std::string LatLonString(real lat, real lon, int prec, bool dms, char dmssep) {
-  return dms ?
-    DMS::Encode(lat, prec + 5, DMS::LATITUDE, dmssep) + " " +
-    DMS::Encode(lon, prec + 5, DMS::LONGITUDE, dmssep) :
-    DMS::Encode(lat, prec + 5, DMS::NUMBER) + " " +
+std::string LatLonString(real lat, real lon, int prec, bool dms, char dmssep,
+                         bool longfirst) {
+  using namespace GeographicLib;
+  std::string
+    latstr = dms ? DMS::Encode(lat, prec + 5, DMS::LATITUDE, dmssep) :
+    DMS::Encode(lat, prec + 5, DMS::NUMBER),
+    lonstr = dms ? DMS::Encode(lon, prec + 5, DMS::LONGITUDE, dmssep) :
     DMS::Encode(lon, prec + 5, DMS::NUMBER);
+  return
+    (longfirst ? lonstr : latstr) + " " + (longfirst ? latstr : lonstr);
 }
 
 std::string AzimuthString(real azi, int prec, bool dms, char dmssep) {
   return dms ? DMS::Encode(azi, prec + 5, DMS::AZIMUTH, dmssep) :
-    DMS::Encode(azi >= 180 ? azi - 360 : azi, prec + 5, DMS::NUMBER);
+    DMS::Encode(azi, prec + 5, DMS::NUMBER);
 }
 
 int main(int argc, char* argv[]) {
   try {
     Utility::set_digits();
-    bool linecalc = false, inverse = false, dms = false, exact = true;
+    bool linecalc = false, inverse = false, dms = false, exact = true,
+      longfirst = false;
     real
       a = Constants::WGS84_a(),
       f = Constants::WGS84_f();
@@ -67,7 +72,7 @@ int main(int argc, char* argv[]) {
         if (m + 3 >= argc) return usage(1, true);
         try {
           DMS::DecodeLatLon(std::string(argv[m + 1]), std::string(argv[m + 2]),
-                            lat1, lon1);
+                            lat1, lon1, longfirst);
           azi12 = DMS::DecodeAzimuth(std::string(argv[m + 3]));
         }
         catch (const std::exception& e) {
@@ -93,7 +98,9 @@ int main(int argc, char* argv[]) {
       } else if (arg == "-:") {
         dms = true;
         dmssep = ':';
-      } else if (arg == "-p") {
+      } else if (arg == "-w")
+        longfirst = true;
+      else if (arg == "-p") {
         if (++m == argc) return usage(1, true);
         try {
           prec = Utility::num<int>(std::string(argv[m]));
@@ -174,11 +181,12 @@ int main(int argc, char* argv[]) {
     // Max precision = 10: 0.1 nm in distance, 10^-15 deg (= 0.11 nm),
     // 10^-11 sec (= 0.3 nm).
     prec = std::min(10 + Math::extra_digits(), std::max(0, prec));
+    std::string s, eol, slat1, slon1, slat2, slon2, sazi, ss12, strc;
+    std::istringstream str;
     int retval = 0;
-    std::string s;
     while (std::getline(*input, s)) {
       try {
-        std::string eol("\n");
+        eol = "\n";
         if (!cdelim.empty()) {
           std::string::size_type m = s.find(cdelim);
           if (m != std::string::npos) {
@@ -186,41 +194,36 @@ int main(int argc, char* argv[]) {
             s = s.substr(0, m);
           }
         }
-        std::istringstream str(s);
+        str.clear(); str.str(s);
         if (linecalc) {
           if (!(str >> s12))
             throw GeographicErr("Incomplete input: " + s);
-          std::string strc;
           if (str >> strc)
             throw GeographicErr("Extraneous input: " + strc);
           rhl.Position(s12, lat2, lon2, S12);
-          *output << LatLonString(lat2, lon2, prec, dms, dmssep) << " "
-                  << Utility::str(S12, std::max(prec-7, 0)) << eol;
+          *output << LatLonString(lat2, lon2, prec, dms, dmssep, longfirst)
+                  << " " << Utility::str(S12, std::max(prec-7, 0)) << eol;
         } else if (inverse) {
-          std::string slat1, slon1, slat2, slon2;
           if (!(str >> slat1 >> slon1 >> slat2 >> slon2))
             throw GeographicErr("Incomplete input: " + s);
-          std::string strc;
           if (str >> strc)
             throw GeographicErr("Extraneous input: " + strc);
-          DMS::DecodeLatLon(slat1, slon1, lat1, lon1);
-          DMS::DecodeLatLon(slat2, slon2, lat2, lon2);
+          DMS::DecodeLatLon(slat1, slon1, lat1, lon1, longfirst);
+          DMS::DecodeLatLon(slat2, slon2, lat2, lon2, longfirst);
           rh.Inverse(lat1, lon1, lat2, lon2, s12, azi12, S12);
           *output << AzimuthString(azi12, prec, dms, dmssep) << " "
                   << Utility::str(s12, prec) << " "
                   << Utility::str(S12, std::max(prec-7, 0)) << eol;
         } else {                // direct
-          std::string slat1, slon1, sazi;
           if (!(str >> slat1 >> slon1 >> sazi >> s12))
             throw GeographicErr("Incomplete input: " + s);
-          std::string strc;
           if (str >> strc)
             throw GeographicErr("Extraneous input: " + strc);
-          DMS::DecodeLatLon(slat1, slon1, lat1, lon1);
+          DMS::DecodeLatLon(slat1, slon1, lat1, lon1, longfirst);
           azi12 = DMS::DecodeAzimuth(sazi);
           rh.Direct(lat1, lon1, azi12, s12, lat2, lon2, S12);
-          *output << LatLonString(lat2, lon2, prec, dms, dmssep) << " "
-                  << Utility::str(S12, std::max(prec-7, 0)) << eol;
+          *output << LatLonString(lat2, lon2, prec, dms, dmssep, longfirst)
+                  << " " << Utility::str(S12, std::max(prec-7, 0)) << eol;
         }
       }
       catch (const std::exception& e) {
diff --git a/tools/TransverseMercatorProj.cpp b/tools/TransverseMercatorProj.cpp
index 211cdfe..2956ebd 100644
--- a/tools/TransverseMercatorProj.cpp
+++ b/tools/TransverseMercatorProj.cpp
@@ -2,7 +2,7 @@
  * \file TransverseMercatorProj.cpp
  * \brief Command line utility for transverse Mercator projections
  *
- * Copyright (c) Charles Karney (2008-2012) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2008-2015) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  *
@@ -15,7 +15,6 @@
 #include <string>
 #include <sstream>
 #include <fstream>
-#include <GeographicLib/EllipticFunction.hpp>
 #include <GeographicLib/TransverseMercatorExact.hpp>
 #include <GeographicLib/TransverseMercator.hpp>
 #include <GeographicLib/DMS.hpp>
@@ -34,7 +33,8 @@ int main(int argc, char* argv[]) {
     using namespace GeographicLib;
     typedef Math::real real;
     Utility::set_digits();
-    bool exact = true, extended = false, series = false, reverse = false;
+    bool exact = true, extended = false, series = false, reverse = false,
+      longfirst = false;
     real
       a = Constants::WGS84_a(),
       f = Constants::WGS84_f(),
@@ -63,8 +63,6 @@ int main(int argc, char* argv[]) {
           lon0 = DMS::Decode(std::string(argv[m]), ind);
           if (ind == DMS::LATITUDE)
             throw GeographicErr("Bad hemisphere");
-          if (!(lon0 >= -540 && lon0 < 540))
-            throw GeographicErr("Bad longitude");
           lon0 = Math::AngNormalize(lon0);
         }
         catch (const std::exception& e) {
@@ -93,7 +91,9 @@ int main(int argc, char* argv[]) {
           return 1;
         }
         m += 2;
-      } else if (arg == "-p") {
+      } else if (arg == "-w")
+        longfirst = true;
+      else if (arg == "-p") {
         if (++m == argc) return usage(1, true);
         try {
           prec = Utility::num<int>(std::string(argv[m]));
@@ -176,12 +176,13 @@ int main(int argc, char* argv[]) {
     // Max precision = 10: 0.1 nm in distance, 10^-15 deg (= 0.11 nm),
     // 10^-11 sec (= 0.3 nm).
     prec = std::min(10 + Math::extra_digits(), std::max(0, prec));
-    std::string s;
+    std::string s, eol, stra, strb, strc;
+    std::istringstream str(s);
     int retval = 0;
     std::cout << std::fixed;
     while (std::getline(*input, s)) {
       try {
-        std::string eol("\n");
+        eol = "\n";
         if (!cdelim.empty()) {
           std::string::size_type m = s.find(cdelim);
           if (m != std::string::npos) {
@@ -189,17 +190,15 @@ int main(int argc, char* argv[]) {
             s = s.substr(0, m);
           }
         }
-        std::istringstream str(s);
+        str.clear(); str.str(s);
         real lat, lon, x, y;
-        std::string stra, strb;
         if (!(str >> stra >> strb))
           throw GeographicErr("Incomplete input: " + s);
         if (reverse) {
           x = Utility::num<real>(stra);
           y = Utility::num<real>(strb);
         } else
-          DMS::DecodeLatLon(stra, strb, lat, lon);
-        std::string strc;
+          DMS::DecodeLatLon(stra, strb, lat, lon, longfirst);
         if (str >> strc)
           throw GeographicErr("Extraneous input: " + strc);
         real gamma, k;
@@ -208,8 +207,8 @@ int main(int argc, char* argv[]) {
             TMS.Reverse(lon0, x, y, lat, lon, gamma, k);
           else
             TME.Reverse(lon0, x, y, lat, lon, gamma, k);
-          *output << Utility::str(lat, prec + 5) << " "
-                  << Utility::str(lon, prec + 5) << " "
+          *output << Utility::str(longfirst ? lon : lat, prec + 5) << " "
+                  << Utility::str(longfirst ? lat : lon, prec + 5) << " "
                   << Utility::str(gamma, prec + 6) << " "
                   << Utility::str(k, prec + 6) << eol;
         } else {
diff --git a/tools/tests.cmake b/tools/tests.cmake
index b31a10a..80c42c4 100644
--- a/tools/tests.cmake
+++ b/tools/tests.cmake
@@ -49,6 +49,42 @@ add_test (NAME GeoConvert8 COMMAND GeoConvert -u -p 6 --input-string "86 0")
 set_tests_properties (GeoConvert8 PROPERTIES PASS_REGULAR_EXPRESSION
   "n 2000000\\.0* 1555731\\.570643")
 
+# Check that integer(minutes) >= 60 and decimal(minutes) > 60 fail.
+# Latter used to succeed; fixed 2015-06-11.
+add_test (NAME GeoConvert9 COMMAND GeoConvert --input-string "5d70.0 10")
+add_test (NAME GeoConvert10 COMMAND GeoConvert --input-string "5d60 10")
+set_tests_properties (GeoConvert9 GeoConvert10 PROPERTIES WILL_FAIL ON)
+# Check that integer(minutes) < 60 and decimal(minutes) <= 60 succeed.
+# Latter used to fail with 60.; fixed 2015-06-11.
+add_test (NAME GeoConvert11 COMMAND GeoConvert --input-string "5d59 10")
+add_test (NAME GeoConvert12 COMMAND GeoConvert --input-string "5d60. 10")
+add_test (NAME GeoConvert13 COMMAND GeoConvert --input-string "5d60.0 10")
+
+# Check DMS::Encode does round ties to even.  Fixed 2015-06-11.
+add_test (NAME GeoConvert14 COMMAND GeoConvert
+  -: -p -4 --input-string "5.25 5.75")
+set_tests_properties (GeoConvert14
+  PROPERTIES PASS_REGULAR_EXPRESSION "05.2N 005.8E")
+add_test (NAME GeoConvert15 COMMAND GeoConvert
+  -: -p -1 --input-string "5.03125 5.09375")
+set_tests_properties (GeoConvert15
+  PROPERTIES PASS_REGULAR_EXPRESSION "05:01:52N 005:05:38E")
+
+# Check MGRS::Forward improved rounding fix, 2015-07-22
+add_test (NAME GeoConvert16 COMMAND GeoConvert
+  -m -p 3 --input-string "38n 444140.6 3684706.3")
+set_tests_properties (GeoConvert16
+  PROPERTIES PASS_REGULAR_EXPRESSION "38SMB4414060084706300")
+# Check MGRS::Forward digit consistency fix, 2015-07-23
+add_test (NAME GeoConvert17 COMMAND GeoConvert
+  -m -p 3 --input-string "38n 500000 63.811")
+add_test (NAME GeoConvert18 COMMAND GeoConvert
+  -m -p 4 --input-string "38n 500000 63.811")
+set_tests_properties (GeoConvert17
+  PROPERTIES PASS_REGULAR_EXPRESSION "38NNF0000000000063811")
+set_tests_properties (GeoConvert18
+  PROPERTIES PASS_REGULAR_EXPRESSION "38NNF000000000000638110")
+
 add_test (NAME GeodSolve0 COMMAND GeodSolve
   -i -p 0 --input-string "40.6 -73.8 49d01'N 2d33'E")
 set_tests_properties (GeodSolve0 PROPERTIES PASS_REGULAR_EXPRESSION
@@ -163,6 +199,13 @@ add_test (NAME GeodSolve24 COMMAND GeodSolve
 set_tests_properties (GeodSolve21 GeodSolve22 GeodSolve23 GeodSolve24
   PROPERTIES PASS_REGULAR_EXPRESSION "-39\\.[0-9]* 105\\.[0-9]* -170\\.[0-9]*")
 
+# Check fix for inaccurate rounding in DMS::Decode, e.g., verify that
+# 7:33:36 = 7.56; fixed on 2015-06-11.
+add_test (NAME GeodSolve25 COMMAND GeodSolve
+  -p 6 --input-string "0 0 7:33:36-7.56 10001965")
+set_tests_properties (GeodSolve25 PROPERTIES PASS_REGULAR_EXPRESSION
+  "89\\.9[0-9]* 0\\.00000000000 0\\.00000000000")
+
 # Check fix for pole-encircling bug found 2011-03-16
 add_test (NAME Planimeter0 COMMAND Planimeter
   --input-string "89 0;89 90;89 180;89 270")
@@ -280,7 +323,7 @@ set_tests_properties (TransverseMercatorProj1 PROPERTIES PASS_REGULAR_EXPRESSION
   "(90\\.0+ 0\\.0+ 0\\.0+|(90\\.0+|89\\.99999999999[0-9]+) -?180\\.0+ -?180\\.0+) (1\\.0000+|0\\.9999+)")
 
 # Test fix to bad handling of pole by RhumbSolve -i
-# Reported  2015-02-24 by Thomas Murray <thomas.murray56 at gmail.com>;
+# Reported  2015-02-24 by Thomas Murray <thomas.murray56 at gmail.com>
 add_test (NAME RhumbSolve0 COMMAND RhumbSolve
   -p 3 -i --input-string "0 0 90 0")
 add_test (NAME RhumbSolve1 COMMAND RhumbSolve
@@ -288,6 +331,12 @@ add_test (NAME RhumbSolve1 COMMAND RhumbSolve
 set_tests_properties (RhumbSolve0 RhumbSolve1 PROPERTIES PASS_REGULAR_EXPRESSION
   "^0\\.0+ 10001965\\.729 ")
 
+# Test fix to CassiniSoldner::Forward bug found 2015-06-20
+add_test (NAME GeodesicProj0 COMMAND GeodesicProj
+  -c 0 0 -p 3 --input-string "90 80")
+set_tests_properties (GeodesicProj0 PROPERTIES PASS_REGULAR_EXPRESSION
+  "^-?0\\.0+ [0-9]+\\.[0-9]+ 170\\.0+ ")
+
 if (EXISTS ${GEOGRAPHICLIB_DATA}/geoids/egm96-5.pgm)
   # Check fix for single-cell cache bug found 2010-11-23
   add_test (NAME GeoidEval0 COMMAND GeoidEval
@@ -305,12 +354,13 @@ if (EXISTS ${GEOGRAPHICLIB_DATA}/magnetic/wmm2010.wmm)
     -n wmm2010 -p 10 -r -t 2012.5 --input-string "-80 240 100e3")
   add_test (NAME MagneticField2 COMMAND MagneticField
     -n wmm2010 -p 10 -r -c 2012.5 -80 100e3 --input-string "240")
-  set_tests_properties (MagneticField0 PROPERTIES PASS_REGULAR_EXPRESSION
-    " 5535\\.5249148687 14765\\.3703243050 -50625\\.9305478794 .*\n.* 20\\.4904268023 1\\.0272592716 83\\.5313962281 ")
-  set_tests_properties (MagneticField1 PROPERTIES PASS_REGULAR_EXPRESSION
-    " 5535\\.5249148687 14765\\.3703243050 -50625\\.9305478794 .*\n.* 20\\.4904268023 1\\.0272592716 83\\.5313962281 ")
-  set_tests_properties (MagneticField2 PROPERTIES PASS_REGULAR_EXPRESSION
-    " 5535\\.5249148687 14765\\.3703243050 -50625\\.9305478794 .*\n.* 20\\.4904268023 1\\.0272592716 83\\.5313962281 ")
+  # In third number, allow a final digit 5 (instead of correct 4) to
+  # accommodate Visual Studio 12 and 14.  The relative difference is
+  # "only" 2e-15; on the other hand, this might be a lurking bug in
+  # these compilers.  (Visual Studio 10 and 11 are OK.)
+  set_tests_properties (MagneticField0 MagneticField1 MagneticField2
+    PROPERTIES PASS_REGULAR_EXPRESSION
+    " 5535\\.5249148687 14765\\.3703243050 -50625\\.930547879[45] .*\n.* 20\\.4904268023 1\\.0272592716 83\\.5313962281 ")
 endif ()
 
 if (EXISTS ${GEOGRAPHICLIB_DATA}/magnetic/emm2015.wmm)
@@ -349,3 +399,11 @@ if (EXISTS ${GEOGRAPHICLIB_DATA}/gravity/egm2008.egm)
   set_tests_properties (Gravity2 PROPERTIES PASS_REGULAR_EXPRESSION
     "7\\.404 -6\\.168 7\\.616")
 endif ()
+
+if (EXISTS ${GEOGRAPHICLIB_DATA}/gravity/grs80.egm)
+  # Check close to zero gravity in geostationary orbit
+  add_test (NAME Gravity3 COMMAND Gravity
+    -p 3 -n grs80 --input-string "0 123 35786e3")
+  set_tests_properties (Gravity3 PROPERTIES PASS_REGULAR_EXPRESSION
+    "^-?0\\.000 -?0\\.000 -?0.000")
+endif ()
diff --git a/windows/Geographic-vc10.vcxproj b/windows/Geographic-vc10.vcxproj
index eda7fc7..ff3874f 100644
--- a/windows/Geographic-vc10.vcxproj
+++ b/windows/Geographic-vc10.vcxproj
@@ -148,6 +148,7 @@
     <ClInclude Include="../include/GeographicLib/DMS.hpp" />
     <ClInclude Include="../include/GeographicLib/Ellipsoid.hpp" />
     <ClInclude Include="../include/GeographicLib/EllipticFunction.hpp" />
+    <ClInclude Include="../include/GeographicLib/GARS.hpp" />
     <ClInclude Include="../include/GeographicLib/GeoCoords.hpp" />
     <ClInclude Include="../include/GeographicLib/Geocentric.hpp" />
     <ClInclude Include="../include/GeographicLib/Geodesic.hpp" />
@@ -155,6 +156,7 @@
     <ClInclude Include="../include/GeographicLib/GeodesicLine.hpp" />
     <ClInclude Include="../include/GeographicLib/GeodesicLineExact.hpp" />
     <ClInclude Include="../include/GeographicLib/Geohash.hpp" />
+    <ClInclude Include="../include/GeographicLib/Georef.hpp" />
     <ClInclude Include="../include/GeographicLib/Geoid.hpp" />
     <ClInclude Include="../include/GeographicLib/Gnomonic.hpp" />
     <ClInclude Include="../include/GeographicLib/GravityCircle.hpp" />
@@ -189,6 +191,7 @@
     <ClCompile Include="../src/DMS.cpp" />
     <ClCompile Include="../src/Ellipsoid.cpp" />
     <ClCompile Include="../src/EllipticFunction.cpp" />
+    <ClCompile Include="../src/GARS.cpp" />
     <ClCompile Include="../src/GeoCoords.cpp" />
     <ClCompile Include="../src/Geocentric.cpp" />
     <ClCompile Include="../src/Geodesic.cpp" />
@@ -198,6 +201,7 @@
     <ClCompile Include="../src/GeodesicLineExact.cpp" />
     <ClCompile Include="../src/Geohash.cpp" />
     <ClCompile Include="../src/Geoid.cpp" />
+    <ClCompile Include="../src/Georef.cpp" />
     <ClCompile Include="../src/Gnomonic.cpp" />
     <ClCompile Include="../src/GravityCircle.cpp" />
     <ClCompile Include="../src/GravityModel.cpp" />
@@ -222,4 +226,3 @@
   <ImportGroup Label="ExtensionTargets">
   </ImportGroup>
 </Project>
-
diff --git a/windows/Geographic-vc10x.vcxproj b/windows/Geographic-vc10x.vcxproj
index 19a9682..0f52a9a 100644
--- a/windows/Geographic-vc10x.vcxproj
+++ b/windows/Geographic-vc10x.vcxproj
@@ -84,6 +84,7 @@
     <ClInclude Include="../include/GeographicLib/DMS.hpp" />
     <ClInclude Include="../include/GeographicLib/Ellipsoid.hpp" />
     <ClInclude Include="../include/GeographicLib/EllipticFunction.hpp" />
+    <ClInclude Include="../include/GeographicLib/GARS.hpp" />
     <ClInclude Include="../include/GeographicLib/GeoCoords.hpp" />
     <ClInclude Include="../include/GeographicLib/Geocentric.hpp" />
     <ClInclude Include="../include/GeographicLib/Geodesic.hpp" />
@@ -92,6 +93,7 @@
     <ClInclude Include="../include/GeographicLib/GeodesicLineExact.hpp" />
     <ClInclude Include="../include/GeographicLib/Geohash.hpp" />
     <ClInclude Include="../include/GeographicLib/Geoid.hpp" />
+    <ClInclude Include="../include/GeographicLib/Georef.hpp" />
     <ClInclude Include="../include/GeographicLib/Gnomonic.hpp" />
     <ClInclude Include="../include/GeographicLib/GravityCircle.hpp" />
     <ClInclude Include="../include/GeographicLib/GravityModel.hpp" />
@@ -125,6 +127,7 @@
     <ClCompile Include="../src/DMS.cpp" />
     <ClCompile Include="../src/Ellipsoid.cpp" />
     <ClCompile Include="../src/EllipticFunction.cpp" />
+    <ClCompile Include="../src/GARS.cpp" />
     <ClCompile Include="../src/GeoCoords.cpp" />
     <ClCompile Include="../src/Geocentric.cpp" />
     <ClCompile Include="../src/Geodesic.cpp" />
@@ -134,6 +137,7 @@
     <ClCompile Include="../src/GeodesicLineExact.cpp" />
     <ClCompile Include="../src/Geohash.cpp" />
     <ClCompile Include="../src/Geoid.cpp" />
+    <ClCompile Include="../src/Georef.cpp" />
     <ClCompile Include="../src/Gnomonic.cpp" />
     <ClCompile Include="../src/GravityCircle.cpp" />
     <ClCompile Include="../src/GravityModel.cpp" />
@@ -158,4 +162,3 @@
   <ImportGroup Label="ExtensionTargets">
   </ImportGroup>
 </Project>
-
diff --git a/windows/Geographic-vc13n.vcxproj b/windows/Geographic-vc13n.vcxproj
index f048a58..cffeda0 100644
--- a/windows/Geographic-vc13n.vcxproj
+++ b/windows/Geographic-vc13n.vcxproj
@@ -152,6 +152,7 @@
     <ClInclude Include="../include/GeographicLib/DMS.hpp" />
     <ClInclude Include="../include/GeographicLib/Ellipsoid.hpp" />
     <ClInclude Include="../include/GeographicLib/EllipticFunction.hpp" />
+    <ClInclude Include="../include/GeographicLib/GARS.hpp" />
     <ClInclude Include="../include/GeographicLib/GeoCoords.hpp" />
     <ClInclude Include="../include/GeographicLib/Geocentric.hpp" />
     <ClInclude Include="../include/GeographicLib/Geodesic.hpp" />
@@ -160,6 +161,7 @@
     <ClInclude Include="../include/GeographicLib/GeodesicLineExact.hpp" />
     <ClInclude Include="../include/GeographicLib/Geohash.hpp" />
     <ClInclude Include="../include/GeographicLib/Geoid.hpp" />
+    <ClInclude Include="../include/GeographicLib/Georef.hpp" />
     <ClInclude Include="../include/GeographicLib/Gnomonic.hpp" />
     <ClInclude Include="../include/GeographicLib/GravityCircle.hpp" />
     <ClInclude Include="../include/GeographicLib/GravityModel.hpp" />
@@ -193,6 +195,7 @@
     <ClCompile Include="../src/DMS.cpp" />
     <ClCompile Include="../src/Ellipsoid.cpp" />
     <ClCompile Include="../src/EllipticFunction.cpp" />
+    <ClCompile Include="../src/GARS.cpp" />
     <ClCompile Include="../src/GeoCoords.cpp" />
     <ClCompile Include="../src/Geocentric.cpp" />
     <ClCompile Include="../src/Geodesic.cpp" />
@@ -202,6 +205,7 @@
     <ClCompile Include="../src/GeodesicLineExact.cpp" />
     <ClCompile Include="../src/Geohash.cpp" />
     <ClCompile Include="../src/Geoid.cpp" />
+    <ClCompile Include="../src/Georef.cpp" />
     <ClCompile Include="../src/Gnomonic.cpp" />
     <ClCompile Include="../src/GravityCircle.cpp" />
     <ClCompile Include="../src/GravityModel.cpp" />
diff --git a/windows/Geographic-vc9.vcproj b/windows/Geographic-vc9.vcproj
index 6d03e0a..e9579e6 100644
--- a/windows/Geographic-vc9.vcproj
+++ b/windows/Geographic-vc9.vcproj
@@ -296,6 +296,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\src\GARS.cpp"
+				>
+			</File>
+			<File
 				RelativePath="..\src\GeoCoords.cpp"
 				>
 			</File>
@@ -332,6 +336,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\src\Georef.cpp"
+				>
+			</File>
+			<File
 				RelativePath="..\src\Gnomonic.cpp"
 				>
 			</File>
@@ -450,6 +458,10 @@
 				>
 			</File>
 			<File
+				RelativePath="../include/GeographicLib/GARS.hpp"
+				>
+			</File>
+			<File
 				RelativePath="../include/GeographicLib/GeoCoords.hpp"
 				>
 			</File>
@@ -482,6 +494,10 @@
 				>
 			</File>
 			<File
+				RelativePath="../include/GeographicLib/Georef.hpp"
+				>
+			</File>
+			<File
 				RelativePath="../include/GeographicLib/Gnomonic.hpp"
 				>
 			</File>
diff --git a/windows/NETGeographic-vc10.vcxproj b/windows/NETGeographic-vc10.vcxproj
index 14a9b37..6b569e0 100644
--- a/windows/NETGeographic-vc10.vcxproj
+++ b/windows/NETGeographic-vc10.vcxproj
@@ -177,6 +177,8 @@
     <ClInclude Include="../dotnet/NETGeographicLib/TransverseMercator.h" />
     <ClInclude Include="../dotnet/NETGeographicLib/TransverseMercatorExact.h" />
     <ClInclude Include="../dotnet/NETGeographicLib/UTMUPS.h" />
+    <ClInclude Include="..\dotnet\NETGeographicLib\GARS.h" />
+    <ClInclude Include="..\dotnet\NETGeographicLib\Georef.h" />
     <ClInclude Include="..\dotnet\NETGeographicLib\Rhumb.h" />
   </ItemGroup>
   <ItemGroup>
@@ -223,6 +225,8 @@
       <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
       <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
     </ClCompile>
+    <ClCompile Include="..\dotnet\NETGeographicLib\GARS.cpp" />
+    <ClCompile Include="..\dotnet\NETGeographicLib\Georef.cpp" />
     <ClCompile Include="..\dotnet\NETGeographicLib\Rhumb.cpp" />
   </ItemGroup>
   <ItemGroup>
diff --git a/windows/NETGeographic-vc13.vcxproj b/windows/NETGeographic-vc13.vcxproj
index f6392e7..f39afb9 100644
--- a/windows/NETGeographic-vc13.vcxproj
+++ b/windows/NETGeographic-vc13.vcxproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup Label="ProjectConfigurations">
     <ProjectConfiguration Include="Debug|Win32">
@@ -181,6 +181,8 @@
     <ClInclude Include="../dotnet/NETGeographicLib/TransverseMercator.h" />
     <ClInclude Include="../dotnet/NETGeographicLib/TransverseMercatorExact.h" />
     <ClInclude Include="../dotnet/NETGeographicLib/UTMUPS.h" />
+    <ClInclude Include="..\dotnet\NETGeographicLib\GARS.h" />
+    <ClInclude Include="..\dotnet\NETGeographicLib\Georef.h" />
     <ClInclude Include="..\dotnet\NETGeographicLib\Rhumb.h" />
   </ItemGroup>
   <ItemGroup>
@@ -227,6 +229,8 @@
       <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
       <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
     </ClCompile>
+    <ClCompile Include="..\dotnet\NETGeographicLib\GARS.cpp" />
+    <ClCompile Include="..\dotnet\NETGeographicLib\Georef.cpp" />
     <ClCompile Include="..\dotnet\NETGeographicLib\Rhumb.cpp" />
   </ItemGroup>
   <ItemGroup>
@@ -240,4 +244,4 @@
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
   </ImportGroup>
-</Project>
\ No newline at end of file
+</Project>

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/geographiclib.git



More information about the Pkg-grass-devel mailing list