18   const char* 
const MGRS::utmcols_[] = { 
"ABCDEFGH", 
"JKLMNPQR", 
"STUVWXYZ" };
 
   21     { 
"JKLPQRSTUXYZ", 
"ABCFGHJKLPQR", 
"RSTUXYZ", 
"ABCFGHJ" };
 
   23     { 
"ABCDEFGHJKLMNPQRSTUVWXYZ", 
"ABCDEFGHJKLMNP" };
 
   29     { minupsSind_, minupsNind_, minutmcol_, minutmcol_ };
 
   31     { maxupsSind_, maxupsNind_, maxutmcol_, maxutmcol_ };
 
   33     { minupsSind_, minupsNind_,
 
   34       minutmSrow_, minutmSrow_ - (maxutmSrow_ - minutmNrow_) };
 
   36     { maxupsSind_, maxupsNind_,
 
   37       maxutmNrow_ + (maxutmSrow_ - minutmNrow_), maxutmNrow_ };
 
   40                      int prec, std::string& mgrs) {
 
   49     bool utmp = zone != 0;
 
   50     CheckCoords(utmp, northp, 
x, 
y);
 
   53     if (!(prec >= -1 && prec <= maxprec_))
 
   59     char mgrs1[2 + 3 + 2 * maxprec_];
 
   63       mlen = 
z + 3 + 2 * prec;
 
   65       mgrs1[0] = digits_[ zone / base_ ];
 
   66       mgrs1[1] = digits_[ zone % base_ ];
 
   72     GEOGRAPHICLIB_STATIC_ASSERT(numeric_limits<long long>::digits >= 44,
 
   73                                 "long long not wide enough to store 10e12");
 
   75       ix = (
long long)(
floor(
x * mult_)),
 
   76       iy = (
long long)(
floor(
y * mult_)),
 
   77       m = (
long long)(mult_) * (
long long)(tile_);
 
   78     int xh = 
int(ix / 
m), yh = 
int(iy / 
m);
 
   82         iband = 
abs(
lat) > angeps ? LatitudeBand(
lat) : (northp ? 0 : -1),
 
   83         icol = xh - minutmcol_,
 
   84         irow = UTMRow(iband, icol, yh % utmrowperiod_);
 
   85       if (irow != yh - (northp ? minutmNrow_ : maxutmSrow_))
 
   87                             + 
" is inconsistent with UTM coordinates");
 
   88       mgrs1[
z++] = latband_[10 + iband];
 
   89       mgrs1[
z++] = utmcols_[zone1 % 3][icol];
 
   90       mgrs1[
z++] = utmrow_[(yh + (zone1 & 1 ? utmevenrowshift_ : 0))
 
   93       bool eastp = xh >= upseasting_;
 
   94       int iband = (northp ? 2 : 0) + (eastp ? 1 : 0);
 
   95       mgrs1[
z++] = upsband_[iband];
 
   96       mgrs1[
z++] = upscols_[iband][xh - (eastp ? upseasting_ :
 
   97                                          (northp ? minupsNind_ :
 
   99       mgrs1[
z++] = upsrows_[northp][yh - (northp ? minupsNind_ : minupsSind_)];
 
  102       ix -= 
m * xh; iy -= 
m * yh;
 
  103       long long d = (
long long)(
pow(
real(base_), maxprec_ - prec));
 
  105       for (
int c = prec; 
c--;) {
 
  106         mgrs1[
z + 
c       ] = digits_[ix % base_]; ix /= base_;
 
  107         mgrs1[
z + 
c + prec] = digits_[iy % base_]; iy /= base_;
 
  111     copy(mgrs1, mgrs1 + mlen, mgrs.begin());
 
  115                      int prec, std::string& mgrs) {
 
  119       real ys = northp ? 
y : 
y - utmNshift_;
 
  133           latp = 
real(0.901) * ys + (ys > 0 ? 1 : -1) * 
real(0.135),
 
  136           late = 
real(0.902) * ys * (1 - 
real(1.85
e-6) * ys * ys);
 
  137         if (LatitudeBand(latp) == LatitudeBand(late))
 
  151                      int& prec, 
bool centerp) {
 
  156         toupper(mgrs[0]) == 
'I' &&
 
  157         toupper(mgrs[1]) == 
'N' &&
 
  158         toupper(mgrs[2]) == 
'V') {
 
  170       zone1 = 10 * zone1 + 
i;
 
  177                           + mgrs.substr(0, 
p));
 
  181     int zonem1 = zone1 - 1;
 
  182     const char* 
band = utmp ? latband_ : upsband_;
 
  186                           + (utmp ? 
"UTM" : 
"UPS") + 
" set " + 
band);
 
  187     bool northp1 = iband >= (utmp ? 10 : 2);
 
  190       real deg = 
real(utmNshift_) / (90 * tile_);
 
  195         x = ((zone == 31 && iband == 17) ? 4 : 5) * tile_;
 
  198           + (northp ? 0 : utmNshift_);
 
  201         x = ((iband & 1 ? 1 : -1) * 
floor(4 * deg + 
real(0.5))
 
  202              + upseasting_) * tile_;
 
  204         y = upseasting_ * tile_;
 
  208     } 
else if (
len - 
p < 2)
 
  210     const char* 
col = utmp ? utmcols_[zonem1 % 3] : upscols_[iband];
 
  211     const char* 
row = utmp ? utmrow_ : upsrows_[northp1];
 
  216                           + (utmp ? 
"zone " + mgrs.substr(0, 
p-2) :
 
  227         irow = (irow + utmrowperiod_ - utmevenrowshift_) % utmrowperiod_;
 
  229       irow = UTMRow(iband, icol, irow);
 
  230       if (irow == maxutmSrow_)
 
  232                             + 
" not in zone/band " + mgrs.substr(0, 
p-2));
 
  234       irow = northp1 ? irow : irow + 100;
 
  235       icol = icol + minutmcol_;
 
  237       bool eastp = iband & 1;
 
  238       icol += eastp ? upseasting_ : (northp1 ? minupsNind_ : minupsSind_);
 
  239       irow += northp1 ? minupsNind_ : minupsSind_;
 
  241     int prec1 = (
len - 
p)/2;
 
  246     for (
int i = 0; 
i < prec1; ++
i) {
 
  251       if (ix < 0 || iy < 0)
 
  252         throw GeographicErr(
"Encountered a non-digit in " + mgrs.substr(
p));
 
  253       x1 = base_ * 
x1 + ix;
 
  254       y1 = base_ * 
y1 + iy;
 
  258         throw GeographicErr(
"Encountered a non-digit in " + mgrs.substr(
p));
 
  263     if (prec1 > maxprec_)
 
  265                           + 
" digits in " + mgrs.substr(
p));
 
  267       unit *= 2; 
x1 = 2 * 
x1 + 1; 
y1 = 2 * 
y1 + 1;
 
  271     x = (tile_ * 
x1) / unit;
 
  272     y = (tile_ * 
y1) / unit;
 
  290       ind = (utmp ? 2 : 0) + (northp ? 1 : 0);
 
  291     if (! (ix >= mineasting_[
ind] && ix < maxeasting_[
ind]) ) {
 
  292       if (ix == maxeasting_[
ind] && 
x == maxeasting_[
ind] * tile_)
 
  297                             + (utmp ? 
"UTM" : 
"UPS") + 
" range for " 
  298                             + (northp ? 
"N" : 
"S" ) + 
" hemisphere [" 
  304     if (! (iy >= minnorthing_[
ind] && iy < maxnorthing_[
ind]) ) {
 
  305       if (iy == maxnorthing_[
ind] && 
y == maxnorthing_[
ind] * tile_)
 
  310                             + (utmp ? 
"UTM" : 
"UPS") + 
" range for " 
  311                             + (northp ? 
"N" : 
"S" ) + 
" hemisphere [" 
  320       if (northp && iy < minutmNrow_) {
 
  323       } 
else if (!northp && iy >= maxutmSrow_) {
 
  324         if (
y == maxutmSrow_ * tile_)
 
  345     bool northp = iband >= 0;
 
  369       minrow = iband > -10 ?
 
  373       baserow = (minrow + maxrow) / 2 - utmrowperiod_ / 2;
 
  377     irow = (irow - baserow + maxutmSrow_) % utmrowperiod_ + baserow;
 
  378     if (!( irow >= minrow && irow <= maxrow )) {
 
  387         sband = iband >= 0 ? iband : -iband - 1,
 
  389         srow = irow >= 0 ? irow : -irow - 1,
 
  391         scol = icol < 4 ? icol : -icol + 7;
 
  394       if ( ! ( (srow == 70 && sband == 8 && scol >= 2) ||
 
  395                (srow == 71 && sband == 7 && scol <= 2) ||
 
  396                (srow == 79 && sband == 9 && scol >= 1) ||
 
  397                (srow == 80 && sband == 8 && scol <= 1) ) )
 
  407       throw GeographicErr(
"MGRS::Check: equator coverage failure");
 
  410       throw GeographicErr(
"MGRS::Check: UTM doesn't reach latitude = 84");
 
  413       throw GeographicErr(
"MGRS::Check: UTM doesn't reach latitude = -80");
 
  416       throw GeographicErr(
"MGRS::Check: Norway exception creates a gap");
 
  419       throw GeographicErr(
"MGRS::Check: Svalbard exception creates a gap");
 
  423         GeographicErr(
"MGRS::Check: North UPS doesn't reach latitude = 84");
 
  427         GeographicErr(
"MGRS::Check: South UPS doesn't reach latitude = -80");
 
  430     const short tab[] = {
 
  446       7, 5, 70,   7, 7, 70,   7, 7, 71,   7, 9, 71, 
 
  447       8, 5, 71,   8, 6, 71,   8, 6, 72,   8, 9, 72, 
 
  448       8, 5, 79,   8, 8, 79,   8, 8, 80,   8, 9, 80, 
 
  449       9, 5, 80,   9, 7, 80,   9, 7, 81,   9, 9, 81, 
 
  452     const int bandchecks = 
sizeof(tab) / (3 * 
sizeof(
short));
 
  453     for (
int i = 0; 
i < bandchecks; ++
i) {
 
  455       if (!( LatitudeBand(
lat) == tab[3*
i+0] ))