[mapcode] 32/56: Version 1.81 - under construction

Stefan Fritsch sf at moszumanska.debian.org
Wed Nov 2 23:27:29 UTC 2016


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

sf pushed a commit to annotated tag v2.0.2
in repository mapcode.

commit 8dd71e851cc1c0da786bec589ef37c57780fe3b4
Author: Rijn Buve <rijn at buve.nl>
Date:   Wed Jul 1 15:58:58 2015 +0200

    Version 1.81 - under construction
---
 README.md             |    6 +
 mapcode_library_c.doc |  Bin 72704 -> 95232 bytes
 mapcodelib/basics.h   |  609 +++++++-----
 mapcodelib/mapcoder.c | 2569 ++++++++++++++++++-------------------------------
 mapcodelib/mapcoder.h |  100 +-
 utility/mapcode.cpp   |    8 +-
 6 files changed, 1412 insertions(+), 1880 deletions(-)

diff --git a/README.md b/README.md
index 48d6fde..9b82e05 100644
--- a/README.md
+++ b/README.md
@@ -46,6 +46,12 @@ decode Mapcodes.
 
 ## Release Notes
 
+* 2.0
+
+    Support for up to 8 character extensions (10 micron accuracy).
+    
+    Fixes to the data rectangles for ISO proposal, see Word document for details.
+
 * 1.50.1
 
     Bug fix for state IN-DD (in India).
diff --git a/mapcode_library_c.doc b/mapcode_library_c.doc
index 4000c9d..7eed7b0 100644
Binary files a/mapcode_library_c.doc and b/mapcode_library_c.doc differ
diff --git a/mapcodelib/basics.h b/mapcodelib/basics.h
index 8f6d937..015a9e8 100644
--- a/mapcodelib/basics.h
+++ b/mapcodelib/basics.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014-2015 Stichting Mapcode Foundation (http://www.mapcode.com)
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
@@ -16,11 +16,11 @@
 
 #define UWORD unsigned short int // 2-byte unsigned integer
 
-#define mapcode_cversion "1.61"
+#define mapcode_cversion "1.81"
 #define MAXWIDE 10
 #define BASEX 31
 #define MAXFITLONG 6
-#define XSIDE3 168 
+#define XSIDE3 168
 #define YSIDE3 176
 
 #define ALIASES "2UK=2UT,2CG=2CT,1GU=GUM,1UM=UMI,1VI=VIR,1PR=PRI,1AS=ASM,1MP=MNP,4CX=CXR,4CC=CCK,4NF=NFK,4HM=HMD,COL=5CL,5ME=5MX,MEX=5MX,5TM=TAM,5AG=AGU,5BC=BCN,5BS=BCS,5CM=CAM,5CS=CHP,5CH=CHH,5CO=COA,5DF=DIF,5DG=DUR,5GT=GUA,5GR=GRO,5HG=HID,5JA=JAL,5MI=MIC,5MO=MOR,5NA=NAY,5NL=NLE,5OA=OAX,5PB=PUE,5QE=QUE,5QR=ROO,5SL=SLP,5SI=SIN,5SO=SON,5TB=TAB,5TL=TLA,5VE=VER,5YU=YUC,5ZA=ZAC,811=8BJ,812=8TJ,813=8HE,814=8SX,815=8NM,821=8LN,822=8JL,823=8HL,831=8SH,832=8JS,833=8ZJ,834=8AH,835=8FJ,836=8JX,837 [...]
@@ -168,63 +168,63 @@ static const char encode_chars[34] = {
 
 
 static const UWORD data_start[MAX_CCODE+1] = {
-0, 3, 6, 9, 13, 16, 18, 19, 30, 31, 
-33, 35, 37, 42, 44, 47, 51, 54, 56, 58, 
-60, 62, 64, 68, 71, 79, 81, 116, 121, 131, 
-133, 135, 138, 143, 155, 159, 165, 167, 169, 173, 
-176, 183, 185, 187, 189, 193, 195, 202, 208, 212, 
-216, 219, 221, 223, 250, 252, 259, 261, 266, 284, 
-288, 292, 296, 298, 303, 311, 315, 325, 327, 332, 
-336, 342, 356, 360, 365, 369, 385, 391, 396, 404, 
-412, 428, 432, 436, 443, 454, 491, 495, 521, 527, 
-545, 557, 593, 659, 694, 733, 745, 754, 782, 798, 
-832, 848, 882, 918, 932, 956, 967, 1022, 1080, 1094, 
-1155, 1179, 1208, 1276, 1353, 1405, 1484, 1569, 1621, 1696, 
-1772, 1833, 1875, 1900, 1948, 1991, 2036, 2097, 2183, 2270, 
-2319, 2382, 2467, 2558, 2643, 2702, 2815, 2912, 3004, 3088, 
-3186, 3248, 3350, 3416, 3511, 3602, 3688, 3776, 3866, 3973, 
-4119, 4221, 4325, 4356, 4393, 4468, 4504, 4538, 4574, 4626, 
-4690, 4741, 4756, 4791, 4931, 5017, 5067, 5143, 5168, 5236, 
-5293, 5328, 5408, 5459, 5530, 5623, 5658, 5736, 5795, 5861, 
-5918, 5971, 6028, 6065, 6156, 6285, 6335, 6365, 6417, 6513, 
-6546, 6627, 6675, 6755, 6798, 6892, 6926, 6971, 7078, 7083, 
-7155, 7199, 7283, 7323, 7347, 7404, 7490, 7564, 7603, 7690, 
-7766, 7874, 7952, 8026, 8096, 8153, 8235, 8317, 8376, 8403, 
-8441, 8495, 8571, 8681, 8761, 8825, 8882, 8936, 9014, 9085, 
-9171, 9221, 9282, 9426, 9430, 9435, 9440, 9445, 9451, 9456, 
-9464, 9472, 9483, 9491, 9506, 9515, 9526, 9559, 9568, 9576, 
-9591, 9601, 9611, 9619, 9627, 9643, 9651, 9661, 9672, 9682, 
-9692, 9701, 9710, 9721, 9762, 9803, 9821, 9918, 10069, 10160, 
-10242, 10437, 10440, 10443, 10446, 10456, 10461, 10464, 10476, 10489, 
-10500, 10516, 10525, 10531, 10565, 10593, 10612, 10680, 10772, 10787, 
-10791, 10827, 10914, 10925, 10943, 10960, 11024, 11056, 11097, 11117, 
-11222, 11302, 11366, 11420, 11479, 11535, 11595, 11601, 11643, 11647, 
-11650, 11660, 11675, 11686, 11724, 11787, 11833, 11838, 11845, 11850, 
-11869, 11879, 11886, 11894, 11908, 11924, 11931, 11939, 11947, 11995, 
-12004, 12015, 12065, 12076, 12086, 12105, 12121, 12134, 12146, 12165, 
-12199, 12208, 12220, 12232, 12236, 12242, 12248, 12260, 12271, 12280, 
-12286, 12300, 12318, 12329, 12371, 12422, 12472, 12528, 12541, 12554, 
-12617, 12677, 12738, 12803, 12874, 12939, 13008, 13083, 13150, 13229, 
-13303, 13317, 13332, 13377, 13390, 13418, 13432, 13445, 13461, 13477, 
-13489, 13531, 13543, 13554, 13589, 13604, 13616, 13633, 13641, 13679, 
-13692, 13707, 13827, 13873, 13917, 13957, 13981, 14022, 14061, 14081, 
-14097, 14115, 14127, 14141, 14149, 14160, 14177, 14190, 14245, 14246, 
-14247, 14248, 14287, 14293, 14298, 14303, 14308, 14314, 14321, 14327, 
-14336, 14342, 14350, 14356, 14363, 14372, 14380, 14389, 14401, 14410, 
-14418, 14429, 14440, 14449, 14459, 14466, 14516, 14550, 14559, 14571, 
-14582, 14621, 14632, 14646, 14663, 14675, 14688, 14702, 14717, 14730, 
-14751, 14759, 14778, 14787, 14799, 14810, 14824, 14839, 14852, 14866, 
-14879, 14893, 14908, 14926, 14946, 14958, 14978, 14991, 15006, 15020, 
-15038, 15054, 15068, 15081, 15098, 15118, 15135, 15153, 15168, 15182, 
-15198, 15209, 15225, 15238, 15253, 15268, 15314, 15328, 15337, 15347, 
-15360, 15374, 15385, 15398, 15414, 15429, 15430, 15457, 15463, 15471, 
-15477, 15493, 15530, 15547, 15571, 15594, 15611, 15631, 15657, 15683, 
-15702, 15719, 15772, 15813, 15835, 15862, 15882, 15903, 15921, 15951, 
-15977, 15997, 16018, 16036, 16054, 16073, 16089, 16105, 16133, 16159, 
-16166, 16168, 16169, 16201
+0, 3, 6, 10, 14, 17, 19, 20, 31, 32,
+34, 36, 38, 43, 45, 48, 52, 59, 63, 65,
+67, 71, 73, 81, 87, 95, 97, 132, 139, 149,
+151, 153, 156, 161, 173, 181, 188, 190, 192, 197,
+200, 207, 212, 214, 216, 220, 222, 229, 235, 239,
+243, 246, 250, 252, 281, 283, 290, 292, 297, 317,
+325, 329, 333, 335, 340, 348, 353, 364, 368, 373,
+377, 386, 400, 404, 409, 413, 429, 435, 440, 448,
+456, 472, 476, 480, 487, 498, 535, 539, 565, 571,
+589, 601, 637, 703, 738, 777, 789, 798, 826, 842,
+876, 892, 926, 962, 991, 1015, 1026, 1081, 1139, 1153,
+1215, 1239, 1268, 1336, 1414, 1467, 1546, 1631, 1683, 1758,
+1834, 1895, 1937, 1962, 2010, 2053, 2098, 2159, 2245, 2332,
+2383, 2446, 2531, 2622, 2707, 2766, 2881, 2984, 3077, 3161,
+3259, 3321, 3425, 3491, 3586, 3682, 3768, 3856, 3946, 4053,
+4199, 4301, 4405, 4436, 4473, 4550, 4586, 4620, 4656, 4708,
+4772, 4823, 4838, 4873, 5020, 5106, 5156, 5232, 5257, 5325,
+5382, 5417, 5499, 5550, 5623, 5716, 5751, 5829, 5888, 5954,
+6011, 6064, 6121, 6158, 6249, 6380, 6430, 6460, 6512, 6608,
+6641, 6722, 6770, 6850, 6893, 6987, 7021, 7066, 7173, 7177,
+7249, 7293, 7379, 7419, 7446, 7503, 7589, 7663, 7702, 7789,
+7865, 7973, 8051, 8125, 8195, 8252, 8334, 8416, 8475, 8502,
+8540, 8594, 8670, 8783, 8863, 8927, 8984, 9038, 9118, 9189,
+9275, 9325, 9389, 9533, 9537, 9542, 9547, 9552, 9558, 9563,
+9571, 9579, 9590, 9598, 9613, 9622, 9633, 9666, 9675, 9683,
+9698, 9708, 9718, 9726, 9734, 9750, 9758, 9768, 9779, 9789,
+9799, 9808, 9817, 9828, 9869, 9910, 9928, 10025, 10176, 10267,
+10349, 10544, 10547, 10550, 10553, 10563, 10568, 10571, 10583, 10596,
+10607, 10623, 10632, 10638, 10672, 10700, 10719, 10787, 10879, 10894,
+10898, 10934, 11021, 11032, 11050, 11067, 11131, 11163, 11204, 11224,
+11329, 11409, 11473, 11527, 11586, 11642, 11702, 11709, 11751, 11755,
+11758, 11768, 11783, 11794, 11832, 11895, 11941, 11946, 11953, 11958,
+11977, 11987, 11994, 12002, 12016, 12032, 12039, 12047, 12056, 12104,
+12113, 12124, 12174, 12185, 12195, 12214, 12230, 12243, 12255, 12274,
+12308, 12317, 12329, 12341, 12345, 12351, 12357, 12369, 12380, 12389,
+12395, 12409, 12429, 12440, 12482, 12533, 12583, 12639, 12652, 12665,
+12728, 12788, 12849, 12914, 12985, 13050, 13119, 13194, 13262, 13341,
+13418, 13432, 13447, 13492, 13505, 13533, 13547, 13560, 13576, 13592,
+13604, 13646, 13658, 13669, 13704, 13719, 13731, 13748, 13756, 13794,
+13807, 13822, 13942, 13988, 14032, 14072, 14096, 14137, 14176, 14196,
+14212, 14230, 14242, 14256, 14264, 14275, 14292, 14305, 14360, 14361,
+14362, 14363, 14403, 14409, 14414, 14419, 14424, 14430, 14437, 14443,
+14452, 14458, 14466, 14472, 14479, 14488, 14496, 14505, 14517, 14526,
+14534, 14545, 14556, 14565, 14575, 14582, 14632, 14666, 14675, 14687,
+14698, 14737, 14748, 14762, 14779, 14791, 14804, 14818, 14833, 14846,
+14867, 14875, 14894, 14903, 14915, 14926, 14940, 14955, 14968, 14982,
+14995, 15009, 15024, 15042, 15062, 15074, 15094, 15107, 15122, 15136,
+15154, 15170, 15184, 15197, 15214, 15234, 15251, 15269, 15284, 15298,
+15314, 15325, 15341, 15354, 15369, 15384, 15430, 15444, 15453, 15463,
+15476, 15490, 15501, 15514, 15530, 15545, 15546, 15573, 15579, 15587,
+15593, 15609, 15646, 15663, 15687, 15710, 15727, 15747, 15773, 15799,
+15818, 15835, 15888, 15929, 15951, 15978, 15998, 16019, 16037, 16068,
+16094, 16114, 16135, 16153, 16171, 16190, 16206, 16222, 16276, 16302,
+16309, 16311, 16312, 16344
 };
 
-#define NR_RECS 16201
+#define NR_RECS 16344
 #define WORST_RECS_PER_CCODE 195 // 8 Argentina @43
 
 typedef struct { long minx; long miny; long maxx; long maxy; unsigned long flags; } mminforec;
@@ -238,6 +238,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {-5200000, 41310000, 9600000, 53557000, 0x0010216},
 {7404110, 43723932, 7444472, 43752762, 0x003021c},
 {-5384925, 36107682, -5321499, 36159576, 0x001000b},
+{-5734540, 35987080, -5161660, 36478120, 0x001888c},
 {-6703000, 35867000, -3426000, 38475972, 0x0a63291},
 {-5384925, 36107682, -5321499, 36159576, 0x003021c},
 {-172537866, -8601181, -172450415, -8514691, 0x001000a},
@@ -282,26 +283,41 @@ static const mminforec mminfo[NR_RECS+1] = {
 {72307352, -7475728, 72588584, -7181104, 0x001000c},
 {71712684, -5499289, 71993916, -5204665, 0x0b00010},
 {70504498, -7827595, 73185688, -5146405, 0x0a80011},
-{12402340, 43893500, 12517000, 43992200, 0x021000b},
+{12402340, 43893500, 12465083, 43975400, 0x2a7044a},
+{12465083, 43895000, 12517906, 43992200, 0x2a7044a},
+{12486204, 43652480, 13131996, 44143520, 0x0014088},
+{8822749, 43227805, 12487042, 45908995, 0x0010015},
+{9750000, 42200000, 13400000, 44780000, 0x01e188d},
 {5850000, 35450000, 18560000, 55080000, 0x50a0216},
 {12402340, 43893500, 12517000, 43992200, 0x003021c},
 {-2619780, 49416000, -2500000, 49510519, 0x022000a},
 {-2704183, 49374669, -2058391, 49816605, 0x001000c},
+{-10700000, 49122422, 1889648, 60875000, 0x0010216},
+{-2704183, 49374669, -2058391, 49816605, 0x003021c},
 {-63109000, 18167000, -62998270, 18236000, 0x019000a},
 {-63432000, 18147000, -62910000, 18600000, 0x01c000c},
 {-62241268, 16693000, -62178000, 16812970, 0x02b000a},
 {-62330844, 16591156, -62039196, 16885780, 0x001000c},
 {-2246000, 49162000, -2016000, 49206000, 0x010000b},
-{-2275397, 49122080, -1994165, 49318496, 0x001000c},
+{-2275397, 49122422, -1994165, 49318838, 0x001000c},
+{-10700000, 49122422, 1889648, 60875000, 0x0010216},
+{-2275397, 49122080, -1994165, 49318496, 0x003021c},
 {105631382, -10495516, 105718833, -10409026, 0x001000a},
 {105490182, -10633774, 105771414, -10339150, 0x001000c},
-{-176248997, -13305580, -176160585, -13219090, 0x001000a},
+{-176223924, -13250561, -176175640, -13218890, 0x1ad044a},
+{-176226867, -13274200, -176162211, -13250561, 0x1ad044a},
+{-176226867, -13300000, -176167576, -13274200, 0x1ad044a},
+{-176250390, -13321601, -176179814, -13300000, 0x1ad044a},
+{-176225180, -13352287, -176175324, -13321601, 0x1ad044a},
 {-178226240, -14468224, -177908552, -14146320, 0x001000c},
 {-176341581, -13435263, -176023893, -13113359, 0x0b00010},
 {-178252267, -14838976, -176017942, -12664233, 0x0a80211},
 {-64640000, 18411419, -64559180, 18460000, 0x2a7044a},
 {-64717380, 18380572, -64612398, 18418000, 0x2a7044a},
-{-64852000, 18305500, -64267000, 18751000, 0x01b000c},
+{-64852000, 18305500, -64494413, 18547000, 0xc730447},
+{-64494413, 18305500, -64221498, 18593000, 0xbde0447},
+{-64600000, 18593000, -64219959, 18800000, 0xbde0447},
+{-64852000, 18305500, -64210000, 18800000, 0x0970211},
 {9473847, 47053018, 9530152, 47091627, 0x1ad004a},
 {9511847, 47091627, 9568152, 47130236, 0x1ad004a},
 {9503847, 47130236, 9560152, 47168845, 0x1ad004a},
@@ -351,7 +367,9 @@ static const mminforec mminfo[NR_RECS+1] = {
 {-171102112, -11080370, -171051284, -11030511, 0x004010b},
 {-170860000, -14378000, -170540000, -14229000, 0x004010b},
 {-169701004, -14300981, -169403687, -14150000, 0x004010b},
+{-168235531, -14618875, -168086700, -14472514, 0x004010b},
 {-171102200, -14378100, -169403600, -11030500, 0x0ef0011},
+{-171102200, -14732000, -167913000, -11030500, 0x0010216},
 {-159832000, -21273000, -159723500, -21198400, 0x01a000b},
 {-161271860, -10480061, -160797932, -9989021, 0x001000c},
 {-158183360, -9316420, -157709432, -8825380, 0x0b00010},
@@ -389,13 +407,18 @@ static const mminforec mminfo[NR_RECS+1] = {
 {73470755, 4165728, 73557245, 4252218, 0x001000a},
 {73036128, -710000, 73504848, -218960, 0x001000c},
 {72835640, 6523792, 73304360, 7014832, 0x0b10010},
-{72536000, -710000, 73790000, 7136000, 0x1a50011},
+{72500000, 5600000, 73510000, 7135000, 0x004018c},
+{72660000, 1750000, 73790000, 5600000, 0x004018c},
+{72900000, 160000, 73650000, 950000, 0x004010c},
+{73026128, -720000, 73514848, -208960, 0x004010c},
+{71500000, -1000000, 75500000, 7500000, 0x0010216},
 {-5761206, -15983245, -5671833, -15896755, 0x001000a},
 {-14424756, -7996255, -14288000, -7882857, 0x004010b},
 {-5805000, -16040000, -5617000, -15896000, 0x004010b},
 {-12372000, -37183000, -12204000, -37046000, 0x004010b},
 {-12747000, -37459000, -12452000, -37271000, 0x004010b},
-{-14530000, -37510000, -5540000, -7777000, 0x6b20216},
+{-10060000, -40400000, -9800000, -40250000, 0x004010b},
+{-14530000, -40500000, -5540000, -7777000, 0x0010217},
 {14419556, 35855000, 14548000, 35930000, 0x01a000a},
 {14165848, 35753584, 14624152, 36146416, 0x001000c},
 {-61799362, 11987132, -61711911, 12073622, 0x001000a},
@@ -403,6 +426,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {-64989026, 18309620, -64863850, 18373000, 0x016000a},
 {-65068846, 18260000, -64576690, 18422000, 0x004010b},
 {-64940000, 17660000, -64550000, 17820000, 0x004010b},
+{-65087000, 18225000, -64640000, 18422000, 0x0750010},
 {-65093994, 17636170, -64550000, 18426851, 0x0d00211},
 {45200476, -12817650, 45242633, -12727106, 0x2a7044a},
 {45242386, -12819750, 45301886, -12755553, 0x2a7044a},
@@ -411,11 +435,14 @@ static const mminforec mminfo[NR_RECS+1] = {
 {14043750, 78045711, 14328250, 78106820, 0x2a7004a},
 {-9164930, 70754480, -7779602, 71245520, 0x001000c},
 {10400000, 76889405, 22024500, 79500000, 0x0a50011},
-{-9154000, 68600000, 33625000, 80843100, 0x0970212},
+{-9154000, 68600000, 33625000, 80843100, 0x0970012},
 {10000000, 74300000, 33624989, 80843000, 0x0010016},
 {-9165000, 70754400, 33625000, 80843100, 0x003021c},
 {-61257000, 13122000, -61139000, 13183000, 0x016000a},
-{-61486000, 12530000, -61111000, 13390000, 0x02e000c},
+{-61300000, 13100000, -61100000, 13390000, 0x004010b},
+{-61300000, 12770000, -61100000, 13100000, 0x004010b},
+{-61500000, 12530000, -61200000, 12770000, 0x004010b},
+{-61500000, 12530000, -61000000, 13400000, 0x0e00211},
 {73395835, -53117885, 73539024, -53031395, 0x001000b},
 {72580000, -53200000, 73870000, -52900000, 0x06a0010},
 {-59642289, 13077029, -59553877, 13163519, 0x001000a},
@@ -452,6 +479,8 @@ static const mminforec mminfo[NR_RECS+1] = {
 {144534432, 13215480, 145013568, 13706520, 0x001000c},
 {-4563036, 54131248, -4416003, 54217738, 0x001000a},
 {-4920600, 53990480, -4134192, 54481520, 0x001000c},
+{-10700000, 49122422, 1889648, 60875000, 0x0010216},
+{-4920600, 53990480, -4134192, 54481520, 0x003021c},
 {-61016523, 13981053, -60928111, 14067543, 0x001000a},
 {-61100000, 13690000, -60830000, 14118000, 0x001000c},
 {151555130, 7315679, 151641620, 7402169, 0x001000a},
@@ -481,6 +510,8 @@ static const mminforec mminfo[NR_RECS+1] = {
 {146678969, 6573900, 149360159, 9255090, 0x0010015},
 {150700754, 6573900, 153381944, 9255090, 0x0a90011},
 {137000000, 5210000, 163120000, 10200000, 0x19a0016},
+{152000000, 1000000, 157000000, 5210000, 0x09e0012},
+{137000000, 1000000, 163120000, 10200000, 0x0010217},
 {103796755, 1261728, 103883245, 1348218, 0x001000a},
 {103570000, 1160000, 104130000, 1482000, 0x016000c},
 {-175250128, -21210543, -175157872, -21124053, 0x001000a},
@@ -498,26 +529,32 @@ static const mminforec mminfo[NR_RECS+1] = {
 {50448000, 25557000, 50825000, 25967000, 0x0bd0010},
 {50300000, 25557000, 50825000, 26338000, 0x0d80211},
 {172918000, 1324000, 173080000, 1365000, 0x00f000a},
-{172778000, 1323000, 173172000, 1974000, 0x026000c},
+{172750000, 1690000, 173123949, 2010000, 0xf040447},
+{172860000, 1315000, 173194709, 1650000, 0xe890447},
 {-157502976, 1911168, -157353217, 2060927, 0x680004b},
-{172908912, 3266656, 173059087, 3416415, 0x680004b},
-{172730095, 3027583, 172879854, 3177342, 0x680004b},
-{174375120, -764880, 174524879, -615121, 0x680004b},
-{175905120, -1396909, 176054879, -1247150, 0x680004b},
-{174655168, -1267440, 174804927, -1117681, 0x680004b},
-{173195120, 1937680, 173344879, 2087439, 0x680004b},
-{172947632, 835120, 173097391, 984879, 0x680004b},
-{176380096, -1432368, 176529855, -1282609, 0x680004b},
-{-160435926, 4609543, -160313278, 4731852, 0x54f004b},
-{175536417, -1961053, 175658726, -1838744, 0x54f004b},
+{172908912, 3266656, 173059087, 3416415, 0x680044b},
+{172739000, 3038000, 172935649, 3152000, 0x680044b},
+{174382200, -815000, 174483629, -594000, 0x680044b},
+{175905120, -1396909, 176054879, -1247150, 0x680044b},
+{174657000, -1260000, 174800639, -1104000, 0x680044b},
+{173195120, 1937680, 173344879, 2087439, 0x680044b},
+{172967000, 835000, 173079589, 1034000, 0x680044b},
+{175500000, -1956000, 175627349, -1780000, 0x680044b},
+{176393000, -1417000, 176520709, -1300000, 0x54f044b},
+{-160455000, 4640000, -160305186, 4740000, 0x54f044b},
 {172594000, 69000, 173976000, 3415000, 0x1060011},
 {174181028, -2888514, 176862218, -207324, 0x001000d},
 {-173318525, -4688133, -170637335, -2006943, 0x0010015},
 {166790000, -4736000, 189387000, 3644400, 0x23b0016},
-{157830000, -11464000, 209800000, 4747000, 0x0010017},
+{197000000, -11500000, 210000000, 4750000, 0x0c00012},
+{157830000, -11500000, 210000000, 4750000, 0x0010017},
 {-71169000, 21417755, -71108000, 21519000, 0x029000a},
-{-71877000, 21440000, -71454000, 21933000, 0x021000c},
-{-72490000, 21600000, -71877000, 21977000, 0x08c0010},
+{-72500000, 21610000, -72400000, 21725000, 0x004010b},
+{-71730000, 21275000, -71605500, 21374852, 0x004010b},
+{-72370000, 21720000, -72057000, 21906781, 0x004010b},
+{-71259727, 21172423, -71077938, 21521497, 0x004010b},
+{-72075000, 21770000, -71838000, 21975000, 0x004010b},
+{-71917362, 21440000, -71454000, 21860000, 0x0aa0010},
 {-72500000, 21000000, -70900000, 22000000, 0x08a0011},
 {6666755, 299756, 6753245, 386246, 0x001000a},
 {6377221, -34742, 6845941, 456298, 0x001000c},
@@ -544,7 +581,8 @@ static const mminforec mminfo[NR_RECS+1] = {
 {-61882549, 15696598, -60899446, 16649910, 0x0a90011},
 {44365794, -12193245, 44454206, -12106755, 0x001000a},
 {43196000, -11952895, 43540000, -11350000, 0x028000c},
-{44150847, -12456700, 44624775, -11965660, 0x0b10010},
+{44190000, -12390000, 44560667, -12060000, 0xf04044b},
+{43575000, -12460000, 43991759, -12185000, 0xe89044b},
 {43165016, -12554984, 44624775, -11125016, 0x0a80011},
 {57456000, -20192000, 57545700, -20108813, 0x001000a},
 {57496000, -20122000, 57756000, -19979500, 0x004010b},
@@ -555,9 +593,12 @@ static const mminforec mminfo[NR_RECS+1] = {
 {56494384, -10570312, 56775616, -10275688, 0x001a08c},
 {54330304, -16089416, 54715696, -15696584, 0x001c88c},
 {57450224, -19965312, 57944984, -19474272, 0x001688c},
+{59454176, -16347312, 59745824, -16052688, 0x001e08c},
 {54300000, -20800000, 63700000, -10270000, 0x0010216},
 {55434000, -20939000, 55522965, -20871000, 0x001000b},
-{55210000, -21389870, 55838000, -20871000, 0x01c000c},
+{55210000, -21389870, 55672500, -20870000, 0x021000c},
+{55517000, -21410000, 55850000, -20870000, 0x0e30010},
+{54847807, -21782402, 56247984, -20441807, 0x0aa0211},
 {6047691, 49561514, 6180309, 49648004, 0x001000a},
 {5812948, 49447980, 6531652, 49939020, 0x001000c},
 {5733648, 49694480, 6452352, 50185520, 0x0b00010},
@@ -572,6 +613,9 @@ static const mminforec mminfo[NR_RECS+1] = {
 {-36524348, -54863306, -35727524, -54372266, 0x0b00010},
 {-38369968, -55334148, -35510032, -53636061, 0x0a80011},
 {-27700000, -59600000, -26000000, -56200000, 0x03a000d},
+{-41820000, -53910992, -41320032, -53600000, 0x0b0a890},
+{-39207461, -54097034, -38707493, -53786042, 0x0b0b090},
+{-34927700, -55178035, -34412108, -54867043, 0x0b0b890},
 {-41820000, -59600000, -26000000, -53600000, 0x0010216},
 {-149574753, -17567930, -149522540, -17518071, 0x22a004a},
 {-149626107, -17591935, -149573894, -17542076, 0x22a004a},
@@ -1161,7 +1205,22 @@ static const mminforec mminfo[NR_RECS+1] = {
 {168750360, -12355846, 168903447, -12206087, 0x680004b},
 {155880000, -8846000, 158750000, -6570000, 0x01b000d},
 {158750000, -9964000, 161591000, -7474400, 0x09e0011},
-{159700000, -11936000, 162500000, -9683000, 0x3640015},
+{155470000, -7433255, 155938720, -6942215, 0x0b10090},
+{159110983, -5491040, 159579703, -5000000, 0x0b00890},
+{159345343, -5687420, 159814063, -5196380, 0x0b01090},
+{159748247, -11756057, 160222175, -11265017, 0x0b11890},
+{160222175, -11952473, 160696103, -11461433, 0x0b12090},
+{161171712, -10621684, 161645640, -10130644, 0x0b12890},
+{161588768, -10835412, 162062696, -10344372, 0x0b13090},
+{162062696, -10935412, 162536624, -10444372, 0x0b13890},
+{161728710, -10112070, 162202638, -9621030, 0x0b04090},
+{161655639, -10372580, 162129567, -9881540, 0x0b04890},
+{166943521, -10113021, 167417449, -9621981, 0x0b05090},
+{165524550, -10464480, 165998478, -9973440, 0x0b15890},
+{165998478, -10464480, 166472406, -9973440, 0x0b16090},
+{165714122, -10955520, 166188050, -10464480, 0x0b16890},
+{166282835, -11495664, 166756763, -11004624, 0x0b17090},
+{166658951, -11892376, 167132879, -11401336, 0x0b17890},
 {155470000, -12355900, 168903500, -5000000, 0x0010016},
 {44452394, 40135449, 44565070, 40221938, 0x001000a},
 {44143000, 40026600, 44713000, 40540000, 0x020000c},
@@ -1384,6 +1443,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {118122940, 24320194, 118492355, 24542126, 0x001c08c},
 {119392453, 24925751, 119491405, 25023959, 0x001d88c},
 {119888306, 25920379, 120083313, 26306957, 0x001e08c},
+{121868618, 25370388, 122175890, 25665012, 0x001e88c},
 {120099346, 25907927, 120614938, 26398967, 0x001f08c},
 {118122500, 21750000, 122500000, 26400500, 0x0010216},
 {89603000, 27430000, 89671500, 27547000, 0x02a000a},
@@ -1582,6 +1642,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {10776112, 57119823, 11286496, 57414447, 0x001e08c},
 {11418030, 56614292, 11751342, 56810708, 0x001e88c},
 {14631144, 54973254, 15224856, 55333350, 0x001f08c},
+{11690000, 54550000, 12170000, 55000000, 0x001f088},
 {4490000, 54544000, 31600000, 68600000, 0x3770216},
 {8000000, 54544000, 15198000, 57780000, 0x003021c},
 {24636000, 59396800, 24854000, 59460000, 0x017000a},
@@ -1634,6 +1695,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {26087740, 57752840, 26962684, 58243880, 0x001c88c},
 {26962684, 57752840, 27837628, 58243880, 0x001d08c},
 {26120000, 57500000, 27555000, 57752840, 0x011d88c},
+{25351589, 59717000, 27153557, 59822030, 0x00ae08c},
 {14105000, 48990000, 32794200, 59822030, 0x0010216},
 {21700000, 57500000, 28250000, 59822030, 0x003021c},
 {-69936000, 18456428, -69828000, 18523000, 0x018000a},
@@ -2549,6 +2611,8 @@ static const mminforec mminfo[NR_RECS+1] = {
 {-53628559, 2100000, -53159839, 2591040, 0x0b03890},
 {-53159839, 2100000, -52691119, 2591040, 0x0b04090},
 {-52972351, 2100000, -52503631, 2591040, 0x0b04890},
+{-52660000, 5275000, -52250000, 5780000, 0x0c05090},
+{-52128655, 4802472, -51659935, 5293512, 0x0b05890},
 {-54597000, 2100000, -51514000, 5780000, 0x0010216},
 {54318811, 24427655, 54412989, 24514145, 0x001000a},
 {55039533, 24943292, 55555125, 25434332, 0x001000c},
@@ -3031,6 +3095,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {-7879634, 36785155, -7296338, 37276195, 0x0016088},
 {-17320204, 32624000, -16634000, 32890000, 0x0759890},
 {-16545000, 32402000, -16275000, 33128000, 0x133b890},
+{-16217756, 29847341, -15681332, 30338381, 0x0b0c090},
 {-31417659, 39303576, -30818739, 39794616, 0x0b1c890},
 {-28840000, 38372000, -28001000, 38651000, 0x070d090},
 {-28322000, 38525000, -27845000, 39100000, 0x0d5d890},
@@ -3041,11 +3106,12 @@ static const mminforec mminfo[NR_RECS+1] = {
 {-9839578, 38475972, -6443404, 41157162, 0x0a91091},
 {-9979996, 35867000, -6703000, 38475972, 0x0a61891},
 {-18145009, 31649405, -15016954, 34330595, 0x0a99891},
+{-18115218, 28968215, -15076536, 31649405, 0x0a9a091},
 {-31500000, 38595688, -29057138, 40502312, 0x0a8c891},
 {-29032561, 37668688, -26619490, 39575312, 0x0a7e091},
 {-26278640, 36409012, -23895360, 38315636, 0x0a7f091},
 {-31500000, 27500000, 4400000, 43850000, 0x0010217},
-{-31500000, 31600000, -6170000, 42154300, 0x003021c},
+{-31500000, 29660000, -6170000, 42154300, 0x003021c},
 {18982634, 47451000, 19109965, 47537489, 0x001000a},
 {18707922, 47323584, 19395378, 47814624, 0x001000c},
 {21574834, 47484200, 21702165, 47570689, 0x3c1004b},
@@ -3135,6 +3201,12 @@ static const mminforec mminfo[NR_RECS+1] = {
 {18123464, 46129710, 18790088, 46620750, 0x0012088},
 {18790088, 46129710, 19456712, 46620750, 0x0012888},
 {19456712, 46129710, 20123336, 46620750, 0x0013088},
+{20117763, 46115500, 20784387, 46620750, 0x0013888},
+{20784387, 46129710, 21451011, 46620750, 0x0014088},
+{17117955, 45638670, 17784579, 46129710, 0x0014888},
+{17784579, 45638670, 18451203, 46129710, 0x0015088},
+{18451203, 45638670, 19117827, 46129710, 0x0015888},
+{19117827, 45638670, 19784451, 46129710, 0x0016088},
 {20117763, 46115500, 20784387, 46620750, 0x0b33890},
 {20784387, 46129710, 21451011, 46620750, 0x0b14090},
 {17117955, 45638670, 17784579, 46129710, 0x0b14890},
@@ -3234,6 +3306,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {126001379, 33100000, 126558635, 33591040, 0x001e088},
 {126558635, 33100000, 127115891, 33591040, 0x001e888},
 {130368752, 37256580, 130957256, 37747620, 0x001f088},
+{127370341, 33714600, 127850000, 34205640, 0x0bff090},
 {124570000, 33100000, 131000000, 38625000, 0x0010216},
 {-22037500, 64086000, -21836500, 64166000, 0x01d000a},
 {-22118200, 63842000, -21214000, 64386000, 0x023000c},
@@ -3577,6 +3650,8 @@ static const mminforec mminfo[NR_RECS+1] = {
 {23342228, 41269656, 23961980, 41760696, 0x0017888},
 {23961980, 41269656, 24581732, 41760696, 0x0018088},
 {24581732, 41269656, 25201484, 41760696, 0x0018888},
+{25201484, 41234000, 25770000, 41760696, 0x0219088},
+{25770000, 41294000, 26363000, 41760696, 0x0019888},
 {25201484, 41234000, 25770000, 41760696, 0x0bfa890},
 {25770000, 41294000, 26363000, 41760696, 0x0b0b090},
 {12090000, 39600000, 30183000, 51061000, 0x0010216},
@@ -3826,6 +3901,11 @@ static const mminforec mminfo[NR_RECS+1] = {
 {2351710, 11026880, 2825638, 11517920, 0x0016888},
 {2825638, 11026880, 3299566, 11517920, 0x0017088},
 {3299566, 11026880, 3773494, 11517920, 0x0017888},
+{2110000, 11517920, 2588674, 11920600, 0x01cd088},
+{2588674, 11517920, 3062602, 11920600, 0x001d888},
+{3062602, 11517920, 3617000, 11920600, 0x01ae088},
+{2369604, 11920600, 2843532, 12411641, 0x001e888},
+{2843532, 11920600, 3317460, 12411641, 0x001f088},
 {2114746, 11517920, 2588674, 11920600, 0x0a0d090},
 {2588674, 11517920, 3062602, 11920600, 0x0a0d890},
 {3062602, 11517920, 3617000, 11920600, 0x094e090},
@@ -4497,22 +4577,22 @@ static const mminforec mminfo[NR_RECS+1] = {
 {88815992, 25991648, 89331584, 26482688, 0x001088c},
 {88078695, 25746128, 88594287, 26237168, 0x001108c},
 {88594287, 25746128, 89109879, 26237168, 0x001188c},
-{89109879, 25746128, 89625471, 26237168, 0x001208c},
-{89480000, 25746128, 89898735, 26260000, 0x023288c},
+{89109879, 25705000, 89550000, 26120000, 0x001208c},
+{89550000, 25705000, 89898735, 26260000, 0x028288c},
 {88310000, 25255088, 88841771, 25746128, 0x01e308c},
 {88841771, 25255088, 89357363, 25746128, 0x001388c},
-{89357363, 25255088, 89890000, 25746128, 0x01e408c},
+{89357363, 25255088, 89890000, 25705000, 0x01d408c},
 {88064808, 24764048, 88580400, 25255088, 0x001488c},
 {88580399, 24764048, 89095991, 25255088, 0x001508c},
 {89095991, 24764048, 89611583, 25255088, 0x001588c},
-{89611583, 24764048, 90090000, 25311000, 0x021608c},
-{90090000, 24764048, 90625771, 25242000, 0x01e688c},
-{90628375, 24764048, 91143967, 25255088, 0x001708c},
+{89611583, 24764048, 90070000, 25311000, 0x022608c},
+{90070000, 24764048, 90580000, 25248267, 0x001688c},
+{90580000, 24764048, 91143967, 25202000, 0x01b708c},
 {91143967, 24764048, 91659559, 25255088, 0x001788c},
 {91659559, 24764048, 92175151, 25255088, 0x001808c},
 {92167000, 24418000, 92500000, 25141000, 0x02e888c},
-{88004500, 24287000, 88560500, 24764048, 0x01d908c},
-{88555592, 24273008, 89065976, 24764048, 0x001988c},
+{88004500, 24296023, 88550000, 24764048, 0x01d908c},
+{88550000, 24273008, 89065976, 24764048, 0x01e988c},
 {89065976, 24273008, 89576360, 24764048, 0x001a08c},
 {89576359, 24273008, 90086743, 24764048, 0x001a88c},
 {90086743, 24273008, 90597127, 24764048, 0x001b08c},
@@ -4532,15 +4612,15 @@ static const mminforec mminfo[NR_RECS+1] = {
 {90076326, 23290928, 90581502, 23781968, 0x0012888},
 {90581502, 23290928, 91086678, 23781968, 0x0013088},
 {91086678, 23290928, 91591854, 23781968, 0x0013888},
-{91769000, 23290928, 92400000, 23740000, 0x01a4088},
 {88690016, 22799888, 89195192, 23290928, 0x0015088},
 {89195192, 22799888, 89700368, 23290928, 0x0015888},
 {89700368, 22799888, 90205544, 23290928, 0x0016088},
 {90205544, 22799888, 90710720, 23290928, 0x0016888},
 {90710720, 22799888, 91215896, 23290928, 0x0017088},
 {91215896, 22799888, 91721072, 23290928, 0x0017888},
-{91721072, 22799888, 92226248, 23290928, 0x0018088},
-{92176824, 22799888, 92682000, 23290928, 0x0018888},
+{91830000, 23380000, 92360000, 23740000, 0x01a4088},
+{91721072, 22799888, 92100000, 23380000, 0x0278088},
+{92100000, 22799888, 92480000, 23380000, 0x0268888},
 {88907241, 22308847, 89412417, 22799887, 0x0019088},
 {89412417, 22308847, 89917593, 22799887, 0x0019888},
 {89917593, 22308847, 90422769, 22799887, 0x001a088},
@@ -4696,6 +4776,8 @@ static const mminforec mminfo[NR_RECS+1] = {
 {-55635909, 2098462, -55167189, 2589502, 0x001d088},
 {-55167189, 2098462, -54698469, 2589502, 0x001d888},
 {-54698469, 2098462, -54229749, 2589502, 0x001e088},
+{-56760837, 1830000, -56292117, 2098462, 0x001e888},
+{-56292117, 1830000, -55823397, 2098462, 0x001f088},
 {-56760837, 1830000, -56292117, 2098462, 0x082e890},
 {-56292117, 1830000, -55823397, 2098462, 0x082f090},
 {-58086600, 1830000, -53979000, 6029000, 0x0010216},
@@ -4803,7 +4885,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {35717000, 34650000, 39550000, 36926185, 0x08f0011},
 {35586890, 32313599, 38955000, 34650000, 0x01c000d},
 {39550000, 34380000, 42380000, 37322182, 0x4350015},
-{34217000, 28520000, 48790000, 37390000, 0x0010216},
+{34217000, 28520000, 48790000, 37390000, 0x0010016},
 {35586900, 32313600, 42380000, 37322200, 0x003021c},
 {-17490000, 14648500, -17416000, 14747500, 0x024000a},
 {-17530000, 14642000, -16875000, 14988000, 0x016000c},
@@ -5074,92 +5156,99 @@ static const mminforec mminfo[NR_RECS+1] = {
 {28255867, 44234040, 28339533, 44294159, 0x29c004b},
 {27385682, 45822450, 27474518, 45884549, 0x2b2004b},
 {25766580, 46339940, 25853419, 46400059, 0x29c004b},
-{22735000, 47855574, 23720000, 48121000, 0x0130088},
-{23720000, 47855574, 24700000, 48121000, 0x0130888},
-{25220000, 47855574, 26368000, 48192000, 0x0131088},
-{26368000, 47855574, 27265500, 48265650, 0x0181888},
-{21873060, 47326342, 22617804, 47855574, 0x01e2088},
-{22617804, 47326342, 23362548, 47855574, 0x01e2888},
-{23362548, 47326342, 24107292, 47855574, 0x01e3088},
-{24107292, 47326342, 24852036, 47855574, 0x01e3888},
-{24852036, 47326342, 25596780, 47855574, 0x01e4088},
-{25596780, 47326342, 26341524, 47855574, 0x01e4888},
-{26341524, 47326342, 27086268, 47855574, 0x01e5088},
-{27086268, 47326342, 27831012, 47855574, 0x01e5888},
-{21537175, 46797110, 22271503, 47326342, 0x0016088},
-{22271503, 46797110, 23005831, 47326342, 0x0016888},
-{23005831, 46797110, 23740159, 47326342, 0x0017088},
-{23740159, 46797110, 24474487, 47326342, 0x0017888},
-{24474487, 46797110, 25208815, 47326342, 0x0018088},
-{25208815, 46797110, 25943143, 47326342, 0x0018888},
-{25943143, 46797110, 26677471, 47326342, 0x0019088},
-{26677471, 46797110, 27411799, 47326342, 0x0019888},
-{27411799, 46797110, 28146127, 47326342, 0x001a088},
-{21065736, 46267878, 21794856, 46797110, 0x001a888},
-{21794856, 46267878, 22523976, 46797110, 0x001b088},
-{22523976, 46267878, 23253096, 46797110, 0x001b888},
-{23253096, 46267878, 23982216, 46797110, 0x001c088},
-{23982216, 46267878, 24711336, 46797110, 0x001c888},
-{24711336, 46267878, 25440456, 46797110, 0x001d088},
-{25440456, 46267878, 26169576, 46797110, 0x001d888},
-{26169576, 46267878, 26898696, 46797110, 0x001e088},
-{26898696, 46267878, 27627816, 46797110, 0x001e888},
-{27627816, 46267878, 28356936, 46797110, 0x001f088},
-{20983450, 45738646, 21707362, 46267878, 0x01e008c},
-{20259538, 45738646, 20983450, 46267878, 0x01e088c},
-{21707362, 45738646, 22431274, 46267878, 0x01e108c},
-{22431274, 45738646, 23155186, 46267878, 0x01e188c},
-{23155186, 45738646, 23879098, 46267878, 0x01e208c},
-{23879098, 45738646, 24603010, 46267878, 0x01e288c},
-{24603010, 45738646, 25326922, 46267878, 0x01e308c},
-{25326922, 45738646, 26050834, 46267878, 0x01e388c},
-{26050834, 45738646, 26774746, 46267878, 0x01e408c},
-{26774746, 45738646, 27498658, 46267878, 0x01e488c},
-{27498658, 45738646, 28222570, 46267878, 0x01e508c},
-{21480918, 45209414, 22194414, 45738646, 0x001588c},
-{20767422, 45209414, 21480918, 45738646, 0x001608c},
-{22194414, 45209414, 22907910, 45738646, 0x001688c},
-{22907910, 45209414, 23621406, 45738646, 0x001708c},
-{23621406, 45209414, 24334902, 45738646, 0x001788c},
-{24334902, 45209414, 25048398, 45738646, 0x001808c},
-{25048398, 45209414, 25761894, 45738646, 0x001888c},
-{25761894, 45209414, 26475390, 45738646, 0x001908c},
-{26475390, 45209414, 27188886, 45738646, 0x001988c},
-{27188886, 45209414, 27902382, 45738646, 0x001a08c},
-{27902382, 45209414, 28615878, 45738646, 0x001a88c},
-{22051715, 44680182, 22760003, 45209414, 0x001b08c},
-{21343427, 44680182, 22051715, 45209414, 0x001b88c},
-{22760003, 44680182, 23468291, 45209414, 0x001c08c},
-{23468291, 44680182, 24176579, 45209414, 0x001c88c},
-{24176579, 44680182, 24884867, 45209414, 0x001d08c},
-{24884867, 44680182, 25593155, 45209414, 0x001d88c},
-{25593155, 44680182, 26301443, 45209414, 0x001e08c},
-{26301443, 44680182, 27009731, 45209414, 0x001e88c},
-{27009731, 44680182, 27718019, 45209414, 0x001f08c},
-{27718019, 44680182, 28426307, 45209414, 0x0b00090},
-{28426307, 44680182, 29134595, 45209414, 0x0b00890},
-{29134595, 44680182, 29842883, 45209414, 0x0b01090},
-{22269409, 44150950, 22972489, 44680182, 0x0b01890},
-{21566329, 44150950, 22269409, 44680182, 0x0b02090},
-{22972489, 44150950, 23675569, 44680182, 0x0b02890},
-{23675569, 44150950, 24378649, 44680182, 0x0b03090},
-{24378649, 44150950, 25081729, 44680182, 0x0b03890},
-{25081729, 44150950, 25784809, 44680182, 0x0b04090},
-{25784809, 44150950, 26487889, 44680182, 0x0b04890},
-{26487889, 44150950, 27190969, 44680182, 0x0b05090},
-{27190969, 44150950, 27894049, 44680182, 0x0b05890},
-{27894049, 44150950, 28597129, 44680182, 0x0b06090},
-{28597129, 44150950, 29300209, 44680182, 0x0b06890},
-{22801927, 43621718, 23494591, 44150950, 0x0b17090},
-{23494591, 43621718, 24187255, 44150950, 0x0b17890},
-{24187255, 43621718, 24879919, 44150950, 0x0b18090},
-{24879919, 43621718, 25572583, 44150950, 0x0b18890},
-{25572583, 43621718, 26265247, 44150950, 0x0b19090},
-{26265247, 43621718, 26957911, 44150950, 0x0b19890},
-{26957911, 43621718, 27650575, 44150950, 0x0b1a090},
-{27650575, 43621718, 28343239, 44150950, 0x0b1a890},
-{28343239, 43621718, 29035903, 44150950, 0x0b1b090},
-{28615800, 45209400, 29705000, 45470000, 0x064b890},
+{22735000, 47855574, 23660000, 48121000, 0x0130088},
+{23660000, 47855574, 24700000, 48000000, 0x00d0888},
+{25205000, 47855574, 25900000, 47980000, 0x0011088},
+{25900000, 47855574, 26580000, 48265650, 0x0011888},
+{26580000, 47855574, 27266000, 48265650, 0x0012088},
+{21900000, 47326342, 22536000, 47820000, 0x0202888},
+{22536000, 47326342, 23172000, 47855574, 0x0213088},
+{23172000, 47326342, 23808000, 47855574, 0x0213888},
+{23808000, 47326342, 24444000, 47855574, 0x0214088},
+{24444000, 47326342, 25080000, 47855574, 0x0214888},
+{25080000, 47326342, 25716000, 47855574, 0x0215088},
+{25716000, 47326342, 26352000, 47855574, 0x0215888},
+{26352000, 47326342, 26988000, 47855574, 0x0216088},
+{26988000, 47326342, 27622000, 47855574, 0x0216888},
+{21512000, 46797110, 22176000, 47326342, 0x0207088},
+{22176000, 46797110, 22840000, 47326342, 0x0207888},
+{22840000, 46797110, 23504000, 47326342, 0x0208088},
+{23504000, 46797110, 24168000, 47326342, 0x0208888},
+{24168000, 46797110, 24832000, 47326342, 0x0209088},
+{24832000, 46797110, 25496000, 47326342, 0x0209888},
+{25496000, 46797110, 26160000, 47326342, 0x020a088},
+{26160000, 46797110, 26824000, 47326342, 0x020a888},
+{26824000, 46797110, 27488000, 47326342, 0x020b088},
+{27488000, 46797110, 28147000, 47326342, 0x020b888},
+{21100000, 46267878, 21752000, 46797110, 0x020c088},
+{21752000, 46267878, 22404000, 46797110, 0x020c888},
+{22404000, 46267878, 23056000, 46797110, 0x020d088},
+{23056000, 46267878, 23708000, 46797110, 0x020d888},
+{23708000, 46267878, 24360000, 46797110, 0x020e088},
+{24360000, 46267878, 25012000, 46797110, 0x020e888},
+{25012000, 46267878, 25664000, 46797110, 0x020f088},
+{25664000, 46267878, 26316000, 46797110, 0x020008c},
+{26316000, 46267878, 26968000, 46797110, 0x020088c},
+{26968000, 46267878, 27620000, 46797110, 0x020108c},
+{27620000, 46267878, 28270000, 46797110, 0x020188c},
+{20259000, 45738646, 20866000, 46289000, 0x022208c},
+{20866000, 45738646, 21473000, 46289000, 0x022288c},
+{21473000, 45738646, 22080000, 46267878, 0x021308c},
+{22080000, 45738646, 22687000, 46267878, 0x021388c},
+{22687000, 45738646, 23294000, 46267878, 0x021408c},
+{23294000, 45738646, 23901000, 46267878, 0x021488c},
+{23901000, 45738646, 24508000, 46267878, 0x021508c},
+{24508000, 45738646, 25115000, 46267878, 0x021588c},
+{25115000, 45738646, 25722000, 46267878, 0x021608c},
+{25722000, 45738646, 26329000, 46267878, 0x021688c},
+{26329000, 45738646, 26936000, 46267878, 0x021708c},
+{26936000, 45738646, 27548000, 46267878, 0x021788c},
+{27548000, 45738646, 28162000, 46267878, 0x021808c},
+{20760000, 45209414, 21401000, 45738646, 0x020888c},
+{21401000, 45209414, 22042000, 45738646, 0x020908c},
+{22042000, 45209414, 22683000, 45738646, 0x020988c},
+{22683000, 45209414, 23324000, 45738646, 0x020a08c},
+{23324000, 45209414, 23965000, 45738646, 0x020a88c},
+{23965000, 45209414, 24606000, 45738646, 0x020b08c},
+{24606000, 45209414, 25247000, 45738646, 0x020b88c},
+{25247000, 45209414, 25888000, 45738646, 0x020c08c},
+{25888000, 45209414, 26529000, 45738646, 0x020c88c},
+{26529000, 45209414, 27170000, 45738646, 0x020d08c},
+{27170000, 45209414, 27811000, 45738646, 0x020d88c},
+{27811000, 45209414, 28450000, 45738646, 0x020e08c},
+{28450000, 45209400, 29705000, 45470000, 0x010e88c},
+{21343427, 44770000, 22100000, 45209414, 0x01bf08c},
+{22100000, 44680182, 22734000, 45209414, 0x0ba0090},
+{22734000, 44680182, 23368000, 45209414, 0x0ba0890},
+{23368000, 44680182, 24002000, 45209414, 0x0ba1090},
+{24002000, 44680182, 24636000, 45209414, 0x0ba1890},
+{24636000, 44680182, 25270000, 45209414, 0x0ba2090},
+{25270000, 44680182, 25904000, 45209414, 0x0ba2890},
+{25904000, 44680182, 26538000, 45209414, 0x0ba3090},
+{26538000, 44680182, 27172000, 45209414, 0x0ba3890},
+{27172000, 44680182, 27806000, 45209414, 0x0ba4090},
+{27806000, 44680182, 28440000, 45209414, 0x0ba4890},
+{28440000, 44680182, 29074000, 45209414, 0x0ba5090},
+{29074000, 44680182, 29708000, 45209414, 0x0ba5890},
+{21566329, 44460000, 22450000, 44770000, 0x0786090},
+{22450000, 44150950, 23110000, 44680182, 0x0b66890},
+{23110000, 44150950, 23770000, 44680182, 0x0b67090},
+{23770000, 44150950, 24430000, 44680182, 0x0b67890},
+{24430000, 44150950, 25090000, 44680182, 0x0b68090},
+{25090000, 44150950, 25750000, 44680182, 0x0b68890},
+{25750000, 44150950, 26410000, 44680182, 0x0b69090},
+{26410000, 44150950, 27070000, 44680182, 0x0b69890},
+{27070000, 44150950, 27730000, 44680182, 0x0b6a090},
+{27730000, 44150950, 28390000, 44680182, 0x0b6a890},
+{28390000, 44150950, 29050000, 44680182, 0x0b6b090},
+{22820000, 43770000, 23470000, 44150950, 0x09bb890},
+{23470000, 43660000, 24100000, 44150950, 0x0b2c090},
+{24100000, 43660000, 24730000, 44150950, 0x0b2c890},
+{24730000, 43621718, 25340000, 44150950, 0x0bcd090},
+{25340000, 43621718, 25950000, 44150950, 0x0bcd890},
+{25950000, 43860000, 26930000, 44150950, 0x06ee090},
+{26930000, 43860000, 27930000, 44150950, 0x06de890},
+{27930000, 43730000, 28714000, 44150950, 0x094f090},
 {12090000, 39600000, 30183000, 51061000, 0x0010216},
 {20251650, 43612000, 29705000, 48265650, 0x003021c},
 {-240995, 5526500, -200000, 5618000, 0x2a7044a},
@@ -5631,6 +5720,8 @@ static const mminforec mminfo[NR_RECS+1] = {
 {170527899, -44773975, 174132610, -42092785, 0x0a87091},
 {163690507, -47455165, 167444173, -44773975, 0x0a87891},
 {167444173, -47455165, 171197839, -44773975, 0x0a88891},
+{173691704, -39411595, 177028296, -36730405, 0x0a89091},
+{173652379, -42092785, 177108135, -39411595, 0x0a89891},
 {177756637, -50333695, 179782425, -48993100, 0x0a8a091},
 {182853029, -44947803, 184700071, -43607208, 0x0a8a891},
 {165697550, -48579152, 167425428, -47417303, 0x0a7b891},
@@ -5761,6 +5852,8 @@ static const mminforec mminfo[NR_RECS+1] = {
 {122615932, 13900080, 123095068, 14391120, 0x0b1b890},
 {120463424, 17842380, 120952976, 18333420, 0x0b1c090},
 {116866000, 4599000, 126607050, 21143000, 0x4c90016},
+{116866000, 4380000, 128000000, 21143000, 0x0d40012},
+{116866000, 4380000, 128000000, 21143000, 0x0010217},
 {12433114, 41851944, 12548434, 41938434, 0x001000a},
 {8986829, 45365330, 9393170, 45652159, 0xc730047},
 {12317720, 41753290, 12682279, 42026709, 0xbde0047},
@@ -6515,6 +6608,8 @@ static const mminforec mminfo[NR_RECS+1] = {
 {135445000, 34450000, 138170700, 37560000, 0x0c6a091},
 {138979810, 38899914, 142405775, 41581104, 0x0a9c091},
 {138170686, 34556386, 141388114, 37237576, 0x0a9c891},
+{135377023, 37560000, 138600000, 40236615, 0x0acd091},
+{131000000, 35959405, 134250000, 38640595, 0x0a9d891},
 {122826000, 24030000, 149150000, 45558000, 0x0010217},
 {31004713, -17869254, 31095286, -17782765, 0x001000a},
 {30886966, -18040495, 31249262, -17694536, 0xf040047},
@@ -7311,9 +7406,8 @@ static const mminforec mminfo[NR_RECS+1] = {
 {-5200000, 41310000, 9600000, 51100000, 0x003021c},
 {19474000, 59973000, 20400000, 60464000, 0x001000c},
 {20400000, 59900000, 21118800, 60536000, 0x0e40010},
-{-9154000, 68600000, 33625000, 80843100, 0x0970012},
 {4490000, 54544000, 31600000, 68600000, 0x3770016},
-{19100000, 59675750, 21134000, 60671833, 0x003021c},
+{19100000, 59675750, 21480000, 60671833, 0x003021c},
 {36798377, -1311622, 36884867, -1225132, 0x001000a},
 {36694245, -1500829, 37162965, -1009789, 0x001000c},
 {39558535, -4050300, 39645264, -3963811, 0x3c1004b},
@@ -7513,7 +7607,9 @@ static const mminforec mminfo[NR_RECS+1] = {
 {44272615, -23165520, 44777791, -22674480, 0x0b1a890},
 {47750427, -15125520, 48229563, -14634480, 0x0b1b090},
 {45218433, -19781520, 45713193, -19290480, 0x0b0b890},
+{43150016, -22305520, 43649984, -21814480, 0x0b1c090},
 {43210000, -25610000, 50500000, -11930000, 0x0010016},
+{42000000, -27000000, 54600000, -9000000, 0x0010217},
 {30438530, 50402055, 30574031, 50488545, 0x001000a},
 {30286000, 50324400, 30716635, 50539700, 0xa9e0447},
 {36077520, 49858490, 36456680, 50103109, 0xa9e0047},
@@ -7577,7 +7673,10 @@ static const mminforec mminfo[NR_RECS+1] = {
 {30255645, 6304524, 30724365, 6795564, 0x0b12890},
 {31895739, 9642124, 32369667, 10133164, 0x0b03090},
 {32579339, 11500624, 33053267, 11991664, 0x0b13890},
-{23400000, 3480000, 36000000, 12250000, 0x0010016},
+{23400000, 3480000, 36000000, 12250000, 0x0900012},
+{21810000, 9342000, 38630000, 23200000, 0x3580016},
+{-19000000, -47500000, 60000000, 37550000, 0x3e50217},
+{23400000, 3480000, 36000000, 12250000, 0x003021c},
 {18504835, 4317755, 18548785, 4402723, 0x2a7044a},
 {18548785, 4344956, 18592194, 4431049, 0x2a7044a},
 {18217521, 4115480, 18686241, 4606520, 0x001000c},
@@ -8912,6 +9011,9 @@ static const mminforec mminfo[NR_RECS+1] = {
 {27362200, -28565520, 27888208, -28074480, 0x0b1f090},
 {26542941, -27500595, 29492250, -24819405, 0x0a80011},
 {16440000, -34900000, 33000000, -22116000, 0x3580016},
+{37000000, -47400000, 38500000, -46300000, 0x001988d},
+{-19000000, -47500000, 60000000, 37550000, 0x3e50217},
+{16440000, -47400000, 38500000, -22116000, 0x003021c},
 {-8032023, 12595155, -7943611, 12681645, 0x001000a},
 {-8245146, 12392934, -7766010, 12883974, 0x001000c},
 {-5721785, 11275900, -5633615, 11362389, 0x3c1004b},
@@ -9244,7 +9346,9 @@ static const mminforec mminfo[NR_RECS+1] = {
 {-71469553, -14535475, -70990417, -14044435, 0x001c88c},
 {-76974355, -7415475, -76505635, -6924435, 0x001d08c},
 {-76584563, -13320475, -76105427, -12829435, 0x001d88c},
+{-69122744, -12739756, -68643608, -12248716, 0x001e08c},
 {-81360000, -18351470, -68670000, -12970, 0x4680016},
+{-92000000, -56600000, -30000000, 13500000, 0x0010217},
 {106810541, 47889000, 106987706, 47951245, 0x016000a},
 {106539272, 47662480, 107226728, 48153520, 0x001000c},
 {103969749, 48970090, 104155251, 49092399, 0x54f004b},
@@ -9512,7 +9616,10 @@ static const mminforec mminfo[NR_RECS+1] = {
 {23230432, 12654480, 23709568, 13145520, 0x0b07090},
 {36965124, 18884980, 37459884, 19376020, 0x0b07890},
 {33745224, 17774480, 34234776, 18265520, 0x0b08090},
-{21810000, 8600000, 38630000, 23200000, 0x36f0016},
+{21810000, 9342000, 38630000, 23200000, 0x3580016},
+{23400000, 3480000, 36000000, 12250000, 0x0900012},
+{-19000000, -47500000, 60000000, 37550000, 0x3e50217},
+{21810000, 9342000, 38630000, 23200000, 0x003021c},
 {106786755, -6240545, 106873245, -6154055, 0x001000a},
 {106557000, -6425520, 107178000, -6068000, 0x017000c},
 {112660000, -7245000, 112804926, -7193000, 0x3c1044b},
@@ -9660,7 +9767,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {-99180500, 19393000, -99074700, 19466000, 0x01a000a},
 {-99320000, 19197764, -98875000, 19732000, 0x022000c},
 {-100620000, 18300000, -98570000, 20296000, 0x0aa0011},
-{-99365200, 19045000, -98938000, 19592000, 0x0020216},
+{-99365200, 19045000, -98938000, 19593000, 0x0020216},
 {-98279000, 19283000, -98152500, 19343800, 0x016000a},
 {-98110776, 19103030, -97616016, 19594070, 0x0b00010},
 {-98590000, 19103030, -98110776, 19602000, 0x001000c},
@@ -9841,7 +9948,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {-98654685, 17512560, -98432916, 17724329, 0x931004b},
 {-102190000, 16574000, -99042000, 18880000, 0x0930011},
 {-100288000, 16250000, -97960000, 18789000, 0x001000d},
-{-102190000, 16250000, -97960000, 18880000, 0x0020216},
+{-102190000, 16250000, -97960000, 18890000, 0x0020216},
 {-100353589, 25654755, -100258450, 25741245, 0x001000a},
 {-100641100, 25544000, -99919000, 25886986, 0x015000c},
 {-100081056, 25087630, -99765544, 25374459, 0xc73004b},
@@ -9873,7 +9980,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {-97444028, 18349405, -94643674, 20300000, 0x0900011},
 {-96330000, 17123005, -93599823, 18770000, 0x001000d},
 {-98680000, 20050000, -96000000, 22470595, 0x0010015},
-{-98680000, 17123000, -93593000, 22478000, 0x0020216},
+{-98682000, 17123000, -93593000, 22478000, 0x0020216},
 {-93174000, 16725600, -93060000, 16793245, 0x018000a},
 {-93390600, 16549700, -92881330, 17005400, 0x01d000c},
 {-92170000, 16099000, -91821433, 16344100, 0xc73044b},
@@ -10000,7 +10107,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {-105858000, 26749400, -105564416, 26977500, 0xa9e044b},
 {-106955078, 28283790, -106678523, 28528409, 0xa9e004b},
 {-108051866, 30305610, -107788135, 30534389, 0x9ee004b},
-{-108380000, 26338700, -104270000, 28400000, 0x07e0011},
+{-108380000, 26259900, -104248545, 28400000, 0x0800011},
 {-108400000, 28400000, -105833000, 31787000, 0x4980015},
 {-108920000, 30910000, -108400000, 31336700, 0x0010088},
 {-108949700, 30480000, -108400000, 30910000, 0x01c0888},
@@ -10027,12 +10134,12 @@ static const mminforec mminfo[NR_RECS+1] = {
 {-104751000, 28400000, -104209000, 28893500, 0x01eb088},
 {-104209000, 28400000, -103650000, 28893500, 0x01eb888},
 {-103650000, 28524000, -103295000, 29174500, 0x02bc088},
-{-104270000, 27800000, -103690000, 28400000, 0x020c888},
-{-104270000, 27200000, -103795500, 27800000, 0x024d088},
-{-104270000, 26724000, -103698000, 27200000, 0x01dd888},
-{-107944000, 25887000, -107251000, 26338700, 0x019e088},
-{-107251000, 25967000, -106316000, 26338700, 0x014e888},
-{-107251000, 25555000, -106460000, 25967000, 0x016f088},
+{-104248545, 27884000, -103690000, 28400000, 0x01ec888},
+{-104248545, 27242000, -103806500, 27884000, 0x026d088},
+{-104248545, 26725000, -103698000, 27242000, 0x01ed888},
+{-107880400, 25854600, -107200100, 26259900, 0x018e088},
+{-107200100, 25922000, -106385000, 26259900, 0x014e888},
+{-107200100, 25560000, -106460000, 25922000, 0x016f088},
 {-109100000, 25555000, -103295000, 31800000, 0x0020216},
 {-51762770, 64129105, -51565765, 64215595, 0x001000a},
 {-52234800, 63935480, -51187992, 64426520, 0x001000c},
@@ -10683,10 +10790,10 @@ static const mminforec mminfo[NR_RECS+1] = {
 {92120300, 11160000, 93485000, 14248000, 0x004010c},
 {92671000, 7842000, 93680000, 9296000, 0x004010c},
 {93600000, 6720000, 94000000, 7465000, 0x004010c},
-{93595254, 14802691, 93721640, 14925000, 0x004010c},
+{92721605, 11139203, 92736454, 11150698, 0x004010c},
 {94221815, 13371257, 94347521, 13493566, 0x004010c},
 {93798494, 12219185, 93923521, 12341494, 0x004010c},
-{92120300, 6670000, 94356000, 14925000, 0x0020216},
+{92120300, 6670000, 94356000, 14333000, 0x0020216},
 {72999358, 8253865, 73085848, 8340355, 0x001000b},
 {72570000, 10505000, 72845000, 11300000, 0x033000c},
 {71923843, 10766451, 72397771, 11257491, 0x0b10010},
@@ -10795,7 +10902,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {75273000, 32122000, 75932000, 32500000, 0x004010c},
 {73875000, 29727000, 76933000, 32122000, 0x004010c},
 {75154000, 29522000, 75402000, 29727000, 0x004018c},
-{73875000, 29522000, 76933000, 32500000, 0x0020216},
+{73875000, 29522000, 76933000, 32514000, 0x0020216},
 {76977509, 28416165, 77075531, 28502655, 0x001000a},
 {76921600, 28080300, 77481544, 28546400, 0x01d000c},
 {76910742, 29390090, 77051057, 29512399, 0x54f004b},
@@ -10823,7 +10930,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {76682000, 30491000, 77210000, 30916000, 0x004010c},
 {74444000, 29214000, 75280000, 30000000, 0x004010c},
 {75280000, 27640000, 77581000, 30491000, 0x004018c},
-{74444000, 27640000, 77581000, 30916000, 0x0020216},
+{74444000, 27640000, 77597000, 30931000, 0x0020216},
 {93580000, 27058000, 93706000, 27121000, 0x017000a},
 {93484559, 26917620, 93871841, 27263579, 0xf040047},
 {95186995, 27887700, 95565605, 28222589, 0xe890047},
@@ -11105,8 +11212,8 @@ static const mminforec mminfo[NR_RECS+1] = {
 {77582386, 11511897, 78056314, 12002937, 0x001a08c},
 {77108458, 11511897, 77582386, 12002937, 0x001a88c},
 {76634530, 11511897, 77108458, 12002937, 0x001b08c},
-{76228000, 11511897, 76701928, 12002937, 0x001b88c},
-{76228000, 11020857, 76701928, 11511897, 0x001c08c},
+{76200000, 11511897, 76673928, 12002937, 0x001b88c},
+{76200000, 11020857, 76673928, 11511897, 0x001c08c},
 {76634530, 11020857, 77108458, 11511897, 0x001c88c},
 {77108458, 11020857, 77582386, 11511897, 0x001d08c},
 {77582386, 11020857, 78056314, 11511897, 0x001d88c},
@@ -11144,7 +11251,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {76989976, 8074617, 77458696, 8565657, 0x0b1e090},
 {77458696, 8074617, 77927416, 8565657, 0x0b1e890},
 {77927416, 8074617, 78396136, 8565657, 0x0b1f090},
-{76228000, 8068000, 80700000, 13500000, 0x0020216},
+{76200000, 8000000, 80700000, 13555000, 0x0020216},
 {77132028, 31046055, 77232933, 31132545, 0x001000a},
 {76911084, 30806980, 77452716, 31298020, 0x001000c},
 {76199074, 32068110, 76468525, 32296889, 0x9ee004b},
@@ -11831,6 +11938,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {79727000, 10822000, 79871000, 11011000, 0x004010b},
 {82183000, 16704000, 82328000, 16778000, 0x004010b},
 {75522000, 11673000, 75569000, 11710000, 0x004010b},
+{75522000, 11703500, 75569000, 11720000, 0x004010b},
 {75522000, 10822000, 82328000, 16778000, 0x0020216},
 {151158106, -33913245, 151261894, -33826755, 0x001000a},
 {150745968, -34120420, 151308432, -33629380, 0x001000c},
@@ -11873,7 +11981,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {150096664, -32529404, 153252000, -29966000, 0x01e000d},
 {149234028, -29966000, 153655000, -28154347, 0x28e0015},
 {141000000, -37508092, 159267000, -28154347, 0x2ca0016},
-{141000000, -37508092, 159267000, -28154347, 0x0020217},
+{140997000, -37508092, 159267000, -28154347, 0x0020217},
 {149082445, -35350645, 149188155, -35264155, 0x001000a},
 {148750000, -35500000, 149400000, -35121000, 0x019000c},
 {148750000, -35922000, 149170000, -35400000, 0x0d40010},
@@ -11890,7 +11998,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {130889613, -16400456, 133630385, -13719266, 0x001000d},
 {132440032, -25040595, 135329759, -22359405, 0x0010015},
 {129000000, -26000000, 138000000, -10600000, 0x4d60016},
-{129000000, -26000000, 138000000, -10600000, 0x0020217},
+{128999000, -26040000, 138000000, -10600000, 0x0020217},
 {138551406, -34968445, 138656155, -34881955, 0x001000a},
 {138459868, -35174720, 139027540, -34683680, 0x001000c},
 {137423314, -33099090, 137628486, -32926111, 0x782004b},
@@ -11905,7 +12013,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {137240141, -35243000, 140036500, -32326000, 0x0ba0011},
 {134082295, -35067336, 137240141, -32386146, 0x0010015},
 {129000000, -38300000, 141000000, -26000000, 0x0010016},
-{129000000, -38300000, 141000000, -26000000, 0x0020217},
+{128999000, -38300000, 141005000, -25995000, 0x0020217},
 {147243600, -42872000, 147336807, -42817755, 0x2a7044a},
 {147273700, -42928500, 147363247, -42872000, 0x2a7044a},
 {147011912, -43201520, 147647288, -42710480, 0x001000c},
@@ -11954,7 +12062,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {146438505, -38728713, 149715515, -36047523, 0x0010015},
 {141200000, -38663000, 143161495, -34087000, 0x034000d},
 {141000000, -39206719, 151318000, -33977816, 0x0010016},
-{141000000, -39206719, 151318000, -33977816, 0x0020217},
+{140950000, -39260000, 151318000, -33977816, 0x0020217},
 {115792028, -32003245, 115892933, -31916755, 0x001000a},
 {115689500, -32274400, 116116000, -31669000, 0x027000c},
 {115700073, -32392510, 115844126, -32270201, 0x54f004b},
@@ -12063,7 +12171,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {146080000, -21260000, 149240000, -19019400, 0x33f0015},
 {138000000, -29181841, 154000000, -15300000, 0x37a0016},
 {138000000, -15300000, 146800000, -9182000, 0x0900012},
-{138000000, -29181841, 159267000, -9182000, 0x0020217},
+{137990000, -29181841, 159267000, -9182000, 0x0020217},
 {-47947500, -15840000, -47871000, -15735000, 0x025000a},
 {-48290000, -16052000, -47805657, -15570000, 0x001000c},
 {-47805657, -16052000, -47300000, -15570000, 0x0ab0010},
@@ -12177,6 +12285,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {-69434267, -11156000, -66610000, -8610000, 0x0a00011},
 {-71585069, -11090000, -69434267, -7850000, 0x026000d},
 {-74004000, -10050000, -71585069, -7100000, 0x4290015},
+{-74004000, -11156000, -66610000, -7100000, 0x0010016},
 {-74004000, -11156000, -66610000, -7100000, 0x0020217},
 {-49296589, -25489045, -49201450, -25402555, 0x001000a},
 {-49480000, -25707000, -49014305, -25168441, 0x022000c},
@@ -12295,7 +12404,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {-51761505, -22688818, -48931360, -20007628, 0x001000d},
 {-48931360, -22688818, -46101215, -20007628, 0x0010015},
 {-53228000, -25304000, -44099000, -19663000, 0x0010016},
-{-53228000, -25304000, -44099000, -19663000, 0x0020217},
+{-53228000, -25310000, -44099000, -19663000, 0x0020217},
 {-42829445, -5135745, -42742955, -5049255, 0x001000a},
 {-42863960, -5404120, -42395240, -4913080, 0x001000c},
 {-41871310, -3045610, -41626691, -2800991, 0xa9e004b},
@@ -12335,7 +12444,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {-56037296, -31620000, -52943703, -29025300, 0x01e000d},
 {-52943703, -32250000, -49888000, -29562200, 0x3c50015},
 {-57788100, -33750000, -49482400, -26922070, 0x0010016},
-{-57788100, -33750000, -49482400, -26922070, 0x0020217},
+{-57788100, -33752000, -49482400, -26922070, 0x0020217},
 {-44315645, -2568745, -44229155, -2482255, 0x001000a},
 {-44426241, -2957400, -44018000, -2403000, 0x023000c},
 {-47513870, -5584290, -47339930, -5411311, 0x782004b},
@@ -12533,7 +12642,9 @@ static const mminforec mminfo[NR_RECS+1] = {
 {-73508143, 41227770, -69858861, 42887549, 0x0020217},
 {-157904128, 21307000, -157811682, 21350245, 0x2a7044a},
 {-157882000, 21268000, -157779518, 21307000, 0x2a7044a},
-{-158281000, 21253500, -157647600, 21711600, 0x01a000c},
+{-158283000, 21290000, -157989062, 21590000, 0xc730447},
+{-158156000, 21480000, -157822111, 21720000, 0xbde0447},
+{-157989062, 21250000, -157640698, 21480000, 0xbde0447},
 {-156700000, 20574000, -156170000, 21032000, 0x0a50010},
 {-160300000, 21700000, -159260000, 22300000, 0x004010c},
 {-158310000, 21200000, -157607000, 21812000, 0x004010c},
@@ -13352,6 +13463,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {-73640369, 40498431, -73025825, 40989471, 0x001d88c},
 {-73025825, 40621191, -72411281, 41112231, 0x001e08c},
 {-72411281, 40805331, -71796737, 41296371, 0x001e88c},
+{-74256850, 40495560, -73640369, 40964920, 0x01ef08c},
 {-75235164, 44888000, -73320000, 45016000, 0x0340090},
 {-75883560, 44402200, -75232560, 44893240, 0x0b00890},
 {-75232560, 44402200, -74581560, 44893240, 0x0b01090},
@@ -13529,6 +13641,9 @@ static const mminforec mminfo[NR_RECS+1] = {
 {-89672711, 37603510, -89084207, 38094550, 0x001c888},
 {-89084207, 37603510, -88495703, 38094550, 0x001d088},
 {-88495703, 37603510, -87907199, 38094550, 0x001d888},
+{-89520000, 36969500, -89080000, 37603510, 0x028e088},
+{-89080000, 37050000, -88570000, 37603510, 0x023e888},
+{-88570000, 37050000, -88060000, 37603510, 0x023f088},
 {-89520000, 36969500, -89080000, 37603510, 0x0e7e090},
 {-89080000, 37050000, -88570000, 37603510, 0x0c8e890},
 {-88570000, 37050000, -88060000, 37603510, 0x0c8f090},
@@ -13649,7 +13764,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {-100004500, 33615700, -97200000, 36494024, 0x0bbe891},
 {-97200000, 33615700, -94431300, 36494024, 0x0bcf091},
 {-103005000, 33615700, -94431300, 37002500, 0x0020217},
-{-96927200, 46832555, -96762374, 46912300, 0x01a000a},
+{-96923000, 46832555, -96767400, 46905500, 0x019000a},
 {-97244062, 46704020, -96739538, 47049979, 0xf040047},
 {-101025865, 46640600, -100542136, 46975489, 0xe890047},
 {-97190356, 47819160, -96875644, 48030929, 0x931004b},
@@ -13871,7 +13986,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {-120000000, 38480000, -117000000, 41310000, 0x021000d},
 {-117000000, 38480000, -114039000, 41310000, 0x4250015},
 {-125000000, 31332000, -102041524, 42010000, 0x2b30016},
-{-120000000, 34950000, -114039000, 42010000, 0x0020217},
+{-120008000, 34950000, -114039000, 42010000, 0x0020217},
 {-112124933, 33404755, -112022106, 33491245, 0x001000a},
 {-111252000, 32029300, -110679700, 32482000, 0x01d000c},
 {-112453072, 33611384, -112349284, 33697874, 0x001008b},
@@ -14213,7 +14328,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {-120000000, 48998000, -110000000, 60000000, 0x0010016},
 {-120000000, 48998000, -110000000, 60000000, 0x0020217},
 {-79439582, 43622755, -79320418, 43709245, 0x001000a},
-{-79846600, 43404480, -79120680, 43912800, 0x01d000c},
+{-79846600, 43439000, -79120680, 43912800, 0x01c000c},
 {-75754500, 45404300, -75582886, 45466000, 0x3c1044b},
 {-75582886, 45424000, -75435625, 45495900, 0x3c1044b},
 {-75820373, 45317811, -75697847, 45404300, 0x3c1044b},
@@ -14473,7 +14588,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {92701194, 24245000, 95620712, 26919000, 0x001e88d},
 {91126000, 21930000, 94324762, 24245000, 0x01bf08d},
 {71660809, 9770405, 74371790, 12451595, 0x001288d},
-{92200000, 11130000, 94320000, 14940000, 0x029308d},
+{92200000, 11130000, 94320000, 14333000, 0x026308d},
 {92190000, 6730000, 93970000, 11000000, 0x030388d},
 {67050143, 5900143, 97416000, 37299857, 0x0010217},
 {112700000, -54780000, 159267000, -9182000, 0x0010017},
@@ -14486,6 +14601,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {-118403860, 28309343, -116586609, 29918057, 0x001288d},
 {-112669677, 17783805, -109869323, 20464995, 0x001308d},
 {-116119377, 17034705, -113319023, 19715895, 0x001388d},
+{-91632058, 21827524, -89338151, 23972476, 0x001408d},
 {-117320000, 31785945, -112189000, 32719000, 0x04d0091},
 {-116774659, 29104755, -113735977, 31785945, 0x0a90891},
 {-113735977, 29104755, -110697295, 31785945, 0x0a91091},
@@ -14544,7 +14660,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {39907000, 44244994, 40388000, 44907500, 0x0ee0010},
 {37200000, 43383000, 41743000, 45505561, 0x0860011},
 {36598000, 41183000, 49615000, 51246000, 0x0010216},
-{38684000, 43759000, 40774000, 45217500, 0x0020217},
+{38666000, 43756000, 40774000, 45217500, 0x0020217},
 {44615000, 43000000, 44717951, 43097650, 0x023000a},
 {44343820, 42810000, 44960000, 43301040, 0x001000c},
 {43874853, 42946020, 44343820, 43291979, 0xf04004b},
@@ -14631,7 +14747,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {38711440, 56058868, 39017517, 56231847, 0x782004b},
 {38272000, 55111000, 42967000, 56811000, 0x0860011},
 {26672000, 49555000, 48440000, 61615000, 0x0010216},
-{38272000, 55111000, 42967000, 56811000, 0x0020217},
+{38272000, 55111000, 42980000, 56820000, 0x0020217},
 {36097808, 51694377, 36236192, 51780867, 0x001000a},
 {35792024, 51470480, 36541976, 51961520, 0x001000c},
 {35029767, 52146966, 35425914, 52391585, 0xa9e004b},
@@ -14640,7 +14756,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {36718359, 51755710, 37085041, 51984489, 0x9ee004b},
 {34080500, 50910000, 38518000, 52442000, 0x07c0011},
 {26672000, 49555000, 48440000, 61615000, 0x0010216},
-{34080500, 50910000, 38518000, 52442000, 0x0020217},
+{34080500, 50900000, 38555000, 52442000, 0x0020217},
 {36210564, 54495000, 36365069, 54574500, 0x01c000a},
 {35816292, 54361380, 36613116, 54852420, 0x001000c},
 {36363208, 54954130, 36857192, 55240959, 0xc73004b},
@@ -14659,7 +14775,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {41718000, 53308000, 41956302, 53568359, 0x864044b},
 {39923000, 51590000, 43252000, 53823000, 0x0ae0011},
 {26672000, 49555000, 48440000, 61615000, 0x0010216},
-{39923000, 51590000, 43252000, 53823000, 0x0020217},
+{39910000, 51590000, 43252000, 53823000, 0x0020217},
 {34309000, 53217656, 34400941, 53285000, 0x2a7044a},
 {34244098, 53285000, 34342169, 53348143, 0x2a7044a},
 {33963708, 53014180, 34739700, 53505220, 0x001000c},
@@ -14689,14 +14805,14 @@ static const mminforec mminfo[NR_RECS+1] = {
 {39344855, 53721960, 39700745, 53933729, 0x931004b},
 {38669670, 53311800, 42705000, 55352700, 0x09a0011},
 {26672000, 49555000, 48440000, 61615000, 0x0010216},
-{38669670, 53311800, 42705000, 55352700, 0x0020217},
+{38660000, 53311800, 42705000, 55370000, 0x0020217},
 {47962535, 46306700, 48099087, 46383800, 0x01b000a},
 {47691688, 46038376, 48358312, 46529416, 0x001000c},
 {45697227, 47986471, 46389891, 48477511, 0x0b10010},
 {44969730, 46443380, 49040000, 48865100, 0x01c000d},
 {45838527, 45189350, 49615000, 47850000, 0x0a80011},
 {36598000, 41183000, 49615000, 51246000, 0x0010216},
-{44969730, 45189350, 49615000, 48867000, 0x0020217},
+{44969730, 45000000, 49615000, 48867000, 0x0020217},
 {37538581, 55705755, 37691380, 55792245, 0x001000a},
 {37174200, 55508961, 37975000, 56000000, 0x001000c},
 {37468000, 55340000, 37621388, 55510000, 0x54f044b},
@@ -14851,7 +14967,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {29888408, 55589000, 30706064, 56080040, 0x001c88c},
 {30706064, 55589000, 31523720, 56080040, 0x001d08c},
 {26672000, 49555000, 48440000, 61615000, 0x0010216},
-{27323000, 55589000, 31526500, 59019500, 0x0020217},
+{27317000, 55589000, 31526500, 59019500, 0x0020217},
 {40859776, 57724755, 41021224, 57811245, 0x001000a},
 {40513036, 57417280, 41377564, 57908320, 0x001000c},
 {41298977, 58343310, 41733022, 58572089, 0x9ee004b},
@@ -14893,7 +15009,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {37200000, 43383000, 41743000, 45505561, 0x0860011},
 {36598000, 44803239, 41280000, 46879000, 0x018000d},
 {36598000, 41183000, 49615000, 51246000, 0x0010216},
-{36598000, 43383000, 41743000, 46879000, 0x0020217},
+{36590000, 43383000, 41743000, 46881000, 0x0020217},
 {44201735, 46270455, 44326665, 46356945, 0x001000a},
 {43952788, 46134980, 44619412, 46626020, 0x001000c},
 {44250393, 47662310, 44587207, 47891089, 0x9ee004b},
@@ -15208,7 +15324,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {47235000, 53974000, 51150000, 56676000, 0x0b50011},
 {50430000, 53974000, 54270000, 56676000, 0x021000d},
 {41775000, 49802000, 61703000, 61676000, 0x0010216},
-{47235000, 53974000, 54270000, 56676000, 0x0020217},
+{47235000, 53974000, 54270000, 56680000, 0x0020217},
 {50070000, 53169000, 50230397, 53242200, 0x01a000a},
 {49818661, 53055000, 50398122, 53398000, 0xf040447},
 {49232000, 53315000, 49885463, 53600000, 0xe890447},
@@ -15221,7 +15337,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {47924000, 52225772, 52563000, 54677000, 0x09c0011},
 {48693650, 51773000, 52563000, 54677000, 0x021000d},
 {41775000, 49802000, 61703000, 61676000, 0x0010216},
-{47924000, 51773000, 52563000, 54677000, 0x0020217},
+{47924000, 51773000, 52563000, 54680000, 0x0020217},
 {45927808, 51500055, 46066192, 51586545, 0x001000a},
 {45530000, 51317000, 46355768, 51788520, 0x01c000c},
 {47666176, 51898710, 47943423, 52071689, 0x782044b},
@@ -15456,7 +15572,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {84900000, 52159000, 89250000, 54753702, 0x01e000d},
 {70354000, 49070000, 99271000, 61033000, 0x2e70216},
 {84454000, 52159000, 89389000, 56833000, 0x0020217},
-{85880000, 51912000, 86121550, 51995700, 0x017000a},
+{85880629, 51908871, 86019974, 51995361, 0x001000a},
 {85595424, 51701680, 86345376, 52192720, 0x001000c},
 {85512055, 51173640, 85818144, 51366959, 0x864044b},
 {86995365, 52171000, 87430573, 52310000, 0x864044b},
@@ -15604,7 +15720,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {133750000, 42912000, 137377000, 45572000, 0x001000d},
 {133360000, 45572000, 139015300, 47358897, 0x2830015},
 {130400100, 42290000, 139015300, 48459900, 0x0010016},
-{130400100, 42290000, 139015300, 48459900, 0x0020217},
+{130393000, 42290000, 139015300, 48459900, 0x0020217},
 {132864400, 48737700, 132989781, 48826745, 0x020000a},
 {132551564, 48517580, 133254644, 49008620, 0x001000c},
 {133636610, 48473940, 133926589, 48667259, 0x864044b},
@@ -15658,7 +15774,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {122716720, 56329405, 127513071, 59010595, 0x001000d},
 {113648601, 60059405, 118951399, 62740595, 0x0010015},
 {105526600, 55489900, 148500000, 64300000, 0x2310016},
-{105526600, 64166000, 162854200, 77118200, 0x07b0012},
+{105526600, 64300000, 162854200, 74060000, 0x06b0012},
 {105526600, 55489900, 162854200, 77118200, 0x0020217},
 {-141010000, 41660000, -52600000, 85000000, 0x0010017},
 {44270000, 77850000, 114300000, 84000000, 0x06e0092},
@@ -15721,7 +15837,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {109713000, 18376000, 109993838, 18460000, 0x680044b},
 {108560000, 18100000, 111320000, 20180000, 0x0960011},
 {110700000, 15720000, 113000000, 17900000, 0x001000d},
-{113600000, 13900000, 117900000, 16440000, 0x2ec0015},
+{113600000, 14700000, 117900000, 16440000, 0x26d0015},
 {108560000, 13900000, 117900000, 20180000, 0x0010216},
 {108560000, 13900000, 117900000, 20180000, 0x0020217},
 {106204523, 38420055, 106314077, 38506545, 0x001000a},
@@ -16180,7 +16296,8 @@ static const mminforec mminfo[NR_RECS+1] = {
 {120380471, 49035730, 121088759, 49526770, 0x0b13890},
 {117362241, 49192480, 118070529, 49683520, 0x0b14090},
 {123768897, 50177475, 124492809, 50668515, 0x0b14890},
-{97150000, 37400000, 126120000, 53343000, 0x30c0016},
+{97150000, 37400000, 115400000, 45600000, 0x0810012},
+{115400000, 37400000, 126120000, 53343000, 0x5030016},
 {97150000, 37400000, 126120000, 53343000, 0x0020217},
 {126595896, 45696255, 126718904, 45782745, 0x001000a},
 {126470000, 45578430, 126839239, 45894000, 0xc730447},
@@ -16362,8 +16479,34 @@ static const mminforec mminfo[NR_RECS+1] = {
 {79645247, 36867024, 80228543, 37358064, 0x0b02890},
 {76959561, 38171324, 77548065, 38662364, 0x0b13090},
 {82663615, 41466924, 83288575, 41957964, 0x0b03890},
-{73479000, 34294000, 96451000, 49183500, 0x33e0016},
-{73479000, 34294000, 96451000, 49183500, 0x0020217},
+{82400000, 46179133, 85400000, 47300000, 0x07b0091},
+{85400000, 46179133, 88700000, 49180000, 0x0c10891},
+{88700000, 46179133, 91080000, 48250000, 0x0bd1091},
+{79750000, 43778215, 83442500, 46179133, 0x09f1891},
+{83442500, 43778215, 87136500, 46179133, 0x09f2091},
+{87136500, 43778215, 91080000, 46179133, 0x09a2891},
+{91080000, 43778215, 95800000, 45250000, 0x06e3091},
+{73494042, 38415835, 76890216, 41097025, 0x0a98091},
+{76890216, 38415835, 80286390, 41097025, 0x0a98891},
+{80286390, 38415835, 83682564, 41097025, 0x0a99091},
+{83682564, 38415835, 87078738, 41097025, 0x0a99891},
+{87078738, 38415835, 90474912, 41097025, 0x0a9a091},
+{90474912, 38415835, 93850000, 41097025, 0x0a9a891},
+{77621258, 41097025, 81166387, 43778215, 0x0a85091},
+{81166387, 41097025, 84711516, 43778215, 0x0a85891},
+{84711516, 41097025, 88256645, 43778215, 0x0a86091},
+{88256645, 41097025, 91801774, 43778215, 0x0a86891},
+{91801774, 40923000, 94070000, 43778215, 0x0d97091},
+{94070000, 41097025, 96451000, 43778215, 0x0cd7891},
+{74450000, 35500000, 77300000, 38415835, 0x0bcb091},
+{77301570, 35734645, 80578580, 38415835, 0x0a9b891},
+{80578580, 35734645, 83855590, 38415835, 0x0a9c091},
+{83855590, 35734645, 87132600, 38415835, 0x0a9c891},
+{87132600, 36220000, 89250000, 38415835, 0x0bfd091},
+{89250000, 36000000, 91400000, 38415835, 0x0c6e091},
+{77300000, 35200000, 85750000, 35734645, 0x02ee891},
+{77300000, 33360000, 80493080, 36000000, 0x0a7f091},
+{73479000, 33360000, 96451000, 49183500, 0x0020217},
 {82244000, 45260000, 91080000, 49200000, 0x0890892},
 {76623000, 39100000, 86500000, 45400000, 0x09c1092},
 {86500000, 39100000, 96510000, 45260000, 0x0991892},
@@ -16389,7 +16532,7 @@ static const mminforec mminfo[NR_RECS+1] = {
 {112200000, 20400000, 118000000, 26400500, 0x0b5b892},
 {118000000, 21750000, 122500000, 26400500, 0x0b5c092},
 {110700000, 13900000, 117900000, 17900000, 0x082c892},
-{73495000, 18158000, 134780000, 53563000, 0x003021c},
+{73495000, 13900000, 134780000, 53563000, 0x003021c},
 {-162125917, 5840551, -162039427, 5927041, 0x001000a},
 {-162492268, 6289623, -162262218, 6518402, 0x9ee004b},
 {-169642729, 16623423, -169422137, 16835192, 0x931004b},
diff --git a/mapcodelib/mapcoder.c b/mapcodelib/mapcoder.c
index 2cbece0..49451df 100644
--- a/mapcodelib/mapcoder.c
+++ b/mapcodelib/mapcoder.c
@@ -18,44 +18,47 @@
 #include <stdlib.h> // atof
 #include <ctype.h>  // toupper
 #include "mapcoder.h"
-#define VERSION160
+
+#define SUPPORT_HIGH_PRECISION
+
+/*
+  no threadsafe:
+    disambiguate_iso3
+*/
+
 
 #ifndef RELEASENEAT
 #else
 
 #include "basics.h"
 
-#define ISEARTH(c) ((c)==ccode_earth)
-#define ISGOODAREA(m) ((m)>=0)
-#define  CCODE_ERR   -1
-
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 //
-//  Global variables
+//  Structures
 //
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
-static const char *cached_iso3="@";   // cache for ccode_of_iso3
-static char disambiguate_iso3[4] = { '1','?','?',0 } ; // cache for disambiguation
-static char entity_iso3_result[4];  // cache for entity_iso3
-static int current_ccode=-1; // cache for setup_country
-
+typedef struct {
+  // input
+  long    lat32,lon32;
+  double  fraclat,fraclon;
+  // output
+  Mapcodes *mapcodes;
+} encodeRec;
+
+typedef struct {
+  // input
+  const char *orginput;   // original full input string
+  char minput[MAX_MAPCODE_RESULT_LEN]; // room to manipulate clean copy of input
+  const char *mapcode;    // input mapcode (first character of proper mapcode excluding territory code)
+  const char *extension;  // input extension (or empty)
+  int context;            // input territory context (or negative)
+  const char *iso;        // input territory alphacode (context)
+  // output
+  double lat,lon;         // result
+  long lat32,lon32;       // result in integer arithmetic (millionts of degrees)
+} decodeRec;
 
-#define MAXGLOBALRESULTS 32 // The worst actually seems to be 14, which is at 52.050500, 113.468600
-#define WORSTCASE_MAPCODE_BYTES 16 // worst case is high-precision earth xxxxx.yyyy-zz, rounded upwords to multiple of 4 bytes (assuming latin-only results)
-static char global_storage[2048]; // cyclic cache for results
-static int storage_ptr;
-static char *addstorage(const char *str)
-{
-  int len=strlen(str)+1; // bytes needed;
-  storage_ptr &= (2048-1);
-  if (storage_ptr<0 || storage_ptr+len>2048-2) storage_ptr=0;
-  strcpy(global_storage+storage_ptr,str);
-  storage_ptr+=len;
-  return global_storage+storage_ptr-len;
-}
-static char **global_results;
-static int nr_global_results;
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 //
@@ -66,19 +69,24 @@ static int nr_global_results;
 static int firstrec(int ccode) { return data_start[ccode]; }
 static int lastrec(int ccode)  { return data_start[ccode+1]-1; }
 
-static int mIsUsaState( int ccode )       { return (ccode>=usa_from && ccode<=usa_upto); } // ccode_usa
-static int mIsIndiaState( int ccode )     { return (ccode>=ind_from && ccode<=ind_upto); } // ccode_ind
-static int mIsCanadaState( int ccode )    { return (ccode>=can_from && ccode<=can_upto); } // ccode_can
-static int mIsAustraliaState( int ccode ) { return (ccode>=aus_from && ccode<=aus_upto); } // ccode_aus
-static int mIsMexicoState( int ccode )    { return (ccode>=mex_from && ccode<=mex_upto); } // ccode_mex
-static int mIsBrazilState( int ccode )    { return (ccode>=bra_from && ccode<=bra_upto); } // ccode_bra
-static int mIsChinaState( int ccode )     { return (ccode>=chn_from && ccode<=chn_upto); } // ccode_chn
-static int mIsRussiaState( int ccode )    { return (ccode>=rus_from && ccode<=rus_upto); } // ccode_rus
-static int isSubdivision( int ccode )  { return mIsUsaState(ccode) || mIsIndiaState(ccode) || mIsCanadaState(ccode) || mIsAustraliaState(ccode) || mIsMexicoState(ccode) || mIsBrazilState(ccode) || mIsChinaState(ccode) || mIsRussiaState(ccode); }
-
-// V160: remove iscountry, renames rcodex pipetype isnameless pipeletter smartdiv fast_encode/BASE31 encode6/SixWide addpostfix=encodeExtension add2res=, codexlow=>postlen, dx=>prelen
+static int ParentTerritoryOf(int ccode) // returns parent, or -1
+{
+  if (ccode>=usa_from && ccode<=usa_upto) return ccode_usa;
+  if (ccode>=ind_from && ccode<=ind_upto) return ccode_ind;
+  if (ccode>=can_from && ccode<=can_upto) return ccode_can;
+  if (ccode>=aus_from && ccode<=aus_upto) return ccode_aus;
+  if (ccode>=mex_from && ccode<=mex_upto) return ccode_mex;
+  if (ccode>=bra_from && ccode<=bra_upto) return ccode_bra;
+  if (ccode>=rus_from && ccode<=rus_upto) return ccode_rus;
+  if (ccode>=chn_from && ccode<=chn_upto) return ccode_chn;
+  return -1;
+}
+
+static int isSubdivision( int ccode )  { return (ParentTerritoryOf(ccode)>=0); }
+
 static int coDex(int m)             { int c=mminfo[m].flags & 31; return 10*(c/5) + ((c%5)+1); }
-// int iscountry(int m)      { return mminfo[m].flags & 32; }
+static int prefixLength(int m)      { int c=mminfo[m].flags & 31; return (c/5); }
+static int postfixLength(int m)     { int c=mminfo[m].flags & 31; return ((c%5)+1); }
 static int isNameless(int m)        { return mminfo[m].flags & 64; }
 static int recType(int m)           { return (mminfo[m].flags>>7) & 3; }
 static int isRestricted(int m)      { return mminfo[m].flags & 512; }
@@ -96,17 +104,34 @@ static void get_boundaries(int m,long *minx, long *miny, long *maxx, long *maxy
   *maxy = mm->maxy;
 }
 
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//
-//  Helper routines
-//
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+static int isInRange(long x,long minx,long maxx) // returns nonzero if x in the range minx...maxx
+{
+  if ( minx<=x && x<maxx ) return 1;
+  if (x<minx) x+=360000000; else x-=360000000; // 1.32 fix FIJI edge case
+  if ( minx<=x && x<maxx ) return 1;
+  return 0;
+}
 
-static void makeup(char *s) // strupr for latin
+static int fitsInside( long x, long y, int m )
 {
-  char *t;
-  for(t=s;*t!=0;t++)
-      *t = toupper(*t);
+  const mminforec *mm = &mminfo[m];
+  return ( mm->miny <= y && y < mm->maxy && isInRange(x,mm->minx,mm->maxx) );
+}
+
+static long xDivider4( long miny, long maxy )
+{
+  if (miny>=0) // both above equator? then miny is closest
+    return xdivider19[ (miny)>>19 ];
+  if (maxy>=0) // opposite sides? then equator is worst
+    return xdivider19[0];
+  return xdivider19[ (-maxy)>>19 ]; // both negative, so maxy is closest to equator
+}
+
+static int fitsInsideWithRoom( long x, long y, int m )
+{
+  const mminforec *mm = &mminfo[m];
+  long xdiv8 = xDivider4(mm->miny,mm->maxy)/4; // should be /8 but there's some extra margin
+  return ( mm->miny-60 <= y && y < mm->maxy+60 && isInRange(x,mm->minx - xdiv8, mm->maxx + xdiv8) );
 }
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -115,7 +140,7 @@ static void makeup(char *s) // strupr for latin
 //
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
-static const char *entity_iso3(int ccode)
+static const char *get_entity_iso3(char *entity_iso3_result,int ccode)
 {
   if (ccode<0 || ccode>=MAX_MAPCODE_TERRITORY_CODE) ccode=ccode_earth; // solve bad args
   memcpy(entity_iso3_result,entity_iso+ccode*4,3);
@@ -123,11 +148,7 @@ static const char *entity_iso3(int ccode)
   return entity_iso3_result;
 }
 
-static void disambiguate( int country ) // 1=USA 2=IND 3=CAN 4=AUS 5=MEX 6=BRA 7=RUS 8=CHI
-{
-  disambiguate_iso3[0] = country+'0';
-}
-
+// static char disambiguate_iso3[4] = { '1','?','?',0 } ; // cache for disambiguation
 static int disambiguate_str( const char *s, int len ) // returns disambiguation >=1, or negative if error
 {
   int res;
@@ -136,20 +157,27 @@ static int disambiguate_str( const char *s, int len ) // returns disambiguation
   char country[4];
   if (s[0]==0 || s[1]==0) return -27; // solve bad args
   if (len!=2 && len!=3) return -923; // solve bad args
-  memcpy(country,s,len); country[len]=0; makeup(country);
+  memcpy(country,s,len); country[len]=0;
+  {
+    char *t;
+    for(t=country;*t!=0;t++)
+        *t = toupper(*t);
+  }
   f=strstr(p,country);
   if (f==NULL)
     return -23; // unknown country
   res = 1 + ((f-p)/(len+1));
-  disambiguate(res);
   return res;
 }
 
+
 // returns coode, or negative if invalid
-static int ccode_of_iso3(const char *in_iso)
+static int ccode_of_iso3(const char *in_iso, int parentcode )
 {
+  static char disambiguate_iso3[4] = { '1','?','?',0 } ; // cache for disambiguation
+  const char *aliases=ALIASES;
   char iso[4];
-  const char *s = cached_iso3; // assume cached index
+  const char *s;
 
   if (in_iso && in_iso[0] && in_iso[1] )
   {
@@ -157,95 +185,88 @@ static int ccode_of_iso3(const char *in_iso)
     {
       if (in_iso[2]=='-')
       {
-        disambiguate_str(in_iso,2);
+        parentcode=disambiguate_str(in_iso,2);
         in_iso+=3;
-        cached_iso3="@";
       }
       else if (in_iso[3]=='-')
       {
-        disambiguate_str(in_iso,3);
+        parentcode=disambiguate_str(in_iso,3);
         in_iso+=4;
-        cached_iso3="@";
       }
     }
   } else return -23; // solve bad args
 
+  if (parentcode>0)
+    disambiguate_iso3[0] = (char)('0'+parentcode);
+
   // make (uppercased) copy of at most three characters
   iso[0]=toupper(in_iso[0]);
   if (iso[0]) iso[1]=toupper(in_iso[1]);
   if (iso[1]) iso[2]=toupper(in_iso[2]);
   iso[3]=0;
 
-  if ( memcmp(s,iso,3)!=0 ) // not equal to cache?
+  if ( iso[2]==0 || iso[2]==' ' ) // 2-letter iso code?
   {
-    const char *aliases=ALIASES;
-    if ( iso[2]==0 || iso[2]==' ' ) // 2-letter iso code?
+    disambiguate_iso3[1] = iso[0];
+    disambiguate_iso3[2] = iso[1];
+
+    s = strstr(entity_iso,disambiguate_iso3); // search disambiguated 2-letter iso
+    if (s==NULL)
+    {
+      s = strstr(aliases,disambiguate_iso3); // search in aliases
+      if ( s && s[3]=='=' )
+      {
+        memcpy(iso,s+4,3);
+        s = strstr(entity_iso,iso); // search disambiguated 2-letter iso
+      } else s=NULL;
+    }
+    if (s==NULL)
     {
-      disambiguate_iso3[1] = iso[0];
-      disambiguate_iso3[2] = iso[1];
-      if ( memcmp(s,disambiguate_iso3,3)!=0 ) // still not equal to cache?
+      // find the FIRST disambiguation option, if any
+      for(s=entity_iso-1;;)
       {
-        s = strstr(entity_iso,disambiguate_iso3); // search disambiguated 2-letter iso
+        s = strstr(s+1,disambiguate_iso3+1);
         if (s==NULL)
-        {
-          s = strstr(aliases,disambiguate_iso3); // search in aliases
-          if ( s && s[3]=='=' )
-          {
-            memcpy(iso,s+4,3);
-            s = strstr(entity_iso,iso); // search disambiguated 2-letter iso
-          } else s=NULL;
+          break;
+        if (s && s[-1]>='1' && s[-1]<='9') {
+          s--;
+          break;
         }
-        if (s==NULL)
+      }
+      if (s==NULL)
+      {
+        // find first disambiguation option in aliases, if any
+        for(s=aliases-1;;)
         {
-          // find the FIRST disambiguation option, if any
-          for(s=entity_iso-1;;)
-          {
-            s = strstr(s+1,disambiguate_iso3+1);
-            if (s==NULL)
-              break;
-            if (s && s[-1]>='1' && s[-1]<='9') {
-              s--;
-              break;
-            }
-          }
+          s = strstr(s+1,disambiguate_iso3+1);
           if (s==NULL)
-          {
-            // find first disambiguation option in aliases, if any
-            for(s=aliases-1;;)
-            {
-              s = strstr(s+1,disambiguate_iso3+1);
-              if (s==NULL)
-                break;
-              if (s && s[-1]>='1' && s[-1]<='9') {
-                memcpy(iso,s+3,3);
-                s = strstr(entity_iso,iso); // search disambiguated 2-letter iso
-                break;
-              }
-            }
+            break;
+          if (s && s[-1]>='1' && s[-1]<='9') {
+            memcpy(iso,s+3,3);
+            s = strstr(entity_iso,iso); // search disambiguated 2-letter iso
+            break;
           }
-
-          if (s==NULL)
-            return -26;
-          cached_iso3 = s; // cache new result!
         }
       }
+
+      if (s==NULL)
+        return -26;
     }
-    else
+  }
+  else
+  {
+    s = strstr(entity_iso,iso); // search 3-letter iso
+    if (s==NULL)
     {
-      s = strstr(entity_iso,iso); // search 3-letter iso
-      if (s==NULL)
-      {
-          s = strstr(aliases,iso); // search in aliases
-          if ( s && s[3]=='=' )
-          {
-            memcpy(iso,s+4,3);
-            s = strstr(entity_iso,iso);
-          } else s=NULL;
-      }
-      if (s==NULL)
-        return -23;
-      cached_iso3 = s; // cache new result!
+        s = strstr(aliases,iso); // search in aliases
+        if ( s && s[3]=='=' )
+        {
+          memcpy(iso,s+4,3);
+          s = strstr(entity_iso,iso);
+        } else s=NULL;
     }
+    if (s==NULL)
+      return -23;
   }
   // return result
   return (s-entity_iso)/4;
@@ -258,12 +279,10 @@ static int ccode_of_iso3(const char *in_iso)
 //
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
-// V160: add ExtraDigits as parameter
-static double fraclon,fraclat;
-static void encodeExtension(char *result,long extrax4,long extray,long dividerx4,long dividery,int extraDigits,int ydirection) // append extra characters to result for more precision
+static void encodeExtension(char *result,long extrax4,long extray,long dividerx4,long dividery,int extraDigits,int ydirection,const encodeRec *enc) // append extra characters to result for more precision
 {
-#ifndef VERSION160 // old integer-arithmetic version
-  #define MAXPRECISIONDIGITS 2
+#ifndef SUPPORT_HIGH_PRECISION // old integer-arithmetic version
+  if (extraDigits<0) extraDigits=0; else if (extraDigits>2) extraDigits=2;
   while (extraDigits-->0)
   {
     long gx=((30*extrax4)/dividerx4);
@@ -281,10 +300,11 @@ static void encodeExtension(char *result,long extrax4,long extray,long dividerx4
     *s++ = 0;
   }
 #else // new floating-point version
-  #define MAXPRECISIONDIGITS 8
   char *s = result+strlen(result);
-  double encx = (extrax4+4*fraclon) / (dividerx4);
-  double ency = (extray +  fraclat*ydirection) / (dividery );
+  double encx = (extrax4+4* enc->fraclon) / (dividerx4);
+  double ency = (extray +   enc->fraclat*ydirection) / (dividery );
+
+  if (extraDigits<0) extraDigits=0; else if (extraDigits>MAX_PRECISION_DIGITS) extraDigits=MAX_PRECISION_DIGITS;
 
   if (extraDigits>0)
     *s++ = '-';
@@ -316,22 +336,22 @@ static void encodeExtension(char *result,long extrax4,long extray,long dividerx4
 #endif
 }
 
+#define decodeChar(c) decode_chars[(unsigned char)c] // force c to be in range of the index, between 0 and 255
 
-
-static const char *extrapostfix="";
-static double extrax,extray;
-static void decodeExtension(long *nx,long *ny, long dividerx4,long dividery,int ydirection) // add extra precision to a coordinate based on extra chars
+// this routine takes the integer-arithmeteic decoding results (in millionths of degrees), adds any floating-point precision digits, and returns the result (still in millionths)
+static void decodeExtension(decodeRec *dec, long dividerx4,long dividery,int ydirection)
 {
-#ifndef VERSION160 // old integer-arithmetic version
+  const char *extrapostfix = dec->extension;
+#ifndef SUPPORT_HIGH_PRECISION // old integer-arithmetic version
   long extrax,extray;
   if (*extrapostfix) {
     int column1,row1,column2,row2,c1,c2;
     c1 = extrapostfix[0];
-    c1 = decode_chars[(unsigned int)c1];
+    c1 = decodeChar(c1);
     if (c1<0) c1=0; else if (c1>29) c1=29;
     row1 =(c1/5); column1 = (c1%5);
     c2 = (extrapostfix[1]) ? extrapostfix[1] : 72; // 72='H'=code 15=(3+2*6)
-    c2 = decode_chars[(unsigned int)c2];
+    c2 = decodeChar(c2);
     if (c2<0) c2=0; else if (c2>29) c2=29;
     row2 =(c2/6); column2 = (c2%6);
 
@@ -342,25 +362,22 @@ static void decodeExtension(long *nx,long *ny, long dividerx4,long dividery,int
     extrax = (dividerx4/8);
     extray = (dividery/2);
   }
-
-  extrax = *nx + extrax;
-  extray = *ny + extray*ydirection;
-
-  *nx = extrax;
-  *ny = extray;
+  extray *= ydirection;
+  dec->lon32 = extrax + dec->lon32;
+  dec->lat32 = extray + dec->lat32;
 #else // new floating-point version
   double dividerx=dividerx4/4.0,processor=1.0;
-  extrax=0;
-  extray=0;
+  dec->lon=0;
+  dec->lat=0;
   while (*extrapostfix) {
     int column1,row1,column2,row2;
     double halfcolumn=0;
     int c1 = *extrapostfix++;
-    c1 = decode_chars[(unsigned int)c1];
+    c1 = decodeChar(c1);
     if (c1<0) c1=0; else if (c1>29) c1=29;
     row1 =(c1/5); column1 = (c1%5);
     if (*extrapostfix) {
-      int c2 = decode_chars[(unsigned int)*extrapostfix++];
+      int c2 = decodeChar(*extrapostfix++);
       if (c2<0) c2=0; else if (c2>29) c2=29;
       row2 =(c2/6); column2 = (c2%6);
     }
@@ -371,69 +388,26 @@ static void decodeExtension(long *nx,long *ny, long dividerx4,long dividery,int
     }
 
     processor *= 30;
-    extrax += ((column1*6 + column2 ))/processor;
-    extray += ((row1*5 + row2 - halfcolumn))/processor;
+    dec->lon += ((column1*6 + column2 ))/processor;
+    dec->lat += ((row1*5 + row2 - halfcolumn))/processor;
   }
 
-  extrax += (0.5/processor);
-  extray += (0.5/processor);
+  dec->lon += (0.5/processor);
+  dec->lat += (0.5/processor);
 
-  extrax *= dividerx;
-  extray *= dividery;
+  dec->lon *= dividerx;
+  dec->lat *= (dividery * ydirection);
 
-  extrax = *nx + extrax;
-  extray = *ny + extray*ydirection;
+  dec->lon += dec->lon32;
+  dec->lat += dec->lat32;
 
-  *nx = (long)extrax;
-  *ny = (long)extray;
+  // also convert back to long
+  dec->lon32 = (long)dec->lon;
+  dec->lat32 = (long)dec->lat;
 #endif
 }
 
 
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//
-//  SECOND-LEVEL ECCODING/DECODING : GRID
-//
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-static long x_divider( long miny, long maxy )
-{
-  if (miny>=0) // both above equator? then miny is closest
-    return xdivider19[ (miny)>>19 ];
-  if (maxy>=0) // opposite sides? then equator is worst
-    return xdivider19[0];
-  return xdivider19[ (-maxy)>>19 ]; // both negative, so maxy is closest to equator
-}
-
-static int isInRange(long x,long minx,long maxx) // returns nonzero if x in the range minx...maxx
-{
-  if ( minx<=x && x<maxx ) return 1;
-  if (x<minx) x+=360000000; else x-=360000000; // 1.32 fix FIJI edge case
-  if ( minx<=x && x<maxx ) return 1;
-  return 0;
-}
-
-static int isInArea(long x,long y,int ccode) // returns nonzero if x,y in area (i.e. certain to generate at least one code); (0 can also mean iso3 is an invalid iso code)
-{
-  if (ccode<0) return 0; // solve bad args
-  {
-    long minx,miny,maxx,maxy;
-    getboundaries(lastrec(ccode),minx,miny,maxx,maxy);
-    if ( y <  miny ) return 0; // < miny!
-    if ( y >= maxy ) return 0; // >= miny!
-    return isInRange(x,minx,maxx);
-  }
-}
-
-// TODO: Unused code - remove or place in mapcoder.h and expose with doubles.
-static int findAreaFor(long x,long y,int ccode) // returns next ccode returns -1 when no more  contain x,y; pass -1 the first time, pass previous ccode to find the next return value
-{
-  while( (++ccode) < MAX_MAPCODE_TERRITORY_CODE )
-    if ( isInArea(x,y,ccode) )
-      return ccode;
-  return -1;
-}
-
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 //
@@ -458,7 +432,7 @@ static long decodeBase31( const char *code )
   long value=0;
   while (*code!='.' && *code!=0 )
   {
-    value = value*31 + decode_chars[(unsigned int)*code++];
+    value = value*31 + decodeChar(*code++);
   }
   return value;
 }
@@ -488,7 +462,7 @@ static void encode_triple( char *result, long difx,long dify )
 static void decode_triple( const char *result, long *difx, long *dify )
 {
       // decode the first character
-      int c1 = decode_chars[(unsigned int)*result++];
+      int c1 = decodeChar(*result++);
       if ( c1<24 )
       {
         long m = decodeBase31(result);
@@ -548,46 +522,50 @@ static void decodeSixWide( long v, long width, long height, long *x, long *y )
 }
 
 
-static void decodeGrid( const char* input,long *nx,long *ny, int m, long minx, long miny, long maxx, long maxy )
+// decodes dec->mapcode in context of territory rectangle m
+static int decodeGrid(decodeRec *dec, int m, int hasHeaderLetter )
 {
+  const char* input = (hasHeaderLetter ? dec->mapcode+1 : dec->mapcode);
   int codexlen = strlen(input)-1;
-  long dc = (long)(strchr(input,'.')-input);
+  long prelen = (long)(strchr(input,'.')-input);
   char result[MAX_PROPER_MAPCODE_LEN+1];
 
-  if (codexlen>MAX_PROPER_MAPCODE_LEN) return; // solve bad args
+  if (codexlen>MAX_PROPER_MAPCODE_LEN) return -109;
   strcpy(result,input);
-  if (dc==1 && codexlen==5)
+  if (prelen==1 && codexlen==5)
   {
-    result[1]=result[2]; result[2]='.'; dc++;
+    result[1]=result[2]; result[2]='.'; prelen++;
   }
 
   {
-    long postlen = codexlen-dc;
-    long codex = 10*dc + postlen;
+    long postlen = codexlen-prelen;
+    long codex = 10*prelen + postlen;
     long divx,divy;
 
     divy = smartDiv(m);
     if (divy==1)
     {
-      divx = xside[dc];
-      divy = yside[dc];
+      divx = xside[prelen];
+      divy = yside[prelen];
     }
     else
     {
-      long pw = nc[dc];
+      long pw = nc[prelen];
       divx = ( pw / divy );
       divx = (long)( pw / divy );
     }
 
-    if ( dc==4 && divx==xside[4] && divy==yside[4] )
+    if ( prelen==4 && divx==xside[4] && divy==yside[4] )
     {
       char t = result[1]; result[1]=result[2]; result[2]=t;
     }
 
     {
       long relx=-1,rely=-1,v=0;
+      long minx,maxx,miny,maxy;
+      getboundaries(m,minx,miny,maxx,maxy);
 
-      if ( dc <= MAXFITLONG )
+      if ( prelen <= MAXFITLONG )
       {
         v = decodeBase31(result);
 
@@ -609,7 +587,7 @@ static void decodeGrid( const char* input,long *nx,long *ny, int m, long minx, l
         long xgridsize = (maxx-minx+divx-1)/divx; // lonlat per cell
 
         if (relx<0 || rely<0 || relx>=divx || rely>=divy)
-          return;
+          return -111;
 
         // and then encodde relative to THE CORNER of this cell
         rely = miny + (rely*ygridsize);
@@ -618,10 +596,10 @@ static void decodeGrid( const char* input,long *nx,long *ny, int m, long minx, l
         {
           long dividery = ( (((ygridsize))+yside[postlen]-1)/yside[postlen] );
           long dividerx = ( (((xgridsize))+xside[postlen]-1)/xside[postlen] );
-          // decoderelative( result+dc+1,nx,ny, relx,rely, dividery,dividerx );
+          // decoderelative
 
           {
-            char *r = result+dc+1;
+            char *r = result+prelen+1;
             long difx,dify;
 
             if ( postlen==3 ) // decode special
@@ -641,28 +619,34 @@ static void decodeGrid( const char* input,long *nx,long *ny, int m, long minx, l
             // reverse y-direction
             dify = yside[postlen]-1-dify;
 
-            *nx = relx+(difx * dividerx);
-            *ny = rely+(dify * dividery);
-            decodeExtension(nx,ny,  dividerx<<2,dividery,1); // grid
+            dec->lon32 = relx+(difx * dividerx);
+            dec->lat32 = rely+(dify * dividery);
+            decodeExtension(dec,  dividerx<<2,dividery,1); // grid
           } // decoderelative
 
         }
       }
     }
   }
-} // decodeGrid
+  return 0;
+}
 
 
 
 
-static int use_high_precision=0; // GLOBAL nr of letters of high-precision postfix (if any)
-static void encodeGrid( char* result, long x,long y, int m, int codex, long minx, long miny, long maxx, long maxy )
+
+static void encodeGrid( char* result, const encodeRec *enc, int const m, int extraDigits, char headerLetter )
 {
-  int orgcodex=codex;
-  *result=0;
-  if ( maxx<=minx || maxy<=miny )
-    return;
+  long minx,miny,maxx,maxy;
+  long y= enc->lat32,x= enc->lon32;
+  int orgcodex=coDex(m);
+  int codex=orgcodex;
+  if (codex==21) codex=22;
   if (codex==14) codex=23;
+  getboundaries(m,minx,miny,maxx,maxy);
+
+  *result=0;
+  if (headerLetter) result++;
 
   { // encode
     long divx,divy;
@@ -762,230 +746,63 @@ static void encodeGrid( char* result, long x,long y, int m, int codex, long minx
           result[2]=result[1]; result[1]='.';
         }
 
-        encodeExtension(result,extrax<<2,extray,dividerx<<2,dividery,use_high_precision,1); // grid
+        encodeExtension(result,extrax<<2,extray,dividerx<<2,dividery,extraDigits,1,enc); // grid
+        if (headerLetter) { result--; *result=headerLetter; }
       } // postfix
     } // grid
   }  // encode
-} // encodeGrid
-
-
-
-
-
-// *********************************************************************************************************************
-
-// indexes
-static int iso_start;
-static int iso_end;
-
-// counts:
-static int iso_count13;
-static int iso_count21;
-static int iso_count22;
-static int iso_count23;
-static int iso_count32;
-static int iso_count24;
-static int iso_count33;
-static int iso_count34;
-static int iso_count42;
-static int iso_count43;
-static int iso_count44;
-
-// first occurances
-static int iso_first13;
-static int iso_first21;
-static int iso_first22;
-static int iso_first23;
-static int iso_first32;
-static int iso_first24;
-static int iso_first33;
-static int iso_first34;
-static int iso_first42;
-static int iso_first43;
-static int iso_first44;
-
-static int iso_firststar14;
-static int iso_firststar22;
-static int iso_firststar23;
-static int iso_firststar32;
-static int iso_firststar24;
-static int iso_firststar33;
-static int iso_firststar34;
-static int iso_firststar44;
-
-static int iso_firstpipe14;
-static int iso_firstpipe22;
-static int iso_firstpipe23;
-static int iso_firstpipe32;
-static int iso_firstpipe24;
-static int iso_firstpipe33;
-static int iso_firstpipe34;
-static int iso_firstpipe44;
-
-// pipe letters
-static char iso_headerletter14[32];
-static char iso_headerletter22[32];
-static char iso_headerletter23[32];
-static char iso_headerletter32[32];
-static char iso_headerletter24[32];
-static char iso_headerletter33[32];
-static char iso_headerletter34[32];
-static char iso_headerletter44[32];
-
-static void setup_country( int newccode )
-{
-  int iso_count14;
-  int iso_first14;
-
-  int iso_pipecount14;
-  int iso_pipecount22;
-  int iso_pipecount23;
-  int iso_pipecount32;
-  int iso_pipecount24;
-  int iso_pipecount33;
-  int iso_pipecount34;
-  int iso_pipecount44;
-
-
-  if ( current_ccode!=newccode ) // cache check
-  {
-    if (newccode<0 || newccode>=MAX_MAPCODE_TERRITORY_CODE) newccode=ccode_earth; // solve bad args
-    current_ccode=newccode;
-
-    // init
-    iso_start=-1;
-    iso_end=-1;
-
-    iso_count13=0;
-    iso_count14=0;
-    iso_count21=0;
-    iso_count22=0;
-    iso_count23=0;
-    iso_count32=0;
-    iso_count24=0;
-    iso_count33=0;
-    iso_count34=0;
-    iso_count42=0;
-    iso_count43=0;
-    iso_count44=0;
-    iso_pipecount14=0;
-    iso_pipecount22=0;
-    iso_pipecount23=0;
-    iso_pipecount32=0;
-    iso_pipecount24=0;
-    iso_pipecount33=0;
-    iso_pipecount34=0;
-    iso_pipecount44=0;
-    iso_firstpipe14=-1;
-    iso_firstpipe22=-1;
-    iso_firstpipe23=-1;
-    iso_firstpipe32=-1;
-    iso_firstpipe24=-1;
-    iso_firstpipe33=-1;
-    iso_firstpipe34=-1;
-    iso_firstpipe44=-1;
-    iso_first13=-1;
-    iso_first14=-1;
-    iso_first21=-1;
-    iso_first22=-1;
-    iso_first23=-1;
-    iso_first32=-1;
-    iso_first24=-1;
-    iso_first33=-1;
-    iso_first34=-1;
-    iso_first42=-1;
-    iso_first43=-1;
-    iso_first44=-1;
-    iso_firststar14=-1;
-    iso_firststar22=-1;
-    iso_firststar23=-1;
-    iso_firststar32=-1;
-    iso_firststar24=-1;
-    iso_firststar33=-1;
-    iso_firststar34=-1;
-    iso_firststar44=-1;
+}
 
-    {
-      int i;
 
-      iso_start = firstrec(current_ccode);
-      iso_end   = lastrec(current_ccode);
 
-      for ( i=iso_start; i<=iso_end; i++ )
-      {
-        int codex = coDex(i);
-        int pipe = recType(i);
-
-        if ( codex==13 ) { iso_count13++; if ( iso_first13<0 ) iso_first13=i; }
-        if ( codex==21 ) { iso_count21++; if ( iso_first21<0 ) iso_first21=i; }
-        if ( codex==22 ) { if (pipe) { if (iso_firstpipe22<0) iso_firstpipe22=i; if (pipe<2)       iso_headerletter22[iso_pipecount22++]=headerLetter(i); else if (iso_firststar22<0) iso_firststar22=i;} else { iso_count22++; if ( iso_first22<0 ) iso_first22=i; } }
-        if ( codex==14 ) { if (pipe) { if (iso_firstpipe14<0) iso_firstpipe14=i; if (pipe<2)       iso_headerletter14[iso_pipecount14++]=headerLetter(i); else if (iso_firststar14<0) iso_firststar14=i;} else { iso_count14++; if ( iso_first14<0 ) iso_first14=i; } }
-        if ( codex==23 ) { if (pipe) { if (iso_firstpipe23<0) iso_firstpipe23=i; if (pipe<2)       iso_headerletter23[iso_pipecount23++]=headerLetter(i); else if (iso_firststar23<0) iso_firststar23=i;} else { iso_count23++; if ( iso_first23<0 ) iso_first23=i; } }
-        if ( codex==32 ) { if (pipe) { if (iso_firstpipe32<0) iso_firstpipe32=i; if (pipe<2)       iso_headerletter32[iso_pipecount32++]=headerLetter(i); else if (iso_firststar32<0) iso_firststar32=i;} else { iso_count32++; if ( iso_first32<0 ) iso_first32=i; } }
-        if ( codex==24 ) { if (pipe) { if (iso_firstpipe24<0) iso_firstpipe24=i; if (pipe<2)       iso_headerletter24[iso_pipecount24++]=headerLetter(i); else if (iso_firststar24<0) iso_firststar24=i;} else { iso_count24++; if ( iso_first24<0 ) iso_first24=i; } }
-        if ( codex==33 ) { if (pipe) { if (iso_firstpipe33<0) iso_firstpipe33=i; if (pipe<2)       iso_headerletter33[iso_pipecount33++]=headerLetter(i); else if (iso_firststar33<0) iso_firststar33=i;} else { iso_count33++; if ( iso_first33<0 ) iso_first33=i; } }
-        if ( codex==34 ) { if (pipe) { if (iso_firstpipe34<0) iso_firstpipe34=i; if (pipe<2)       iso_headerletter34[iso_pipecount34++]=headerLetter(i); else if (iso_firststar34<0) iso_firststar34=i;} else { iso_count34++; if ( iso_first34<0 ) iso_first34=i; } }
-        if ( codex==42 ) { iso_count42++; if ( iso_first42<0 ) iso_first42=i; }
-        if ( codex==43 ) { iso_count43++; if ( iso_first43<0 ) iso_first43=i; }
-        if ( codex==44 ) { if (pipe) { if (iso_firstpipe44<0) iso_firstpipe44=i; if (pipe<2)       iso_headerletter44[iso_pipecount44++]=headerLetter(i); else if (iso_firststar44<0) iso_firststar44=i;} else { iso_count44++; if ( iso_first44<0 ) iso_first44=i; } }
-      }
-    }
 
-    iso_headerletter14[iso_pipecount14]=0;
-    iso_headerletter22[iso_pipecount22]=0;
-    iso_headerletter23[iso_pipecount23]=0;
-    iso_headerletter32[iso_pipecount32]=0;
-    iso_headerletter24[iso_pipecount24]=0;
-    iso_headerletter33[iso_pipecount33]=0;
-    iso_headerletter34[iso_pipecount34]=0;
-    iso_headerletter44[iso_pipecount44]=0;
-  }
-} // setup_country
 
+// find first territory rectangle of the same type as m
+static int firstNamelessRecord(int codex, int m, int firstcode) {
+    int i = m;
+    while (i >= firstcode && coDex(i) == codex && isNameless(i)) i--;
+    return (i+1);
+}
 
-static int count_city_coordinates_for_country( int codex ) // returns count
-{
-  if (codex==21) return iso_count21;
-  if (codex==22) return iso_count22;
-  if (codex==13) return iso_count13;
-  return 0;
+// count all territory rectangles of the same type as m
+static int countNamelessRecords(int codex, int m, int firstcode) {
+    int i = firstNamelessRecord(codex, m, firstcode);
+    int e = m;
+    while (coDex(e) == codex) e++;
+    return (e-i);
 }
 
 
-static int city_for_country( int X, int codex ) // returns m
-{
-  if ( codex==21 ) return iso_first21+X;
-  if ( codex==13 ) return iso_first13+X;
-  return iso_first22+X;
-}
 
 
+// decodes dec->mapcode in context of territory rectangle m, territory dec->context
 // Returns x<0 in case of error, or record#
-static int decodeNameless( const char *orginput, long *x, long *y,         int input_ctry, int codex, long debug_oldx, long debug_oldy )
+static int decodeNameless(decodeRec *dec, int m )
 {
-  int A;
+  int A,F;
   char input[8];
-  int codexlen = strlen(orginput)-1;
-  int dc = (codex != 22) ? 2 : 3;
+  int codexm = coDex(m);
+  int dc = (codexm != 22) ? 2 : 3;
 
+  int codexlen = strlen(dec->mapcode)-1;
   if ( codexlen!=4 && codexlen!=5 )
     return -2; // solve bad args
 
-  // copy without dot (its only 4 or 5 chars)
-  strcpy(input,orginput);
-  strcpy(input+dc,orginput+dc+1);
+  // copy without dot
+  strcpy(input,dec->mapcode);
+  strcpy(input+dc,dec->mapcode+dc+1);
 
-  setup_country(input_ctry);
 
-  A = count_city_coordinates_for_country( codex );
-  if ( (A<2 && codex!=21) || (codex==21 && A<1) )
+  A = countNamelessRecords(codexm,m,firstrec(dec->context));
+  F = firstNamelessRecord( codexm,m,firstrec(dec->context));
+
+  if ( (A<2 && codexm!=21) || A<1 )
     return -3;
 
-  {
+  { // check just in case
     int p = 31/A;
     int r = 31%A;
     long v;
-    int m;
     long SIDE;
     int swapletters=0;
     long xSIDE;
@@ -997,9 +814,9 @@ static int decodeNameless( const char *orginput, long *x, long *y,         int i
     strcpy(result,input);
 
     // now determine X = index of first area, and SIDE
-    if ( codex!=21 && A<=31 )
+    if ( codexm!=21 && A<=31 )
     {
-      int offset = decode_chars[(unsigned int)*result];
+      int offset = decodeChar(*result);
 
       if ( offset < r*(p+1) )
       {
@@ -1007,17 +824,17 @@ static int decodeNameless( const char *orginput, long *x, long *y,         int i
       }
       else
       {
-        swapletters=(p==1 && codex==22);
+        swapletters=(p==1 && codexm==22);
         X = r + (offset-(r*(p+1))) / p;
       }
     }
-    else if ( codex!=21 && A<62 )
+    else if ( codexm!=21 && A<62 )
     {
 
-      X = decode_chars[(unsigned int)*result];
+      X = decodeChar(*result);
       if ( X < (62-A) )
       {
-        swapletters=(codex==22);
+        swapletters=(codexm==22);
       }
       else
       {
@@ -1026,7 +843,7 @@ static int decodeNameless( const char *orginput, long *x, long *y,         int i
     }
     else // code==21 || A>=62
     {
-      long BASEPOWER = (codex==21) ? 961*961 : 961*961*31;
+      long BASEPOWER = (codexm==21) ? 961*961 : 961*961*31;
       long BASEPOWERA = (BASEPOWER/A);
 
       if (A==62) BASEPOWERA++; else BASEPOWERA = 961*(BASEPOWERA/961);
@@ -1036,9 +853,11 @@ static int decodeNameless( const char *orginput, long *x, long *y,         int i
       v %= BASEPOWERA;
     }
 
+
+
     if (swapletters)
     {
-      m = city_for_country(           X,codex);
+      m = F + X;
       if ( ! isSpecialShape22(m) )
       {
         char t = result[codexlen-3]; result[codexlen-3]=result[codexlen-2]; result[codexlen-2]=t;
@@ -1046,7 +865,7 @@ static int decodeNameless( const char *orginput, long *x, long *y,         int i
     }
 
     // adjust v and X
-    if ( codex!=21 && A<=31 )
+    if ( codexm!=21 && A<=31 )
     {
 
       v = decodeBase31(result);
@@ -1056,7 +875,7 @@ static int decodeNameless( const char *orginput, long *x, long *y,         int i
       }
 
     }
-    else if ( codex!=21 && A<62 )
+    else if ( codexm!=21 && A<62 )
     {
 
       v = decodeBase31(result+1);
@@ -1068,7 +887,7 @@ static int decodeNameless( const char *orginput, long *x, long *y,         int i
         }
     }
 
-    m = city_for_country(           X,codex);
+    m = F + X;
     SIDE = smartDiv(m);
 
     getboundaries(m,minx,miny,maxx,maxy);
@@ -1106,24 +925,24 @@ static int decodeNameless( const char *orginput, long *x, long *y,         int i
       }
 
       {
-        long dividerx4 = x_divider(miny,maxy); // *** note: dividerx4 is 4 times too large!
+        long dividerx4 = xDivider4(miny,maxy); // *** note: dividerx4 is 4 times too large!
         long dividery = 90;
 
-        *x = minx + ((dx * dividerx4)/4); // *** note: FIRST multiply, then divide... more precise, larger rects
-        *y = maxy - (dy*dividery);
+        dec->lon32 = minx + ((dx * dividerx4)/4); // *** note: FIRST multiply, then divide... more precise, larger rects
+        dec->lat32 = maxy - (dy*dividery);
+        decodeExtension(dec, dividerx4,dividery,-1); // nameless
 
-        decodeExtension(x,y, dividerx4,dividery,-1); // nameless
-
-#ifdef VERSION160 // BUGFIX! @@@
-        extrax += ((dx * dividerx4)%4)/4.0;
+#ifdef SUPPORT_HIGH_PRECISION // BUGFIX!
+        dec->lon += ((dx * dividerx4)%4)/4.0;
 #endif
 
         return m;
       }
     }
   }
-  return -19;
-} // decodeNameless
+}
+
+
 
 
 
@@ -1165,7 +984,7 @@ static int unpack_if_alldigits(char *input) // returns 1 if unpacked, 0 if left
       break;
     else if (*s=='.' && !dotpos)
       dotpos=s;
-    else if ( decode_chars[(unsigned int)*s]<0 || decode_chars[(unsigned int)*s]>9 )
+    else if ( decodeChar(*s)<0 || decodeChar(*s)>9 )
       return 0;  // nondigit, so stop
   }
 
@@ -1173,7 +992,7 @@ static int unpack_if_alldigits(char *input) // returns 1 if unpacked, 0 if left
   {
       if (aonly) // v1.50 encoded only with A's
       {
-        int v = (s[0]=='A' || s[0]=='a' ? 31 : decode_chars[(unsigned int)s[0]]) * 32 + (s[1]=='A' || s[1]=='a' ? 31 : decode_chars[(unsigned int)s[1]]);
+        int v = (s[0]=='A' || s[0]=='a' ? 31 : decodeChar(s[0])) * 32 + (s[1]=='A' || s[1]=='a' ? 31 : decodeChar(s[1]));
         *input  = '0'+(v/100);
         s[0]= '0'+((v/10)%10);
         s[1]= '0'+(v%10);
@@ -1191,8 +1010,8 @@ static int unpack_if_alldigits(char *input) // returns 1 if unpacked, 0 if left
       if (*e=='a' || *e=='A') v+=31;
       else if (*e=='e' || *e=='E') v+=32;
       else if (*e=='u' || *e=='U') v+=33;
-      else if (decode_chars[(unsigned int)*e]<0) return -9; // invalid last character!
-      else v+=decode_chars[(unsigned int)*e];
+      else if (decodeChar(*e)<0) return -9; // invalid last character!
+      else v+=decodeChar(*e);
 
       if (v<100)
       {
@@ -1206,952 +1025,470 @@ static int unpack_if_alldigits(char *input) // returns 1 if unpacked, 0 if left
 }
 
 
-#define VERSION_1_32// 1.32 true recursive processing
-#ifdef VERSION_1_32 // 1.32 true recursive processing
-static int result_override=-1;
-#endif
-static const char* makeiso(int cc,int longcode); // 0=short / 1=XX-YYY for states, XXX for country / 2=shortest unique
-
-static void addresult(char *resultbuffer, char *result, long x,long y, int ccode)
+static int stateletter(int ccode) // parent
 {
-  // add to global array (if any)
-#ifdef VERSION_1_32 // 1.32 true recursive processing
-  if (result_override>=0) ccode=result_override; // 1.32 true recursive processing
-#endif
-  if (*result && global_results && nr_global_results>=0 && nr_global_results+1<(2*MAXGLOBALRESULTS)) {
-    global_results[nr_global_results++] = addstorage(result);
-    global_results[nr_global_results++] = addstorage(makeiso(ccode,1));
-  }
-  // add to buffer (if any)
-  if (resultbuffer)
-  {
-    if (*resultbuffer) strcat(resultbuffer," ");
-    strcat(resultbuffer,result);
-  }
-} // addresult
+  if (ccode>=usa_from && ccode<=usa_upto) return 1; //ccode_usa
+  if (ccode>=ind_from && ccode<=ind_upto) return 2; //ccode_ind
+  if (ccode>=can_from && ccode<=can_upto) return 3; //ccode_can
+  if (ccode>=aus_from && ccode<=aus_upto) return 4; //ccode_aus
+  if (ccode>=mex_from && ccode<=mex_upto) return 5; //ccode_mex
+  if (ccode>=bra_from && ccode<=bra_upto) return 6; //ccode_bra
+  if (ccode>=rus_from && ccode<=rus_upto) return 7; //ccode_rus
+  if (ccode>=chn_from && ccode<=chn_upto) return 8; //ccode_chn
+  return 0;
+}
+
+
+
 
 
 // returns -1 (error), or m (also returns *result!=0 in case of success)
-static int encodeNameless( char *resultbuffer, char *result, long x, long y, int input_ctry, int CODEX, int forcecoder )
+static int encodeNameless( char *result, const encodeRec* enc, int input_ctry, int codexm, int extraDigits, int m )
 {
-  int A;
+  // determine how many nameless records there are (A), and which one is this (X)...
+  long y= enc->lat32,x= enc->lon32;
+  int  A = countNamelessRecords(codexm, m, firstrec(input_ctry));
+  long X = m - firstNamelessRecord( codexm, m, firstrec(input_ctry));
 
   *result=0;
 
-  setup_country(input_ctry);
-  A = count_city_coordinates_for_country( CODEX );
-
-  // determine A = nr of 2.2
-  if ( A>1 )
   {
     int p = 31/A;
     int r = 31%A; // the first r items are p+1
-    long codexlen = (CODEX/10)+(CODEX%10);
+    long codexlen = (codexm/10)+(codexm%10);
     // determine side of square around centre
     long SIDE;
-    // now determine X = index of first area
-    long X=0;
-    // loop through country records
-    int j   = (CODEX==21 ? iso_first21 : (CODEX==22 ? iso_first22 : iso_first13));
-    int e = j+(CODEX==21 ? iso_count21 : (CODEX==22 ? iso_count22 : iso_count13));
-    for ( X=0; j<e; j++,X++ )
-    {
-      int m = (j);
-
-      if (forcecoder<0     || forcecoder==m)
-      {
-        long storage_offset;
-        long miny,maxy;
-        long minx,maxx;
 
-        long xSIDE,orgSIDE;
+    long storage_offset;
+    long miny,maxy;
+    long minx,maxx;
 
+    long xSIDE,orgSIDE;
 
-        if ( CODEX!=21 && A<=31 )
-        {
-          int size=p; if (X<r) size++; // example: A=7, p=4 r=3:  size(X)={5,5,5,4,4,4,4}
-          storage_offset= (X*p + (X<r ? X : r)) * (961*961); // p=4,r=3: offset(X)={0,5,10,15,19,23,27}-31
-        }
-        else if ( CODEX!=21 && A<62 )
-        {
-          if ( X < (62-A) )
-          {
-            storage_offset = X*(961*961);
-          }
-          else
-          {
-            storage_offset = (62-A +           ((X-62+A)/2) )*(961*961);
-            if ( (X+A) & 1 )
-            {
-              storage_offset += (16*961*31);
-            }
-          }
-        }
-        else
-        {
-          long BASEPOWER = (CODEX==21) ? 961*961 : 961*961*31;
-          long BASEPOWERA = (BASEPOWER/A);
-          if (A==62)
-            BASEPOWERA++;
-          else
-            BASEPOWERA = (961) *           (BASEPOWERA/961);
-
-          storage_offset = X * BASEPOWERA;
-        }
-        SIDE = smartDiv(m);
 
-        getboundaries(m,minx,miny,maxx,maxy);
-        orgSIDE=xSIDE=SIDE;
-        if ( isSpecialShape22(m) ) //  - keep the existing rectangle!
+    if ( codexm!=21 && A<=31 )
+    {
+      int size=p; if (X<r) size++; // example: A=7, p=4 r=3:  size(X)={5,5,5,4,4,4,4}
+      storage_offset= (X*p + (X<r ? X : r)) * (961*961); // p=4,r=3: offset(X)={0,5,10,15,19,23,27}-31
+    }
+    else if ( codexm!=21 && A<62 )
+    {
+      if ( X < (62-A) )
+      {
+        storage_offset = X*(961*961);
+      }
+      else
+      {
+        storage_offset = (62-A +           ((X-62+A)/2) )*(961*961);
+        if ( (X+A) & 1 )
         {
-            SIDE = 1+((maxy-miny)/90); // new side, based purely on y-distance
-            xSIDE = (orgSIDE*orgSIDE) / SIDE;
+          storage_offset += (16*961*31);
         }
+      }
+    }
+    else
+    {
+      long BASEPOWER = (codexm==21) ? 961*961 : 961*961*31;
+      long BASEPOWERA = (BASEPOWER/A);
+      if (A==62)
+        BASEPOWERA++;
+      else
+        BASEPOWERA = (961) *           (BASEPOWERA/961);
 
+      storage_offset = X * BASEPOWERA;
+    }
+    SIDE = smartDiv(m);
 
+    getboundaries(m,minx,miny,maxx,maxy);
+    orgSIDE=xSIDE=SIDE;
+    if ( isSpecialShape22(m) ) //  - keep the existing rectangle!
+    {
+        SIDE = 1+((maxy-miny)/90); // new side, based purely on y-distance
+        xSIDE = (orgSIDE*orgSIDE) / SIDE;
+    }
 
-        if ( miny<=y && y<maxy && isInRange(x,minx,maxx) )
-        {
-          long v = storage_offset;
+    if (fitsInside(x,y,m))
+    {
+      long v = storage_offset;
 
-          long dividerx4 = x_divider(miny,maxy); // *** note: dividerx4 is 4 times too large!
-#ifdef VERSION160 // precise encoding: take fraction into account!
-          long xFracture = (long)(4*fraclon);
+      long dividerx4 = xDivider4(miny,maxy); // *** note: dividerx4 is 4 times too large!
+#ifdef SUPPORT_HIGH_PRECISION // precise encoding: take fraction into account!
+      long xFracture = (long)(4* enc->fraclon);
 #else
-          long xFracture = 0;
+      long xFracture = 0;
 #endif
-          long dx = (4*(x-minx)+xFracture)/dividerx4; // like div, but with floating point value
-          long extrax4 = (x-minx)*4 - dx*dividerx4; // like modulus, but with floating point value
-
-          long dividery = 90;
-          long dy     = (maxy-y)/dividery;  // between 0 and SIDE-1
-          long extray = (maxy-y)%dividery;
+      long dx = (4*(x-minx)+xFracture)/dividerx4; // like div, but with floating point value
+      long extrax4 = (x-minx)*4 - dx*dividerx4; // like modulus, but with floating point value
 
-  #ifdef VERSION160 // precise encoding: check if fraction takes this out of range
-          if (extray==0 && fraclat>0) {
-              if (dy==0)
-                continue; // fraction takes this coordinate out of range
-              dy--;
-              extray += dividery;
-
-          }
-  #endif
+      long dividery = 90;
+      long dy     = (maxy-y)/dividery;  // between 0 and SIDE-1
+      long extray = (maxy-y)%dividery;
 
-          if ( isSpecialShape22(m) )
-          {
-            v += encodeSixWide(dx,SIDE-1-dy,xSIDE,SIDE);
-          }
-          else
-          {
-            v +=  (dx*SIDE + dy);
-          }
+#ifdef SUPPORT_HIGH_PRECISION // precise encoding: check if fraction takes this out of range
+      if (extray==0 &&  enc->fraclat>0) {
+          if (dy==0)
+            return -1; // fraction takes this coordinate out of range
+          dy--;
+          extray += dividery;
 
-          encodeBase31( result, v, codexlen+1 ); // nameless
-          {
-            int dotp=codexlen;
-            if (CODEX==13)
-              dotp--;
-            memmove(result+dotp,result+dotp-1,4); result[dotp-1]='.';
-          }
+      }
+#endif
 
-          if ( ! isSpecialShape22(m) )
-          if ( CODEX==22 && A<62 && orgSIDE==961 )
-          {
-            char t = result[codexlen-2]; result[codexlen-2]=result[codexlen]; result[codexlen]=t;
-          }
+      if ( isSpecialShape22(m) )
+      {
+        v += encodeSixWide(dx,SIDE-1-dy,xSIDE,SIDE);
+      }
+      else
+      {
+        v +=  (dx*SIDE + dy);
+      }
 
-          encodeExtension(result,extrax4,extray,dividerx4,dividery,use_high_precision,-1); // nameless
+      encodeBase31( result, v, codexlen+1 ); // nameless
+      {
+        int dotp=codexlen;
+        if (codexm==13)
+          dotp--;
+        memmove(result+dotp,result+dotp-1,4); result[dotp-1]='.';
+      }
 
-          return m;
+      if ( ! isSpecialShape22(m) )
+      if ( codexm==22 && A<62 && orgSIDE==961 )
+      {
+        char t = result[codexlen-2]; result[codexlen-2]=result[codexlen]; result[codexlen]=t;
+      }
 
-        } // in range
+      encodeExtension(result,extrax4,extray,dividerx4,dividery,extraDigits,-1,enc); // nameless
 
-      } // forcecoder?
-    }
-  } // there are multiple 2.2 !
+      return m;
 
+    } // in range
+  }
   return -1;
-} // encodeNameless
+}
 
 
 
 
-// returns nonzero if error
-//    -182 no countryname
-static int master_decode(  long *nx,long *ny, // <- store result in nx,ny
-          const char *org_input,
-          const char *default_cityname, int input_ctry, // <- context, in case input has no name, or no countryname
-          long debug_oldx,long debug_oldy // <- optional "original coordinates"
-          )
+// decodes dec->mapcode in context of territory rectangle m
+static int decodeAutoHeader(decodeRec *dec,  int m )
 {
- const char *dot=NULL;
- int err=0;
- int m=-1; // key record for decoding
-
- int ilen=strlen(org_input);
- char input[MAX_CLEAN_MAPCODE_LEN+1];
- if (ilen<5 || ilen>MAX_CLEAN_MAPCODE_LEN)
-   return -8;
- strcpy(input,org_input);
-
- {
-   char *min = strchr(input,'-');
-   if (min) {
-     *min++=0;
-     extrapostfix=&org_input[min-input];
-     if (strlen(extrapostfix)>MAX_PRECISION_DIGITS)
-       return -19; // extension too long
-     ilen=strlen(input);
-   } else extrapostfix="";
- }
-
-
- *nx=*ny=0; // reset to zero in case of error
-
- {
-  int voweled = unpack_if_alldigits(input);
-  if (voweled<0)
-    return -7;
+  const char *input = dec->mapcode;
+  int err = -1;
+  int firstcodex = coDex(m);
+  char *dot = strchr(input,'.');
 
-  // debug support: U-lead pre-processing
-  if (*input=='u' || *input=='U')  {
-    strcpy(input,input+1);
-    ilen--;
-    voweled=1;
-  }
+  long STORAGE_START=0;
+  long value;
 
-  if (ilen>10) return -8;
+  if (dot==NULL)
+    return -201;
 
-  // find dot and check that all characters are valid
-  {
-    int nrd=0; // nr of true digits
-    const char *s=input;
-    for ( ; *s!=0; s++ )
-    {
-      if (*s=='.')
-        { if (dot) return -5; else dot=s; }
-      else if ( decode_chars[(unsigned int)*s]<0 )
-        return -4; // invalid char
-      else if ( decode_chars[(unsigned int)*s]<10 ) // digit?
-        nrd++;
-    }
-    if (dot==NULL)
-      return -2;
-    else if (!voweled && nrd+1==ilen) // there is a dot, and everything else is a digit!
-      return -998;
-  }
-
-//////////// AT THIS POINT, dot=FIRST DOT, input=CLEAN INPUT (no vowels) ilen=INPUT LENGTH
+  value = decodeBase31(input); // decode top
+  value *= (961*31);
 
-  // analyse input
+  for ( ; coDex(m)==firstcodex && recType(m)>1; m++ )
   {
-    int prelen = (dot-input);
-    int postlen = ilen-1-prelen;
-    if ( prelen<2 || prelen>5 || postlen<2 || postlen>4 )
-      return -3;
-  }
-
-//////////////////////////////////
-
-    if ( ilen>=10 )
-      input_ctry = ccode_earth;
-
-    if (input_ctry<0) return input_ctry;
-    setup_country(input_ctry);
+    long minx,miny,maxx,maxy;
+    getboundaries(m,minx,miny,maxx,maxy);
 
-    // special case: 43 or worse, for a state
-    if ( (ilen==8 || ilen==9) && iso_count43==1 && isRestricted((iso_first43)) && ( mIsIndiaState((input_ctry )) || mIsMexicoState((input_ctry )) ) )
     {
-      input_ctry =
-          mIsMexicoState((input_ctry )) ? ccode_mex :
-          mIsIndiaState((input_ctry )) ? ccode_ind :
-          CCODE_ERR;
-      setup_country(input_ctry);
-    }
-    else if ( ilen==9 && iso_count44==1 && isRestricted((iso_first44)) && isSubdivision((input_ctry ))   )
-    {
-      input_ctry =
-        mIsUsaState((input_ctry )) ? ccode_usa :
-        mIsCanadaState((input_ctry )) ? ccode_can :
-        mIsAustraliaState((input_ctry )) ? ccode_aus :
-        mIsBrazilState((input_ctry )) ? ccode_bra :
-        mIsChinaState((input_ctry )) ? ccode_chn :
-        mIsRussiaState((input_ctry )) ? ccode_rus :
-        CCODE_ERR;
-      setup_country(input_ctry);
-    }
-
-    if (
-             ( ilen==5 && input[2]=='.' && iso_count21==0 && iso_count22==1 )
-          || ( ilen==5 && input[2]=='.' && iso_count21==1 )
-          || ( ilen==6 && input[2]=='.' && iso_count23==1 )
-          || ( ilen==6 && input[3]=='.' && iso_count32==1 )
-          || ( ilen==7 && input[2]=='.' && iso_count24==1 )
-          || ( ilen==7 && input[3]=='.' && iso_count33==1 )
-          || ( ilen==7 && input[4]=='.' && iso_count42==1 )
-          || ( ilen==8 && input[3]=='.' && iso_count34==1 )
-          || ( ilen==8 && input[4]=='.' && iso_count43==1 )
-          || ( ilen==9 && input[4]=='.' && iso_count44==1 )
-       )
+      // determine how many cells
+      long H = (maxy-miny+89)/90; // multiple of 10m
+      long xdiv = xDivider4(miny,maxy);
+      long W = ( (maxx-minx)*4 + (xdiv-1) ) / xdiv;
+      long product;
+
+      // decode
+      // round up to multiples of YSIDE3*XSIDE3...
+      H = YSIDE3*( (H+YSIDE3-1)/YSIDE3 );
+      W = XSIDE3*( (W+XSIDE3-1)/XSIDE3 );
+      product = (W/XSIDE3)*(H/YSIDE3)*961*31;
       {
-          long minx,miny,maxx,maxy;
-          if ( ilen==5 && iso_count21==1) m = (iso_first21);
-          if ( ilen==5 && iso_count21==0) m = (iso_first22);
-          if ( ilen==6 && input[2]=='.' ) m = (iso_first23);
-          if ( ilen==6 && input[3]=='.' ) m = (iso_first32);
-          if ( ilen==7 && input[2]=='.' ) m = (iso_first24);
-          if ( ilen==7 && input[3]=='.' ) m = (iso_first33);
-          if ( ilen==7 && input[4]=='.' ) m = (iso_first42);
-          if ( ilen==8 && input[3]=='.' ) m = (iso_first34);
-          if ( ilen==8 && input[4]=='.' ) m = (iso_first43);
-          if ( ilen==9 ) m = (iso_first44);
-
-          getboundaries(m,minx,miny,maxx,maxy);
-          decodeGrid( input,nx,ny, m, minx,miny,maxx,maxy);
-
-          //
-          if (isRestricted(m)) {
-            int j,fitssomewhere=0;
-            for (j=iso_start; (j)<m; j++) { // look in previous rects
-              long minx,miny,maxx,maxy,xdiv8;
-              if (isRestricted((j))) continue;
-              getboundaries((j),minx,miny,maxx,maxy);
-              // 1.33 fix to not remove valid results just across the edge of a territory
-              xdiv8 = x_divider(miny,maxy)/4; // should be /8 but there's some extra margin
-              if ( miny-60<=*ny && *ny<maxy+60 && isInRange(*nx,minx-xdiv8,maxx+xdiv8) ) { fitssomewhere=1; break; }
-            }
-            if (!fitssomewhere) {
-              err=-1234;
-            }
-          }
+        long GOODROUNDER = coDex(m)>=23 ? (961*961*31) : (961*961);
+        if ( recType(m)==2 ) // *+ pipe!
+          product = ((STORAGE_START+product+GOODROUNDER-1)/GOODROUNDER)*GOODROUNDER - STORAGE_START;
+      }
 
 
-      }
-      else if ( ilen==6 && input[3]=='.' && iso_count22>1 ) // multiple 22 into 3.2
-      {
-        m   = decodeNameless( input, nx,ny, input_ctry, 22, debug_oldx,debug_oldy);
-        if (m<0) err=m; else err=0;
-      }
-      else if ( ilen==6 && input[2]=='.' && iso_count13>1 ) // multiple 13 into 2.3
-      {
-        m   = decodeNameless( input, nx,ny, input_ctry, 13, debug_oldx,debug_oldy);
-        if (m<0) err=m; else err=0;
-      }
-      else if ( ilen==5 ) // multiple 21 into 2.2
+      if ( value >= STORAGE_START && value < STORAGE_START + product )
       {
-        if (iso_count21<=0)
-          err=-191;
-        else if ( input[2]!='.' )
-          err=-9;
-        else {
-          m   = decodeNameless( input, nx,ny, input_ctry, 21, debug_oldx,debug_oldy);
-          if (m<0) err=m; else err=0;
-        }
-      }
-      else if (
-                 ( ilen==7 && iso_firststar23>=0 && input[3]=='.')
-              || ( ilen==6 && iso_firststar22>=0 && input[2]=='.')
-        )
-      {
-        // decodeAutoHeader
-        int start = (ilen==6 ? iso_firststar22 : iso_firststar23);
+        // decode
+        long dividerx = (maxx-minx+W-1)/W;
+        long dividery = (maxy-miny+H-1)/H;
 
-        long STORAGE_START=0;
-        long value;
-        int j;
+        value -= STORAGE_START;
+        value /= (961*31);
 
-        value = decodeBase31(input); // decode top
-        value *= (961*31);
+        err=0;
 
-        err=-1;
-        for ( j=start; coDex(j)==coDex(start) && recType(j)>1; j++ )
+        // PIPELETTER DECODE
         {
-          long minx,miny,maxx,maxy;
-
-
-          m=(j);
-          getboundaries(m,minx,miny,maxx,maxy);
-
+          long difx,dify;
+          decode_triple(dot+1,&difx,&dify); // decode bottom 3 chars
           {
-            // determine how many cells
-            long H = (maxy-miny+89)/90; // multiple of 10m
-            long xdiv = x_divider(miny,maxy);
-            long W = ( (maxx-minx)*4 + (xdiv-1) ) / xdiv;
-            long product = W*H;
-
-            // decode
-            // round up to multiples of YSIDE3*XSIDE3...
-            H = YSIDE3*( (H+YSIDE3-1)/YSIDE3 );
-            W = XSIDE3*( (W+XSIDE3-1)/XSIDE3 );
-            product = (W/XSIDE3)*(H/YSIDE3)*961*31;
+            long vx = (value / (H/YSIDE3))*XSIDE3 + difx; // is vx/168
+            long vy = (value % (H/YSIDE3))*YSIDE3 + dify; // is vy/176
+
+            dec->lat32 = maxy - vy*dividery;
+            dec->lon32 = minx + vx*dividerx;
+            if ( dec->lon32<minx || dec->lon32>=maxx || dec->lat32<miny || dec->lat32>maxy ) // *** CAREFUL! do this test BEFORE adding remainder...
             {
-            long GOODROUNDER = coDex(m)>=23 ? (961*961*31) : (961*961);
-            if ( recType(m)==2 ) // *+ pipe!
-              product = ((STORAGE_START+product+GOODROUNDER-1)/GOODROUNDER)*GOODROUNDER - STORAGE_START;
+              return -122; // invalid code
             }
+            decodeExtension(dec,  dividerx<<2,dividery,-1); // autoheader decode
 
+          }
+        }
 
-            if ( value >= STORAGE_START && value < STORAGE_START + product )
-            {
-              // decode
-              long dividerx = (maxx-minx+W-1)/W;
-              long dividery = (maxy-miny+H-1)/H;
+        break;
+      }
+      STORAGE_START += product;
+    }
+  } // for j
+  return 0;
+}
 
-              value -= STORAGE_START;
-              value /= (961*31);
+// encode in m (know to fit)
+static int encodeAutoHeader( char *result, const encodeRec *enc, int m, int extraDigits )
+{
+  int i;
+  long STORAGE_START=0;
+  long y= enc->lat32,x= enc->lon32;
 
-              err=0; // decoding headerLetter!
+  // search back to first of the group
+  int firstindex = m;
+  int codex = coDex(m);
+  while ( recType(firstindex - 1) > 1 && coDex(firstindex - 1) == codex)
+      firstindex--;
 
-              // PIPELETTER DECODE
-              {
-                long difx,dify;
-                decode_triple(input+ilen-3,&difx,&dify); // decode bottom 3 chars
-                {
-                  long vx = (value / (H/YSIDE3))*XSIDE3 + difx; // is vx/168
-                  long vy = (value % (H/YSIDE3))*YSIDE3 + dify; // is vy/176
-                  *ny = maxy - vy*dividery;
-                  *nx = minx + vx*dividerx;
+  for (i = firstindex; coDex(i) == codex; i++)
+  {
+    long W,H,xdiv,product;
+    long minx,miny,maxx,maxy;
 
-                  if ( *nx<minx || *nx>=maxx || *ny<miny || *ny>maxy ) // *** CAREFUL! do this test BEFORE adding remainder...
-                  {
-                    err = -122; // invalid code
-                  }
+    getboundaries(i,minx,miny,maxx,maxy);
+    // determine how many cells
+    H = (maxy-miny+89)/90; // multiple of 10m
+    xdiv = xDivider4(miny,maxy);
+    W = ( (maxx-minx)*4 + (xdiv-1) ) / xdiv;
+
+    // encodee
+    // round up to multiples of YSIDE3*XSIDE3...
+    H = YSIDE3*( (H+YSIDE3-1)/YSIDE3 );
+    W = XSIDE3*( (W+XSIDE3-1)/XSIDE3 );
+    product = (W/XSIDE3)*(H/YSIDE3)*961*31;
+    if ( recType(i)==2 ) { // plus pipe
+      long GOODROUNDER = codex>=23 ? (961*961*31) : (961*961);
+      product = ((STORAGE_START+product+GOODROUNDER-1)/GOODROUNDER)*GOODROUNDER - STORAGE_START;
+    }
 
-                  decodeExtension(nx,ny, dividerx<<2,dividery,-1); // autoheader decode
+    if ( i==m )
+    {
+      // encode
+      long dividerx = (maxx-minx+W-1)/W;
+      long vx =     (x-minx)/dividerx;
+      long extrax = (x-minx)%dividerx;
 
-                }
-              }
+      long dividery = (maxy-miny+H-1)/H;
+      long vy =     (maxy-y)/dividery;
+      long extray = (maxy-y)%dividery;
 
-              break;
-            }
-            STORAGE_START += product;
-          }
-        } // for j
-      }
-// ************** PIPELETTER 32 33 42 34 43 54=world
-      else if (
-                   ( ilen== 6 && iso_firstpipe22>=0 && iso_firststar22<0 && input[3]=='.' ) // lettered 22-pipes -> 32
-                || ( ilen== 7 && iso_firstpipe23>=0 && iso_firststar23<0 && input[3]=='.' ) // lettered 23-pipes -> 33
-                || ( ilen== 7 && iso_firstpipe32>=0 && iso_firststar32<0 && input[4]=='.' ) // lettered 32-pipes -> 42
-                || ( ilen== 7 && iso_firstpipe14>=0 && iso_firststar14<0 && input[2]=='.' ) // lettered 14-pipes -> 24
-                || ( ilen== 8 && iso_firstpipe24>=0 && iso_firststar24<0 && input[3]=='.' ) // lettered 24-pipes -> 34
-                || ( ilen== 8 && iso_firstpipe33>=0 && iso_firststar33<0 && input[4]=='.' ) // lettered 33-pipes -> 43
-                || ( ilen== 9 && iso_firstpipe34>=0 && iso_firststar34<0 && input[4]=='.' ) // lettered 34-pipes -> 44
-                || ( ilen==10 && iso_firstpipe44>=0 && iso_firststar44<0 && input[5]=='.' ) // lettered 44-pipes -> 54
-              )
-      {
-        const char *pipeptr;
-        char letter=toupper(*input);
-        if (letter=='I') letter='1';
-        if (letter=='O') letter='0';
-        switch (ilen)
-        {
-          case  6: pipeptr = strchr(iso_headerletter22,letter); if (pipeptr) m=(iso_firstpipe22+(pipeptr-iso_headerletter22)); break;
-          case  7: if (input[3]=='.') {
-                   pipeptr = strchr(iso_headerletter23,letter); if (pipeptr) m=(iso_firstpipe23+(pipeptr-iso_headerletter23)); break;
-          }else if (input[2]=='.') {
-                   pipeptr = strchr(iso_headerletter14,letter); if (pipeptr) m=(iso_firstpipe14+(pipeptr-iso_headerletter14)); break;
-          }else{
-                   pipeptr = strchr(iso_headerletter32,letter); if (pipeptr) m=(iso_firstpipe32+(pipeptr-iso_headerletter32)); break;
-          }
-          case  8: if (input[3]=='.') {
-                   pipeptr = strchr(iso_headerletter24,letter); if (pipeptr) m=(iso_firstpipe24+(pipeptr-iso_headerletter24)); break;
-          }else{
-                   pipeptr = strchr(iso_headerletter33,letter); if (pipeptr) m=(iso_firstpipe33+(pipeptr-iso_headerletter33)); break;
-          }
-          case  9: pipeptr = strchr(iso_headerletter34,letter); if (pipeptr) m=(iso_firstpipe34+(pipeptr-iso_headerletter34)); break;
-          case 10: pipeptr = strchr(iso_headerletter44,letter); if (pipeptr) m=(iso_firstpipe44+(pipeptr-iso_headerletter44)); break;
-        }
+      long codexlen = (codex/10)+(codex%10);
+      long value = (vx/XSIDE3) * (H/YSIDE3);
 
-        if (!ISGOODAREA(m))
-        {
-          err = -98;
-        }
-        else
-        {
-          long minx,miny,maxx,maxy;
-          ilen--;
-          getboundaries(m,minx,miny,maxx,maxy);
-          decodeGrid( input+1,nx,ny, m, minx,miny,maxx,maxy);
-          err=0;
+#ifdef SUPPORT_HIGH_PRECISION // precise encoding: check if fraction takes this out of range
+      if ( extray==0 &&  enc->fraclat>0 ) {
+        if (vy==0) {
+          STORAGE_START += product;
+          continue;
         }
+        vy--;
+        extray += dividery;
       }
-// ************** fail!
-      else // THIS MEANS EVERYTHING HAS FAILED!!!
-      {
-        err=-99;
-      }
- }
+#endif
 
-// *********************** done, return results...
+      value += (vy/YSIDE3);
 
+      // PIPELETTER ENCODE
+      encodeBase31( result, (STORAGE_START/(961*31)) + value, codexlen-2 );
+      result[codexlen-2]='.';
+      encode_triple( result+codexlen-1, vx%XSIDE3, vy%YSIDE3 );
 
-  if (err==0)
-  {
-    // * make sure it fits the country *
-    if (!ISEARTH(input_ctry))
-    {
-      long minx,miny,maxx,maxy,xdiv8;
-      getboundaries((iso_end),minx,miny,maxx,maxy);
-      xdiv8 = x_divider(miny,maxy)/4; // should be /8 but there's some extra margin
-      if ( ! ( miny-60<=*ny && *ny<maxy+60 && isInRange(*nx,minx-xdiv8,maxx+xdiv8) ) ) // no fit?
-      {
-        err=-2222;
-      }
+      encodeExtension( result,extrax<<2,extray,dividerx<<2,dividery,extraDigits,-1,enc); // autoheader
+      return m;
     }
+
+    STORAGE_START += product;
   }
+  return i-1; // return last autoheader record as the (failing) record
+}
 
 
-  return err;
-} // master_decode
 
 
 
-
-// make sure resultbuffer is large enough!
-// x,y = lon/lat times 1.000.000
 static int debugStopAt=-1;
-static void master_encode( char *resultbuffer, int the_ctry, long x, long y, int forcecoder, int stop_with_one_result, int allow_world, int skip_parentstate )
+static void encoderEngine( int ccode, const encodeRec *enc, int stop_with_one_result, int extraDigits, int result_override )
 {
-  int result_ctry=the_ctry;
-  int i;
-  if (resultbuffer) *resultbuffer=0;
-
-  if (the_ctry<0) return;
+  int from,upto;
+  long y= enc->lat32,x= enc->lon32;
 
-  // V160 - cut y to [-90,90], and normalise all x to [-180,180>
-  if (y > 90000000) y = 90000000; else if (y< -90000000) y =-90000000;
-  x %= 360000000;
-  if (x>=180000000) x-=360000000; else if (x<-180000000) x+=360000000;
+  if (enc==NULL || ccode<0 || ccode>ccode_earth)
+    return; // bad arguments
 
-  ///////////////////////////////////////////////////////////
-  // turn into 3-letter ISO code!
-  ///////////////////////////////////////////////////////////
-  setup_country( the_ctry );
-  i=iso_start;
-
-
-  if (!ISEARTH(the_ctry))
-  {
-    long minx,miny,maxx,maxy;
-    getboundaries((iso_end),minx,miny,maxx,maxy);
-    if ( ! (miny<=y && y<maxy && isInRange(x,minx,maxx) ) )
-    {
-      i=iso_end+1; // skip to "Earth" (if supported)
-      if (!allow_world /*&& skip_parentstate*/) return;
-    }
-  }
+  from = firstrec(ccode);
+  upto = lastrec(ccode);
 
+  if (ccode != ccode_earth)
+    if ( ! fitsInside(x,y,upto) )
+      return;
 
   ///////////////////////////////////////////////////////////
   // look for encoding options
   ///////////////////////////////////////////////////////////
   {
+    int i;
     char result[128];
-    long minx,miny,maxx,maxy;
-    long STORAGE_START=0;
-    int forcecoder_starpipe = (forcecoder>=0    && recType(forcecoder)>1 );
     int result_counter=0;
+
     *result=0;
-    for( ; i<NR_BOUNDARY_RECS; i++ )
+    for( i=from; i<=upto; i++ )
     {
-      int m=(i);
-      int codex;
-
-      if ( i==iso_end && isRestricted(m) && isSubdivision(the_ctry) ) // last item is a reference to a state's country
-      {
-        if (skip_parentstate)
-          return;
-        if (forcecoder>=0   ) // we would have found it the normal way!
-          return;
-
-#ifdef VERSION_1_32 // 1.32 true recursive processing
-        result_override=the_ctry;  // 1.32 true recursive processing
-#endif
-
-        the_ctry =
-          mIsUsaState(the_ctry) ? ccode_usa :
-          mIsCanadaState(the_ctry) ? ccode_can :
-          mIsIndiaState(the_ctry) ? ccode_ind :
-          mIsMexicoState(the_ctry) ? ccode_mex :
-          mIsBrazilState(the_ctry) ? ccode_bra :
-          mIsChinaState(the_ctry) ? ccode_chn :
-          mIsRussiaState(the_ctry) ? ccode_rus :
-          ccode_aus;
-
-
-#ifdef VERSION_1_32 // 1.32 true recursive processing
-        master_encode( resultbuffer, the_ctry, x,y, forcecoder, stop_with_one_result,/*allow-world*/0,1 );
-        result_override=-1;
-        return; /**/
-#else
-        setup_country( the_ctry );
-        i=iso_start-1; continue;
-#endif
-      }
-
-      if ( i>iso_end )
-      {
-        if (forcecoder>=0    || !allow_world )
-          break;
-        // find first WORLD record...
-        result_ctry=the_ctry=ccode_earth;
-        setup_country(the_ctry);
-        // now process from here...
-        i=iso_start-1; continue;
-      }
-
-
-      if ( isRestricted(m) && result_counter==0 && forcecoder<0 ) // skip isRestricted records unless there already is a result
-        continue;
-
-
-      if ( forcecoder>=0    && m!=forcecoder && (forcecoder_starpipe==0 || recType(m)<=1)                ) continue; // not the right forcecoder (unless starpipe)
-
-      codex = coDex(m);
-      if ( codex==54 ) continue; // exlude antarctica "inner coding" options
-
-
-      getboundaries(m,minx,miny,maxx,maxy);
-
-      if ( isNameless(m) )
-      {
-        if ( y<miny || y>=maxy || !isInRange(x,minx,maxx) ) continue;
-        {
-          int ret=encodeNameless( resultbuffer, result, x,y, the_ctry, codex,  m );
-          if (ret>=0)
-          {
-            i=ret;
-          }
-        }
-      }
-      else if ( recType(m)>1 )
+      int codex = coDex(i);
+      if (codex<54)
       {
-        // encodeAutoHeader
-        if ( i<=iso_start || coDex(i-1)!=codex || recType(i-1)<=1 ) // is this the FIRST starpipe?
+        if (fitsInside(x,y,i))
         {
-          STORAGE_START=0;
-        }
-
-
+          if ( isNameless(i) )
           {
-            // determine how many cells
-            long H = (maxy-miny+89)/90; // multiple of 10m
-            long xdiv = x_divider(miny,maxy);
-            long W = ( (maxx-minx)*4 + (xdiv-1) ) / xdiv;
-            long product = W*H;
-
-            // encodee
-            // round up to multiples of YSIDE3*XSIDE3...
-            H = YSIDE3*( (H+YSIDE3-1)/YSIDE3 );
-            W = XSIDE3*( (W+XSIDE3-1)/XSIDE3 );
-            product = (W/XSIDE3)*(H/YSIDE3)*961*31;
+            int ret = encodeNameless( result, enc, ccode, codex, extraDigits, i );
+            if (ret>=0)
             {
-            long GOODROUNDER = codex>=23 ? (961*961*31) : (961*961);
-            if ( recType(m)==2 ) // plus pipe
-              product = ((STORAGE_START+product+GOODROUNDER-1)/GOODROUNDER)*GOODROUNDER - STORAGE_START;
-            }
-
-
-          if ( ( !ISGOODAREA(forcecoder) || forcecoder==m ) && ( miny<=y && y<maxy && isInRange(x,minx,maxx) ) )
-          {
-            // encode
-            long dividerx = (maxx-minx+W-1)/W;
-            long vx =     (x-minx)/dividerx;
-            long extrax = (x-minx)%dividerx;
-
-            long dividery = (maxy-miny+H-1)/H;
-            long vy =     (maxy-y)/dividery;
-            long extray = (maxy-y)%dividery;
-
-            long codexlen = (codex/10)+(codex%10);
-            long value = (vx/XSIDE3) * (H/YSIDE3);
-
-    #ifdef VERSION160 // precise encoding: check if fraction takes this out of range
-            if ( extray==0 && fraclat>0 ) {
-              if (vy==0) {
-                STORAGE_START += product;
-                continue;
-              }
-              vy--;
-              extray += dividery;
-            }
-    #endif
-
-            value += (vy/YSIDE3);
-
-            // PIPELETTER ENCODE
-            encodeBase31( result, (STORAGE_START/(961*31)) + value, codexlen-2 );
-            result[codexlen-2]='.';
-            encode_triple( result+codexlen-1, vx%XSIDE3, vy%YSIDE3 );
-
-            encodeExtension( result,extrax<<2,extray,dividerx<<2,dividery,use_high_precision,-1); // autoheader
-
-            {
-              #ifdef SUPPRESS_MULTIPLE_PIPES
-              while ( i<iso_end && coDex(i+1)==codex )
-                i++;
-              #endif
-
+              i=ret;
             }
           }
-
-          STORAGE_START += product;
-        }
-      }
-      else // must be grid, possibly a multi-area
-      {
-          int multi_area = (recType(m)==1 ? 1 : 0); // has pipe letter?
-          if (codex==21) { if (iso_count21==1) codex=22; else continue; }
-
-          if ( miny<=y && y<maxy && isInRange(x,minx,maxx) )
-          if ( codex!=55 ) // exclude Earth 55
+          else if ( recType(i)>1 )
           {
-            encodeGrid( result+multi_area, x,y, m, codex, minx,miny,maxx,maxy );
-            if (multi_area && result[multi_area])
-            {
-              *result = headerLetter(m);
-            }
+            encodeAutoHeader(result,enc,i,extraDigits);
           }
-      } // codex>21 grid, may be multi-area
-
-      // =========== handle result if any
-      if (*result) // GOT A RESULT?
-      {
-        result_counter++;
-
-        repack_if_alldigits(result,0);
-
-        if (debugStopAt<0 || debugStopAt==i)
-          addresult(resultbuffer,result,x,y,result_ctry); // 1.29 - also add parents recursively
-        if (debugStopAt==i) return;
-        if (stop_with_one_result) return;
-        *result=0;
-      }
-    } // for i
-  }
-} // master_encode
-
-
-
-
-
-
-#ifndef REMOVE_VALIDCODE
-static int valid_code( const char *input ) // returns < 0 if invalid, 0 if potentially valid, 1 if potentially a complete code (i.e. from 2.2 to 5.4, using valid chars)
-{
-  const unsigned char *i = (const unsigned char *)input;
-  int dots=0,prefix=0,postfix=0,alldigits=1,voweled=0;
-  for ( ; *i!=0; i++ )
-  {
-    if ( *i=='.' )
-    {
-      if ( dots++ )
-        return -1; // more than one dot!
-      if (prefix<2)
-        return -2; // prefix less than 2 characters!
-    }
-    else
-    {
-      if ( decode_chars[*i]<0 )
-      {
-
-        if ( decode_chars[*i]<-1 ) // i.e. A, E or U
-        {
-          if ( (*i=='A' || *i=='a') && i==(const unsigned char*)input ) // A is the first letter
+          else if ( i==upto && isRestricted(i) && isSubdivision(ccode) ) // if the last item is a reference to a state's country
           {
-            voweled=1;
-            prefix--;  // do not count as prefix!
+            // *** do a recursive call for the parent ***
+            encoderEngine( ParentTerritoryOf(ccode), enc, stop_with_one_result,extraDigits,ccode );
+            return; /**/
           }
-          else if (alldigits && !voweled && i[1]=='.') // vowel after digits just before dot
+          else // must be grid
           {
-            voweled=1;
+              if ( result_counter>0 || !isRestricted(i) ) // skip isRestricted records unless there already is a result
+              {
+                char headerletter = (recType(i)==1) ? headerLetter(i) : 0;
+                encodeGrid( result, enc, i, extraDigits,headerletter );
+              }
           }
-          else if (alldigits && voweled && i[1]==0 && i[-1]!='.') // last char of voweled entry, not right after dot?
-            ;
-          else
-            return -6; // invalid char: vowel
-        }
-        else
 
-        {
-          return -3; // other invalid character
-        }
-      }
-      else // consonant or digit
-      {
-        if (*i<'0' || *i>'9') // nondigit
-        {
-          alldigits=0;
-          if (voweled && i[1]!=0) return -7; // nondigit in voweled entry, not in the last position: invalid
+          // =========== handle result (if any)
+          if (*result)
+          {
+            result_counter++;
+
+            repack_if_alldigits(result,0);
+
+            if (debugStopAt<0 || debugStopAt==i) {
+              int cc = (result_override>=0 ? result_override : ccode);
+              if (*result && enc->mapcodes && enc->mapcodes->count < MAX_NR_OF_MAPCODE_RESULTS) {
+                char *s = enc->mapcodes->mapcode[enc->mapcodes->count++];
+                if (cc==ccode_earth)
+                  strcpy( s , result );
+                else {
+                  getTerritoryIsoName(s,cc+1,0);
+                  strcat(s," ");
+                  strcat(s,result);
+                }
+              }
+              if (debugStopAt==i) return;
+            }
+            if (stop_with_one_result) return;
+            *result=0; // clear for next iteration
+          }
         }
       }
-      if (dots)
-      {
-        postfix++;
-        if (postfix>4) return -4; // more than 4 letters postfix
-      }
-      else
-      {
-        prefix++;
-        if (prefix>5) return -5; // more than 5 letters prefix
-      }
-    }
-  }
-
-  // return if it looks like a "complete" code (i.e. one that can be decoded
-  if ( postfix<2 ) return -8;
-  if (alldigits && !voweled) return -11;
-  // note: at this point, prefix is between 2 and 5, and postfix is between 2 and 4 (12 options)
-  if ( postfix==4 )
-  {
-    return 1; // the 4 options 2.4 3.4 4.4 5.4 are all possible!
+    } // for i
   }
-  // note: at this point, prefix is between 2 and 5, and postfix is between 2 and 3
-  if ( prefix==5 ) return -9; // the 2 options 5.2 5.3 are impossible!
-  // note: at this point, prefix is between 2 and 4, and postfix is between 2 and 3
-  return 1; // the other 6 options (2.2 3.2 4.2 2.3 3.3 4.3) are all possible
-}
-#endif // REMOVE_VALIDCODE
-
-
-static int stateletter(int ccode) // parent
-{
-  if (ccode>=usa_from && ccode<=usa_upto) return 1; //ccode_usa
-  if (ccode>=ind_from && ccode<=ind_upto) return 2; //ccode_ind
-  if (ccode>=can_from && ccode<=can_upto) return 3; //ccode_can
-  if (ccode>=aus_from && ccode<=aus_upto) return 4; //ccode_aus
-  if (ccode>=mex_from && ccode<=mex_upto) return 5; //ccode_mex
-  if (ccode>=bra_from && ccode<=bra_upto) return 6; //ccode_bra
-  if (ccode>=rus_from && ccode<=rus_upto) return 7; //ccode_rus
-  if (ccode>=chn_from && ccode<=chn_upto) return 8; //ccode_chn
-  return 0;
 }
 
-static int stateparent(int ccode) // returns parent, or -1
-{
-  if (ccode>=usa_from && ccode<=usa_upto) return ccode_usa;
-  if (ccode>=ind_from && ccode<=ind_upto) return ccode_ind;
-  if (ccode>=can_from && ccode<=can_upto) return ccode_can;
-  if (ccode>=aus_from && ccode<=aus_upto) return ccode_aus;
-  if (ccode>=mex_from && ccode<=mex_upto) return ccode_mex;
-  if (ccode>=bra_from && ccode<=bra_upto) return ccode_bra;
-  if (ccode>=rus_from && ccode<=rus_upto) return ccode_rus;
-  if (ccode>=chn_from && ccode<=chn_upto) return ccode_chn;
-  return -1;
-}
 
-static char makeiso_bufbytes[16];
-static char *makeiso_buf;
-static const char* makeiso(int cc,int longcode) // 0=short / 1=XX-YYY for states, XXX for country / 2=shortest unique
+// returns nonzero if error
+static int decoderEngine( decodeRec *dec )
 {
-  if (cc<0 || cc>=MAX_MAPCODE_TERRITORY_CODE) return ""; else
+  int parentcode=-1;
+  int err=-255; // unknown error
+  int ccode,len;
+  char *minus;
+  const char *iso3;
+  char *s = dec->minput;
+
+  // copy input, cleaned of leading and trailing whitespace, into private, non-const buffer
   {
-    int p=stateletter(cc);
-    const char* ei=entity_iso3(cc);
-    if (*ei>='0' && *ei<='9') ei++;
-    if (makeiso_buf==makeiso_bufbytes) makeiso_buf=makeiso_bufbytes+8; else makeiso_buf=makeiso_bufbytes;
-    if (longcode && p)
-    {
-      memcpy(makeiso_buf,&parents2[p*3-3],2);
-      makeiso_buf[2]='-';
-      strcpy(makeiso_buf+3,ei);
-    }
-    else
-    {
-      strcpy(makeiso_buf,ei);
-    }
-    return makeiso_buf;
+    const char *r = dec->orginput;
+    while (*r>0 && *r<=32) r++; // skip lead
+    len=strlen(r);
+    if (len>MAX_MAPCODE_RESULT_LEN-1) len=MAX_MAPCODE_RESULT_LEN-1;
+    while (len>0 && r[len-1]>=0 && r[len-1]<=32) len--; // remove trail
+    memcpy(s,r,len); s[len]=0;
   }
-}
-
-
-
-static int resultlen(const char *result)
-{
-  const char* hpos = strchr(result,'-');
-  if (hpos)
-    return hpos-result;
-  return strlen(result);
-}
 
-// TODO: Unused code - remove or place in mapcoder.h.
-// returns empty string if error (e.g. bad iso);
-// returns nonzero if a code was generated
-static int mapcode_encode(char *result,long y, long x, const char *iso3, char *isofound)
-{
-  int cc=ccode_of_iso3(iso3);
-  master_encode(result,cc,x,y,-1,1,1,0);
-  if (isofound)
+  // make input (excluding territory) uppercase, and replace digits 0 and 1 with O and I
   {
-    *isofound=0;
-    if (*result) {
-      if (resultlen(result)==10)
-        strcpy(isofound,makeiso(ccode_earth,1));
-      else
-        strcpy(isofound,makeiso(cc,1));
+    char *t = strchr(s,' '); if (t==NULL) t=s;
+    for(;*t!=0;t++)
+    {
+      if (*t>='a' && *t<='z') *t += ('A'-'a');
+      if (*t=='O') *t='0';
+      if (*t=='I') *t='1';
     }
   }
-  return *result;
-}
-
-
-// returns nonzero if error
-// if ccode_found!=NULL
-static int full_mapcode_decode(long *y, long *x, const char *iso3, const char *orginput,int *ccode_found,char *clean_input)
-{
-  char input[MAX_MAPCODE_RESULT_LEN];
-  int err,ccode,len;
-  char *s=(char*)orginput;
-  int ilen=strlen(iso3);
-
-  if (iso3) disambiguate_str(iso3,strlen(iso3));
 
-  if (clean_input) *clean_input=0;
+  // check if extension, determine length without extension
+  minus = strchr(s+4,'-');
+  if (minus)
+    len=minus-s;
 
-  while (*s>0 && *s<=32) s++; // skip lead
-  len=strlen(s);
+  // make sure there is valid context
+  iso3 = convertTerritoryCodeToIsoName(dec->context,0); // get context string (or empty string)
+  if (*iso3==0) iso3="AAA";
+  parentcode=disambiguate_str(iso3,strlen(iso3)); // pass for future context disambiguation
 
-  if (len>MAX_MAPCODE_RESULT_LEN-1) len=MAX_MAPCODE_RESULT_LEN-1;
-  memcpy(input,s,len); s=input; s[len]=0;
-
-
- {
-   char *min = strchr(s+4,'-');
-   if (min) {
-     *min++=0;
-     extrapostfix=&orginput[min-s];
-     len=strlen(s);
-   } else extrapostfix="";
- }
-
-  // remove trail
-  while (len>0 && s[len-1]>=0 && s[len-1]<=32) { s[--len]=0; }
-
-  if (len>0 && len<10 && ilen<7 && strchr(s,' ')==0) // no space in input (so just a mapcode?); and room for ISO-space-MAPCODE?
+  // insert context if none in input
+  if (len>0 && len<=9 && strchr(s,' ')==0) // just a non-international mapcode without a territory code?
   {
-      memmove(s+ilen+1,s,len+1);
+      int ilen=strlen(iso3);
+      memmove(s+ilen+1,s,strlen(s)+1);
       s[ilen]=' ';
       memcpy(s,iso3,ilen);
       len+=(1+ilen);
       iso3="";
   }
+  // parse off extension
+  s[len]=0;
+  if (minus)
+    dec->extension = &s[len+1];
+  else
+    dec->extension="";
 
-
+  // now split off territory, make point to start of proper mapcode
   if (len>8 && (s[3]==' ' || s[3]=='-') && (s[6]==' ' || s[7]==' ')) // assume ISO3 space|minus ISO23 space MAPCODE
   {
-    int p=disambiguate_str(s,3);
-    if (p<0) return p;
+    parentcode=disambiguate_str(s,3);
+    if (parentcode<0) return parentcode;
     s+=4; len-=4;
   }
   else if (len>7 && (s[2]==' ' || s[2]=='-') && (s[5]==' ' || s[6]==' ')) // assume ISO2 space|minus ISO23 space MAPCODE
   {
-    int p=disambiguate_str(s,2);
-    if (p<0) return p;
+    parentcode=disambiguate_str(s,2);
+    if (parentcode<0) return parentcode;
     s+=3; len-=3;
   }
 
-
   if (len>4 && s[3]==' ') // assume ISO whitespace MAPCODE, overriding iso3
   {
     iso3=s; // overrides iso code!
@@ -2163,76 +1500,173 @@ static int full_mapcode_decode(long *y, long *x, const char *iso3, const char *o
     s+=3;len-=3;
   }
 
-
   while (*s>0 && *s<=32) {s++;len--;} // skip further whitespace
 
   // returns nonzero if error
-  ccode = ccode_of_iso3(iso3);
-  if (ccode==ccode_mex && len<8) ccode=ccode_of_iso3("5MX"); // special case for mexico country vs state
+  ccode = ccode_of_iso3(iso3,parentcode);
+  if (ccode==ccode_mex && len<8) ccode=ccode_of_iso3("5MX",-1); // special case for mexico country vs state
+
+  // master_decode(s,ccode)
+  {
+  const char *dot = NULL; // dot position in input
+  int prelen;   // input prefix length
+  int postlen;  // input postfix length
+  int codex;    // input codex
+  int from,upto; // record range for territory
+  int i;
+
+
+  // unpack digits (a-lead or aeu-encoded
+  int voweled = unpack_if_alldigits(s);
+  if (voweled<0)
+    return -7;
 
-  if (ccode_found) *ccode_found=ccode;
+  // debug support: U-lead pre-processing
+  if (*s=='u' || *s=='U')  {
+    s++;
+    len--;
+    voweled=1;
+  }
 
+  if (len>10) return -8;
+
+  // find dot and check that all characters are valid
   {
-    char *t;
-    for(t=s;*t!=0;t++)
+    int nrd=0; // nr of true digits
+    const char *r=s;
+    for ( ; *r!=0; r++ )
     {
-      if (*t>='a' && *t<='z') *t += ('A'-'a');
-      if (*t=='O') *t='0';
-      if (*t=='I') *t='1';
+      if (*r=='.') {
+        if (dot)
+          return -5; // more than one dot
+        dot=r;
+      }
+      else if ( decodeChar(*r) <  0 ) // invalid char?
+        return -4;
+      else if ( decodeChar(*r) < 10 ) // digit?
+        nrd++;
     }
+    if (dot==NULL)
+      return -2;
+    else if (!voweled && nrd+1==len) // everything but the dot is digit, so MUST be voweled!
+      return -998;
   }
 
-  if (*extrapostfix) {
-    strcat(s,"-");
-    strcat(s,extrapostfix);
-    err = master_decode(  x,y,s,"",ccode,0,0);
+//////////// AT THIS POINT, dot=FIRST DOT, input=CLEAN INPUT (no vowels) ilen=INPUT LENGTH
+
+  // analyse input
+  prelen = (dot-s);
+  postlen = len-1-prelen;
+  codex = prelen*10 + postlen;
+  if ( prelen<2 || prelen>5 || postlen<2 || postlen>4 )
+    return -3;
+
+  if (len==10) {
+    // international mapcodes must be in international context
+    ccode = ccode_earth;
   }
-  else {
-    err = master_decode(  x,y,s,"",ccode,0,0);
+  else if (isSubdivision(ccode))
+  {
+    // long mapcodes must be interpreted in the parent of a subdivision
+
+	  int parent = ParentTerritoryOf(ccode);
+	  if (len==9 || (len==8 && (parent==ccode_ind || parent==ccode_mex )))
+		  ccode = parent;
   }
 
-  if (clean_input && len<=10)
-  {
-    strcpy(clean_input,s);
-    if (*extrapostfix)
+  // remember final territory context
+  dec->context = ccode;
+  dec->mapcode = s;
+
+  err  = -817;
+  from = firstrec(ccode);
+  upto = lastrec(ccode);
+
+   // try all ccode rectangles to decode s (pointing to first character of proper mapcode)
+   for ( i = from; i <= upto; i++ )
+   {
+    int codexi = coDex(i);
+	  if ( recType(i)==0 && !isNameless(i) && (codexi==codex || (codex==22 && codexi==21) ) )
+	  {
+      err = decodeGrid( dec, i, 0 );
+
+      if (isRestricted(i)) {
+        int fitssomewhere=0;
+        int j;
+        for (j=i-1; j>=from; j--) { // look in previous rects
+          if (!isRestricted((j))) {
+            if ( fitsInsideWithRoom(dec->lon32,dec->lat32,j) ) {
+              fitssomewhere=1;
+              break;
+            }
+          }
+        }
+        if (!fitssomewhere) {
+          err=-1234;
+        }
+      }
+
+		  break;
+	  }
+	  else if ( recType(i)==1 && prefixLength(i)+1==prelen && postfixLength(i)==postlen && headerLetter(i)==*s )
+	  {
+      err = decodeGrid( dec, i, 1 );
+		  break;
+	  }
+	  else if (isNameless(i) &&
+	   (	(codexi==21 && codex==22)
+	   ||	(codexi==22 && codex==32)
+	   ||	(codexi==13 && codex==23) ) )
+	  {
+      i = decodeNameless( dec, i);
+      if (i<0) err=i; else err=0;
+		  break;
+	  }
+	  else if ( recType(i)>=2 && postlen==3 && prefixLength(i)+postfixLength(i)==prelen+2 )
     {
-      strcat(clean_input,"-");
-      strcat(clean_input,extrapostfix);
-    }
-    makeup(clean_input);
+		  err = decodeAutoHeader( dec, i );
+		  break;
+	  }
+   } // for
   }
 
-  if (err)
-  {
-    #ifdef REMOVE_VALIDCODE
-      *x=*y=0;
-    #else
-      if (ccode<0 || valid_code(s)<0 ) // bad iso or bad input
-      {
-        *x=*y=0;
-      }
-      else if (err && ccode>=0)
-      {
-        long miny,maxy,minx,maxx;
-        setup_country(ccode);
-        getboundaries((data_start[ccode]),minx,miny,maxx,maxy);
-        *x = (minx+maxx)/2;
-        *y = (miny+maxy)/2;
-      }
-    #endif // REMOVE_VALIDCODE
+
+#ifdef SUPPORT_HIGH_PRECISION
+  // convert from millionths
+  if (err) {
+    dec->lat = dec->lon = 0;
+  }
+  else {
+    dec->lat /= (double)1000000.0;
+    dec->lon /= (double)1000000.0;
   }
+#else
+  // convert from millionths
+  if (err) dec->lat32 = dec->lon32 = 0;
+  dec->lat = dec->lat32/(double)1000000.0;
+  dec->lon = dec->lon32/(double)1000000.0;
+#endif
 
   // normalise between =180 and 180
-  if ( *x>180000000 ) *x-=360000000; else if ( *x<-180000000 ) *x+=360000000;
+  if (dec->lat <  -90.0) dec->lat  = -90.0;
+  if (dec->lat >   90.0) dec->lat  =  90.0;
+  if (dec->lon < -180.0) dec->lon += 360.0;
+  if (dec->lon >= 180.0) dec->lon -= 360.0;
+
+  // store as integers for legacy's sake
+  dec->lat32 = (long)(dec->lat*1000000);
+  dec->lon32 = (long)(dec->lon*1000000);
+
+  // make sure decode result fits the country
+  if (err==0)
+    if ( ccode != ccode_earth )
+      if ( ! fitsInsideWithRoom(dec->lon32,dec->lat32, lastrec(ccode) ) ) {
+        err=-2222;
+  }
 
   return err;
 }
 
-// TODO: Unused code - remove or place in mapcoder.h.
-static int mapcode_decode(long *y, long *x, const char *iso3, const char *orginput,int *ccode_found)
-{
-  return full_mapcode_decode(y,x,iso3,orginput,ccode_found,NULL);
-}
 
 
 #ifdef SUPPORT_FOREIGN_ALPHABETS
@@ -2291,11 +1725,10 @@ static struct { UWORD min; UWORD max; const char *convert; } unicode2asc[] =
 
 
 
-static char asciibuf[16];
-static const char *decode_utf16(const UWORD* s)
+char *convertToRoman(char *asciibuf, int maxlen, const UWORD* s)
 {
   char *w = asciibuf;
-  const char *e = w+16-1;
+  const char *e = w+maxlen-1;
   for ( ; *s!=0 && w<e ; s++  )
   {
     if ( *s>=1 && *s<='z' ) // normal ascii
@@ -2326,11 +1759,10 @@ static const char *decode_utf16(const UWORD* s)
 }
 
 
-static UWORD unibuf[16];
-static const UWORD* encode_utf16(const char *mapcode,int language) // convert mapcode to language (0=roman 1=greek 2=cyrillic 3=hebrew)
+static UWORD* encode_utf16(UWORD* unibuf,int maxlen,const char *mapcode,int language) // convert mapcode to language (0=roman 1=greek 2=cyrillic 3=hebrew)
 {
   UWORD *w = unibuf;
-  const UWORD *e = w+16-1;
+  const UWORD *e = w+maxlen-1;
   const char *r = mapcode;
   while( *r!=0 && w<e )
   {
@@ -2358,274 +1790,200 @@ static const UWORD* encode_utf16(const char *mapcode,int language) // convert ma
 
 
 
-#define TOKENSEP  0
-#define TOKENDOT  1
-#define TOKENCHR  2
-#define TOKENZERO 3
-#define TOKENHYPH 4
+#define TOKENSEP   0
+#define TOKENDOT   1
+#define TOKENCHR   2
+#define TOKENVOWEL 3
+#define TOKENZERO  4
+#define TOKENHYPH  5
 #define ERR -1
 #define Prt -9 // partial
 #define GO  99
 
-  static signed char fullmc_statemachine[23][5] = {
-                      // WHI DOT DET ZER HYP
-  /* 0 start        */ {  0 ,ERR, 1 ,ERR,ERR }, // looking for very first detter
-  /* 1 gotL         */ { ERR,ERR, 2 ,ERR,ERR }, // got one detter, MUST get another one
-  /* 2 gotLL        */ { 18 , 6 , 3 ,ERR,14  }, // GOT2: white: got territory + start prefix | dot: 2.X mapcode | det:3letter | hyphen: 2-state
-  /* 3 gotLLL       */ { 18 , 6 , 4 ,ERR,14  }, // white: got territory + start prefix | dot: 3.X mapcode | det:4letterprefix | hyphen: 3-state
-  /* 4 gotprefix4   */ { ERR, 6 , 5 ,ERR,ERR }, // dot: 4.X mapcode | det: got 5th prefix letter
-  /* 5 gotprefix5   */ { ERR, 6 ,ERR,ERR,ERR }, // got 5char so MUST get dot!
-  /* 6 prefix.      */ { ERR,ERR, 7 ,Prt,ERR }, // MUST get first letter after dot
-  /* 7 prefix.L     */ { ERR,ERR, 8 ,Prt,ERR }, // MUST get second letter after dot
-  /* 8 prefix.LL    */ { 22 ,ERR, 9 , GO,11  }, // get 3d letter after dot | X.2- | X.2 done!
-  /* 9 prefix.LLL   */ { 22 ,ERR,10 , GO,11  }, // get 4th letter after dot | X.3- | X.3 done!
-  /*10 prefix.LLLL  */ { 22 ,ERR,ERR, GO,11  }, // X.4- | x.4 done!
-
-  /*11 mc-          */ { ERR,ERR,12 ,Prt,ERR }, // MUST get first precision letter
-  /*12 mc-L         */ { 22 ,ERR,13 , GO,ERR }, // Get 2nd precision letter | done X.Y-1
-  /*13 mc-LL        */ { 22 ,ERR,ERR, GO,ERR }, // done X.Y-2 (*or skip whitespace*)
-
-  /*14 ctry-        */ { ERR,ERR,15 ,ERR,ERR }, // MUST get first state letter
-  /*15 ctry-L       */ { ERR,ERR,16 ,ERR,ERR }, // MUST get 2nd state letter
-  /*16 ctry-LL      */ { 18 ,ERR,17 ,ERR,ERR }, // white: got CCC-SS and get prefix | got 3d letter
-  /*17 ctry-LLL     */ { 18 ,ERR,ERR,ERR,ERR }, // got CCC-SSS so MUST get whitespace and then get prefix
-
-  /*18 startprefix  */ { 18 ,ERR,19 ,ERR,ERR }, // skip more whitespace, MUST get 1st prefix letter
-  /*19 gotprefix1   */ { ERR,ERR,20 ,ERR,ERR }, // MUST get second prefix letter
-  /*20 gotprefix2   */ { ERR, 6 ,21 ,ERR,ERR }, // dot: 2.X mapcode | det: 3d perfix letter
-  /*21 gotprefix3   */ { ERR, 6 , 4 ,ERR,ERR }, // dot: 3.x mapcode | det: got 4th prefix letter
-
-  /*22 whitespace   */ { 22 ,ERR,ERR, GO,ERR }  // whitespace until end of string
-
+  static signed char fullmc_statemachine[23][6] = {
+                      // WHI DOT DET VOW ZER HYP
+  /* 0 start        */ {  0 ,ERR, 1 , 1 ,ERR,ERR }, // looking for very first detter
+  /* 1 gotL         */ { ERR,ERR, 2 , 2 ,ERR,ERR }, // got one detter, MUST get another one
+  /* 2 gotLL        */ { 18 , 6 , 3 , 3 ,ERR,14  }, // GOT2: white: got territory + start prefix | dot: 2.X mapcode | det:3letter | hyphen: 2-state
+  /* 3 gotLLL       */ { 18 , 6 , 4 ,ERR,ERR,14  }, // white: got territory + start prefix | dot: 3.X mapcode | det:4letterprefix | hyphen: 3-state
+  /* 4 gotprefix4   */ { ERR, 6 , 5 ,ERR,ERR,ERR }, // dot: 4.X mapcode | det: got 5th prefix letter
+  /* 5 gotprefix5   */ { ERR, 6 ,ERR,ERR,ERR,ERR }, // got 5char so MUST get dot!
+  /* 6 prefix.      */ { ERR,ERR, 7 , 7 ,Prt,ERR }, // MUST get first letter after dot
+  /* 7 prefix.L     */ { ERR,ERR, 8 , 8 ,Prt,ERR }, // MUST get second letter after dot
+  /* 8 prefix.LL    */ { 22 ,ERR, 9 , 9 , GO,11  }, // get 3d letter after dot | X.2- | X.2 done!
+  /* 9 prefix.LLL   */ { 22 ,ERR,10 ,10 , GO,11  }, // get 4th letter after dot | X.3- | X.3 done!
+  /*10 prefix.LLLL  */ { 22 ,ERR,ERR,ERR, GO,11  }, // X.4- | x.4 done!
+
+  /*11 mc-          */ { ERR,ERR,12 ,ERR,Prt,ERR }, // MUST get first precision letter
+  /*12 mc-L         */ { 22 ,ERR,13 ,ERR, GO,ERR }, // Get 2nd precision letter | done X.Y-1
+  /*13 mc-LL*       */ { 22 ,ERR,13 ,ERR, GO,ERR }, // *** keep reading precision detters *** until whitespace or done
+
+  /*14 ctry-        */ { ERR,ERR,15 ,15 ,ERR,ERR }, // MUST get first state letter
+  /*15 ctry-L       */ { ERR,ERR,16 ,16 ,ERR,ERR }, // MUST get 2nd state letter
+  /*16 ctry-LL      */ { 18 ,ERR,17 ,17 ,ERR,ERR }, // white: got CCC-SS and get prefix | got 3d letter
+  /*17 ctry-LLL     */ { 18 ,ERR,ERR,ERR,ERR,ERR }, // got CCC-SSS so MUST get whitespace and then get prefix
+
+  /*18 startprefix  */ { 18 ,ERR,19 ,19 ,ERR,ERR }, // skip more whitespace, MUST get 1st prefix letter
+  /*19 gotprefix1   */ { ERR,ERR,20 ,ERR,ERR,ERR }, // MUST get second prefix letter
+  /*20 gotprefix2   */ { ERR, 6 ,21 ,ERR,ERR,ERR }, // dot: 2.X mapcode | det: 3d perfix letter
+  /*21 gotprefix3   */ { ERR, 6 , 4 ,ERR,ERR,ERR }, // dot: 3.x mapcode | det: got 4th prefix letter
+
+  /*22 whitespace   */ { 22 ,ERR,ERR,ERR, GO,ERR }  // whitespace until end of string
   };
 
+
+
   // pass fullcode=1 to recognise territory and mapcode, pass fullcode=0 to only recognise proper mapcode (without optional territory)
   // returns 0 if ok, negative in case of error (where -999 represents "may BECOME a valid mapcode if more characters are added)
   int compareWithMapcodeFormat(const char *s,int fullcode)
   {
-    int nondigits=0;
+    int nondigits=0,vowels=0;
     int state=(fullcode ? 0 : 18); // initial state
     for(;;s++) {
       int newstate,token;
-      // recognise token
-      if (*s>='0' && *s<='9') token=TOKENCHR;
-      else if ((*s>='a' && *s<='z') || (*s>='A' && *s<='Z'))
-        { token=TOKENCHR; if (state!=11 && state!=12) nondigits++; }
-      else if (*s=='.' ) token=TOKENDOT;
+      // recognise token: decode returns -2=a -3=e -4=0, 0..9 for digit or "o" or "i", 10..31 for char, -1 for illegal char
+      if (*s=='.' ) token=TOKENDOT;
       else if (*s=='-' ) token=TOKENHYPH;
       else if (*s== 0  ) token=TOKENZERO;
       else if (*s==' ' || *s=='\t') token=TOKENSEP;
-      else return -4; // invalid character
+      else {
+        signed char c = decode_chars[(unsigned char)*s];
+        if (c<0) { // vowel or illegal?
+          token=TOKENVOWEL; vowels++;
+          if (c==-1) // illegal?
+            return -4;
+        } else if (c<10) { // digit
+          token=TOKENCHR; // digit
+        } else { // charcter B-Z
+          token=TOKENCHR;
+          if (state!=11 && state!=12 && state!=13) nondigits++;
+        }
+      }
       newstate = fullmc_statemachine[state][token];
       if (newstate==ERR)
         return -(1000+10*state+token);
-      if (newstate==GO )
-        return (nondigits>0 ? 0 : -5);
-      if (newstate==Prt)
+      else if (newstate==GO )
+        return (nondigits ? (vowels>0 ? -6 : 0) : (vowels>0 && vowels<=2 ? 0 : -5));
+      else if (newstate==Prt)
         return -999;
+      else if (newstate==18)
+        nondigits=vowels=0;
       state=newstate;
-      if (state==18)
-        nondigits=0;
     }
   }
 
-// TODO: Unused code - remove or place in mapcoder.h.
-static int lookslike_mapcode(const char *s)  // return -999 if partial, 0 if ok, negative if not
-{
-  // old-style recognizer, does not suport territory context
-  return compareWithMapcodeFormat(s,0);
-}
 
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 //
-//  Freebee: interpret coordinates, separated by either space or comma (if comma, whitespace allowed everywhere else)
-//   [signletters*] v1 [degreesymbol [v2 [minutesym [v3 [secondsym]]]]] [letter]
+//  Engine
 //
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-static unsigned char *addnum(unsigned char *r,long v,int fill2,unsigned char unit)
-{
-  if (v>=100) { *r++=(unsigned char)('0'+(v/100)); v%=100; }
-  if (fill2 || v>=10) { *r++=(unsigned char)('0'+(v/10)); v%=10; }
-  *r++=(unsigned char)('0'+v);
-  if (unit) *r++=unit;
-  *r=0;
-  return r;
-}
-
-static void asdms1(unsigned char *r,double v,long max,unsigned char degsym) // worst case is -###d##'##", 11 char ex zts (or 10 if max=90)
-{
-  long d,m,s;
-  if (v<0) { *r++='-'; v=-v; }
-  s = (long)(3600*v+0.5); // round to seconds
-  if (s>max) s=max;
-  d=s/3600;
-  r=addnum(r,d,0,degsym);
-  s%=3600;
-  if (s)
-  {
-    m=s/60;
-    r=addnum(r,m,1,'\'');
-    s%=60;
-    if (s)
-      r=addnum(r,s,1,'\"');
-  }
-}
-
-// TODO: Unused code - remove or place in mapcoder.h.
-static unsigned char *asdms(unsigned char *r,double lat,double lon,unsigned char degsym) // worst case EXcluding zts is 22 bytes: -##d##'##",-###d##'##"
-{
-  asdms1(r,lat,90*3600,degsym);
-  strcat((char*)r,",");
-  asdms1(r+strlen((char*)r),lon,180*3600,degsym);
-  return r;
-}
 
-static int interpret_coord( const unsigned char *i, int islat, double *result )
+// pass point to an array of pointers (at least 42), will be made to point to result strings...
+// returns nr of results;
+static int encodeLatLonToMapcodes_internal( char **v, Mapcodes *mapcodes, double lat, double lon, int tc, int stop_with_one_result, int extraDigits ) // 1.31 allow to stop after one result
 {
-  int expnow=0; // expect now: 0=deg 1=min 2=sec 3=none
-  double d=0,m=0,s=0;
-
-  #define isdig(c) ((c)>='0' && (c)<='9')
-  #define iswhite(c) ((c)>0 && (c)<=32)
-  #define skipwhite(i) {while (iswhite(*i)) i++;}
-  #define skipnum(i) {while (isdig(*i)) i++;}
-  #define skipfp(i) {skipnum(i); if (*i=='.') {i++;skipnum(i);}}
-
-  const char *winds = islat ? "nsNS+- " : "ewEW+- ";
-
-  // skip white spaces, signs and appropriate wind direction letters
-  char *p;
-  int sign=1;
-
-  while (*i && (p=(char*)strchr(winds,*i))!=NULL) { { if ( (p-(char*)winds) & 1 ) sign*=-1; } i++; }
+  encodeRec enc;
+  enc.mapcodes = mapcodes;
+  enc.mapcodes->count=0;
 
-  // we are now at a lead digit, or there is an error
-  if (!isdig(*i))
-    return -12; // digit expected
+  if (lat<-90) lat=-90;
+  if (lat> 90) lat= 90;
+  if (lon<-180) lon+=360;
+  if (lon>=180) lon-=360;
+#ifndef SUPPORT_HIGH_PRECISION
+  lat*=1000000; if (lat<0) lat-=0.5; else lat+=0.5;
+  lon*=1000000; if (lon<0) lon-=0.5; else lon+=0.5;
+  enc.lat32=(long)lat;
+  enc.lon32=(long)lon;
+#else // precise encoding: do NOT round, instead remember the fraction...
+  lat+= 90;
+  lon+=180;
+  lat*=1000000;
+  lon*=1000000;
+  enc.lat32=(long)lat;
+  enc.lon32=(long)lon;
+  enc.fraclat=lat-enc.lat32;
+  enc.fraclon=lon-enc.lon32;
+  // for 8-digit precision, cells are divided into 810,000 by 810,000 minicells.
+  enc.fraclat *= 810000; if (enc.fraclat<1) enc.fraclat=0; else { if (enc.fraclat>809999) { enc.fraclat=0; enc.lat32++; } else enc.fraclat /= 810000; }
+  enc.fraclon *= 810000; if (enc.fraclon<1) enc.fraclon=0; else { if (enc.fraclon>809999) { enc.fraclon=0; enc.lon32++; } else enc.fraclon /= 810000; }
+  enc.lat32-= 90000000;
+  enc.lon32%=360000000;
+  enc.lon32-=180000000;
+#endif
 
-  while ( expnow<4 && isdig(*i) )
+  if (tc==0) // ALL results?
   {
-    // get value
-    double v=atof((char*)i); skipfp(i); skipwhite(i);
-    if ( *i && strchr("oOdD\x0F8\x0BA\x0B0\x0A7",*i) ) // degree symbol? $F8=248degree $BA=186 $B0=176 $A7=167
-    {
-      i++; skipwhite(i);
-      d=v; expnow=1; // after degree, expect minutes
-    }
-    else if ( *i && strchr("\'`mM\x0B4\x093",*i) && i[1]!=i[0] ) // minute symbol (NOT repeated, else assume seconds symbol)  $B4=180 $93=147
-    {
-      i++; skipwhite(i);
-      m=v; expnow=2; // after minutes, expect seconds
-    }
-    else if ( *i && strchr("\"\'`\x094\x084",*i) ) // seconds symbol? $94=148 $84=132
-    {
-      if (i[0]==i[1]) i++; i++; skipwhite(i);
-      s=v; expnow=3; // after seconds, expect something explicitly specified
-    }
-    else // anything else? assume that we got what we expected
-    {
-      if (expnow==0) d=v; else if (expnow==1) m=v; else if (expnow==2) s=v; else return -18; // -18 = trailing unitless number
-      expnow=4;
+    int i;
+    for(i=0;i<MAX_MAPCODE_TERRITORY_CODE;i++) {
+      encoderEngine(i,&enc,stop_with_one_result,extraDigits,-1);
+      if ((stop_with_one_result||debugStopAt>=0) && enc.mapcodes->count>0) break;
     }
   }
-
-  // allow all posisble final endsigns
-  { while (*i && (p=(char*)strchr(winds,*i))!=NULL) { if ( (p-(char*)winds) & 1 ) sign*=-1; i++; } }
-
-  // we now MUST be at the end of the string!
-  if (*i)
-    return -17; // trash trailing
-
-  *result = (d+m/60.0+s/3600.0) * sign;
-  if ( islat && (*result< -90 || *result> 90)) return -13;
-  if (!islat && (*result<-180 || *result>180)) return -14;
-
-  return 0;
-}
-
-// TODO: Unused code - remove or place in mapcoder.h.
-static int interpret_coords( unsigned char *i, double *x, double *y  ) // returns negative if impossible
-{
-  unsigned char *sep=NULL;
-  unsigned char *altsep=NULL;
-  unsigned char *s;
-  unsigned char *firstcompass=NULL;
-  skipwhite(i); // skip leading nonsense
-  for (s=i;*s!=0;s++)
+  else
   {
-    switch (*s)
-    {
-    case 'N':case 'S':case 'W':case 'E':
-    case 'n':case 's':case 'w':case 'e':
-      if (firstcompass==NULL) firstcompass=s; // determine first compass letter before comma (if any)
-      break;
-    case '+':case '-':
-    case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':
-    case '\"': case 148: case 132: // second CP1252
-    case 'm': case 'M': case '\'': case '`': case 180: case 147: // minute CP1252
-    case 'o': case 'O': case 'd': case 'D': case 248: case 186: case 176: case 167: // 167:cp850
-    case '.':
-      break;
-    case ' ':
-      if (altsep) altsep=i; else altsep=s;
-      while (*s==' ') s++;
-      s--;
-      break;
-    case ',': case 130:
-      if (sep) return -1; // more than one comma!
-      sep=s;
-      if (firstcompass==NULL) firstcompass=s;
-      break;
-    default:
-      return -2; // invalid char
-    }
+    encoderEngine((tc-1),&enc,stop_with_one_result,extraDigits,-1);
   }
-  if (sep==NULL && altsep!=NULL) sep=altsep; // use whitespace as sep if no comma
-  if (sep==NULL) return -3; // no separator
-  if (sep==i) return -4; // separator as lead
 
+  if (v)
   {
-    int e;
-
-    if (firstcompass && *firstcompass && strchr("EWew",*firstcompass))
-    {
-      unsigned char t=*sep; *sep=0;
-      e=interpret_coord(i,0,x);
-      *sep=t;
-      if (!e) e=interpret_coord(sep+1,1,y);
-    }
-    else
-    {
-      unsigned char t=*sep; *sep=0;
-      e=interpret_coord(i,1,y);
-      *sep=t;
-      if (!e) e=interpret_coord(sep+1,0,x);
+    int i;
+    for(i=0;i<enc.mapcodes->count;i++) {
+      char *s = &enc.mapcodes->mapcode[i][0];
+      char *p = strchr( s, ' ' );
+      if (p==NULL) {
+        v[i*2+1] = (char*) "AAA";
+        v[i*2  ] = s;
+      }
+      else {
+        *p++=0;
+        v[i*2+1] = s;
+        v[i*2  ] = p;
+      }
     }
-
-    if (e) return e;
   }
 
-  return 0; // POSSIBLE
+  return enc.mapcodes->count;
 }
 
 
-
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 //
 //  Wrapper for LBS team
 //
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
-
-const char *convertTerritoryCodeToIsoName(int tc,int format) // formats: 0=full 1=short (returns empty string in case of error)
+// threadsafe
+char* getTerritoryIsoName(char *result, int tc, int format) // formats: 0=full 1=short (returns empty string in case of error)
 {
-  return makeiso(tc-1,(format==0));
+  if (tc<1 || tc>MAX_MAPCODE_TERRITORY_CODE)
+    *result=0;
+  else {
+    int p=stateletter(tc-1);
+    char iso3[4];
+    const char *ei = get_entity_iso3(iso3,tc-1);
+    if (*ei>='0' && *ei<='9') ei++;
+    if (format==0 && p)
+    {
+      memcpy(result,&parents2[p*3-3],2);
+      result[2]='-';
+      strcpy(result+3,ei);
+    }
+    else
+    {
+      strcpy(result,ei);
+    }
+  }
+  return result;
 }
 
-int getParentCountryOfState(int tc) // returns negative if tc is not a code that has a parent country
+
+
+int getParentCountryOf(int tc) // returns negative if tc is not a code that has a parent country
 {
-    int parentccode=stateparent(tc-1); // returns parent ccode or -1
+    int parentccode=ParentTerritoryOf(tc-1); // returns parent ccode or -1
     if (parentccode>=0) return parentccode+1;
     return -1;
 }
@@ -2634,7 +1992,7 @@ int getCountryOrParentCountry(int tc) // returns tc if tc is a country, parent c
 {
   if (tc>0 && tc<MAX_MAPCODE_TERRITORY_CODE)
   {
-    int tp=getParentCountryOfState(tc);
+    int tp=getParentCountryOf(tc);
     if (tp>0) return tp;
     return tc;
   }
@@ -2648,7 +2006,7 @@ int convertTerritoryIsoNameToCode(const char *string,int optional_tc) // optiona
   while (*string>0 && *string<=32) string++; // skip leading whitespace
   if (ccode<0 || strchr(string,'-')>=0 || strlen(string)>3 )
   {
-    ccode=ccode_of_iso3(string); // ignore optional_tc
+    ccode=ccode_of_iso3(string,-1); // ignore optional_tc
   }
   else // there is a ccode, there is no hyphen in the string, and the string is as most 3 chars
   {
@@ -2658,150 +2016,111 @@ int convertTerritoryIsoNameToCode(const char *string,int optional_tc) // optiona
     strcpy(tmp,convertTerritoryCodeToIsoName(tc,1)); // short parent country code
     strcat(tmp,"-");
     strcat(tmp,string);
-    ccode=ccode_of_iso3(tmp);
+    ccode=ccode_of_iso3(tmp,-1);
   }
   if (ccode<0) return -1; else return ccode+1;
 }
 
-// pass point to an array of pointers (at least 64), will be made to point to result strings...
-// returns nr of results;
-int encodeLatLonToMapcodes_full( char **v, double lat, double lon, int tc, int stop_with_one_result, int extraDigits ) // 1.31 allow to stop after one result
-{
-  long lat32,lon32;
-  int ccode=tc-1;
-  if (tc==0) ccode=0;
-  if (ccode<0 || ccode>=MAX_MAPCODE_TERRITORY_CODE) return 0;
-  if (lat<-90 || lat>90 || lon<-180 || lon>180) return 0;
-  if (lon<-180) lon+=360;
-  if (lon>=180) lon-=360;
-  if (extraDigits<0) extraDigits=0; else if (extraDigits>MAXPRECISIONDIGITS) extraDigits=MAXPRECISIONDIGITS; use_high_precision=extraDigits;
-#ifndef VERSION160
-  lat*=1000000; if (lat<0) lat-=0.5; else lat+=0.5;
-  lon*=1000000; if (lon<0) lon-=0.5; else lon+=0.5;
-  lat32=(long)lat;
-  lon32=(long)lon;
-#else // precise encoding: do NOT round, instead remember the fraction...
-  lat+=180;
-  lon+=360;
-  lat*=1000000;
-  lon*=1000000;
-  lat32=(long)lat;
-  lon32=(long)lon;
-  fraclat=lat-lat32;
-  fraclon=lon-lon32;
-  // for 8-digit precision, cells are divided into 810,000 by 810,000 minicells.
-  fraclat *= 810000; if (fraclat<1) fraclat=0; else { if (fraclat>809999) { fraclat=0; lat32++; } else fraclat /= 810000; }
-  fraclon *= 810000; if (fraclon<1) fraclon=0; else { if (fraclon>809999) { fraclon=0; lon32++; } else fraclon /= 810000; }
-
-  /*
-  {
-    long fraclonTOP,fraclatTOP,BOTTOM;
-         if ( extraDigits==0 ) { BOTTOM=     1;}
-    else if ( extraDigits<=2 ) { BOTTOM=    30;}
-    else if ( extraDigits<=4 ) { BOTTOM=   900;}
-    else if ( extraDigits<=6 ) { BOTTOM= 27000;}
-    else if ( extraDigits<=8 ) { BOTTOM=810000;}
-
-    fraclatTOP = (long)( fraclat * BOTTOM + 0.4 );
-    fraclonTOP = (long)( fraclon * BOTTOM + 0.4 );
-    if (fraclatTOP==BOTTOM) { fraclatTOP=0; lat32++; }
-    if (fraclatTOP<=0) fraclat=0;
-    if (fraclonTOP==BOTTOM) { fraclonTOP=0; lon32++; }
-    if (fraclonTOP<=0) fraclon=0;
-  }
-  */
 
-  lat32-=180000000;
-  lon32-=360000000;
-#endif
-  nr_global_results=0;
-  global_results=v;
-  if (ccode==0)
-  {
-    int i;
-    for(i=0;i<MAX_MAPCODE_TERRITORY_CODE;i++) {
-      master_encode(NULL,i,lon32,lat32,-1,stop_with_one_result,0,0); // 1.29 - also add parents recursively
-      if ((stop_with_one_result||debugStopAt>=0) && nr_global_results>0) break;
-    }
-  }
-  else
-  {
-    master_encode(NULL,ccode,lon32,lat32,-1,stop_with_one_result,0,0); // 1.29 - also add parents recursively
-  }
-  global_results=NULL;
-  return nr_global_results/2;
-}
 
-// decode string into nx,ny; returns negative in case of error
-int decodeMapcodeToLatLon( double *lat, double *lon, const char *string, int context_tc ) // context_tc is used to disambiguate ambiguous short mapcode inputs; pass 0 or negative if not available
+// decode string into lat,lon; returns negative in case of error
+int decodeMapcodeToLatLon( double *lat, double *lon, const char *input, int context_tc ) // context_tc is used to disambiguate ambiguous short mapcode inputs; pass 0 or negative if not available
 {
-  if (lat==NULL || lon==NULL || string==NULL)
+  if (lat==NULL || lon==NULL || input==NULL)
   {
     return -100;
   }
   else
   {
-    long llat,llon;
-    const char *iso3 = convertTerritoryCodeToIsoName(context_tc,0);
-    int err=full_mapcode_decode(&llat,&llon,iso3,string,NULL,NULL);
-#ifdef VERSION160 // precise encoding: result built in extrax/y
-    *lat = extray/(double)1000000.0;
-    *lon = extrax/(double)1000000.0;
-#else
-    *lat = llat/1000000.0;
-    *lon = llon/1000000.0;
-#endif
-    while (*lat < -90.0) *lat = -90.0;
-    while  (*lat > 90.0) *lat = 90.0;
-    while (*lon < -180.0) *lon += 360.0; // @@@ V160 bugfix
-    while (*lon >= 180.0) *lon -= 360.0; // @@@ V160 bugfix
-    return err;
+    int ret;
+    decodeRec dec;
+    dec.orginput = input;
+    dec.context = context_tc;
+
+    ret = decoderEngine(&dec);
+    *lat = dec.lat;
+    *lon = dec.lon;
+    return ret;
   }
 }
 
 #ifdef SUPPORT_FOREIGN_ALPHABETS
 
-const char *decodeToRoman(const UWORD* s)
-{
-  return decode_utf16(s);
-}
-
-const UWORD* encodeToAlphabet(const char *mapcode,int alphabet) // 0=roman, 2=cyrillic
+UWORD* convertToAlphabet(UWORD* unibuf, int maxlength, const char *mapcode,int alphabet) // 0=roman, 2=cyrillic
 {
   if ( asc2lan[alphabet][4]==0x003f ) // alphabet has no letter E
     if ( strchr(mapcode,'E') || strchr(mapcode,'U') || strchr(mapcode,'e') || strchr(mapcode,'u') ) // v1.50 get rid of E and U
     {
-      char u[16];
-      strcpy(u,mapcode);
+      // safely copy mapcode into temporary buffer u
+      char u[MAX_MAPCODE_RESULT_LEN];
+      int len = strlen(mapcode);
+      if (len>=MAX_MAPCODE_RESULT_LEN)
+        len=MAX_MAPCODE_RESULT_LEN-1;
+      memcpy(u,mapcode,len);
+      u[len]=0;
       unpack_if_alldigits(u);
       repack_if_alldigits(u,1);
-      return encode_utf16(u,alphabet);
+      mapcode=u;
     }
-  return encode_utf16(mapcode,alphabet);
+  return encode_utf16(unibuf,maxlength,mapcode,alphabet);
 }
 
-#endif
 
-int encodeLatLonToMapcodes( char **v, double lat, double lon, int tc, int extraDigits )
+static char asciibuf[MAX_MAPCODE_RESULT_LEN];
+const char *decodeToRoman(const UWORD* s)
+{
+  return convertToRoman(asciibuf,MAX_MAPCODE_RESULT_LEN,s);
+}
+
+static UWORD unibuf[MAX_MAPCODE_RESULT_LEN];
+const UWORD* encodeToAlphabet(const char *mapcode,int alphabet) // 0=roman, 2=cyrillic
 {
-  return encodeLatLonToMapcodes_full(v,lat,lon,tc,0,extraDigits);
+  return convertToAlphabet(unibuf,MAX_MAPCODE_RESULT_LEN,mapcode,alphabet);
 }
 
+
+
+
+#endif
+
 int encodeLatLonToSingleMapcode( char *result, double lat, double lon, int tc, int extraDigits )
 {
   char *v[2];
-  int ret=encodeLatLonToMapcodes_full(v,lat,lon,tc,1,extraDigits);
+  Mapcodes rlocal;
+  int ret=encodeLatLonToMapcodes_internal(v,&rlocal,lat,lon,tc,1,extraDigits);
   *result=0;
-  if (ret>0) {
-    if (strcmp(v[1],"AAA")!=0) {
-      strcpy(result,v[1]);
-      strcat(result," ");
-    }
-    strcat(result,v[0]);
+  if (ret<=0) // no solutions?
+    return -1;
+  // prefix territory unless international
+  if (strcmp(v[1],"AAA")!=0) {
+    strcpy(result,v[1]);
+    strcat(result," ");
   }
-  return ret;
+  strcat(result,v[0]);
+  return 1;
 }
 
+// encodeLatLonToMapcodes is not threadsafe!
+int encodeLatLon( Mapcodes *results, double lat, double lon, int tc, int extraDigits )
+{
+  return encodeLatLonToMapcodes_internal(NULL,results,lat,lon,tc,0,extraDigits);
+}
 
-#endif // RELEASENEAT
+// Legacy: NOT threadsafe
+Mapcodes rglobal;
+int encodeLatLonToMapcodes( char **v, double lat, double lon, int tc, int extraDigits )
+{
+  return encodeLatLonToMapcodes_internal(v,&rglobal,lat,lon,tc,0,extraDigits);
+}
 
+// Legacy: NOT threadsafe
+static char makeiso_bufbytes[16];
+static char *makeiso_buf;
+const char *convertTerritoryCodeToIsoName(int tc,int format)
+{
+  if (makeiso_buf==makeiso_bufbytes) makeiso_buf=makeiso_bufbytes+8; else makeiso_buf=makeiso_bufbytes;
+  return (const char*)getTerritoryIsoName(makeiso_buf,tc,format);
+}
+
+
+#endif // RELEASENEAT
diff --git a/mapcodelib/mapcoder.h b/mapcodelib/mapcoder.h
index 4b6705e..6ca8577 100644
--- a/mapcodelib/mapcoder.h
+++ b/mapcodelib/mapcoder.h
@@ -18,19 +18,60 @@
 #define UWORD           unsigned short int  // 2-byte unsigned integer.
 #define SUPPORT_FOREIGN_ALPHABETS
 
-#define MAX_NR_OF_MAPCODE_RESULTS           48          // Max. number of results ever returned by encoder.
-#define MAX_PROPER_MAPCODE_LEN              10          // Max. number of characters in a proper mapcode
+#define MAX_NR_OF_MAPCODE_RESULTS           21          // Max. number of results ever returned by encoder (e.g. for 26.904899, 95.138515).
+#define MAX_PROPER_MAPCODE_LEN              10          // Max. number of characters in a proper mapcode (including the dot)
 #define MAX_PRECISION_DIGITS                8           // Max. number of extension characters (excluding the hyphen)
-#define MAX_ISOCODE_LEN                     7           // Max. number of characters of a valid territory code (RUS-KAM)
-#define MAX_CLEAN_MAPCODE_LEN               (MAX_PROPER_MAPCODE_LEN + 1 + MAX_PRECISION_DIGITS)  // Max. number of characters in a clean mapcode.
-#define MAX_MAPCODE_RESULT_LEN              (MAX_ISOCODE_LEN + MAX_CLEAN_MAPCODE_LEN + 2)        // Max. number of characters to store a single result (*including* zero-terminator).
+#define MAX_ISOCODE_LEN                     7           // Max. number of characters of a valid territory code; although nothing longer than SIX characters is ever generated (RU-KAM), users can input SEVEN characters (RUS-KAM)
+#define MAX_CLEAN_MAPCODE_LEN               (MAX_PROPER_MAPCODE_LEN + 1 + MAX_PRECISION_DIGITS)  // Max. number of characters in a clean mapcode (excluding zero-terminator)
+#define MAX_MAPCODE_RESULT_LEN              (MAX_ISOCODE_LEN + 1 + MAX_CLEAN_MAPCODE_LEN + 1)    // Max. number of characters to store a single result (including zero-terminator).
 #define COMPARE_MAPCODE_MISSING_CHARACTERS  -999        // Used for compareWithMapcodeFormat.
 
+
+/**
+ * The type Mapcodes hold a number of mapcodes, for example from an encoding call.
+ * If a result contains a space, it splits the territory alphacode from the mapcode.
+ * International mapcodes do not specify a territory alphacode, nor a space.
+ */
+typedef struct {
+  int count;                                                        // The number of mapcode results (length of array).
+  char mapcode[MAX_NR_OF_MAPCODE_RESULTS][MAX_MAPCODE_RESULT_LEN];  // The mapcodes.
+} Mapcodes;
+
+
 /**
  * Encode a latitude, longitude pair (in degrees) to a set of Mapcodes.
  *
  * Arguments:
- *      results         - Results set of Mapcodes. The caller must pass an array of at least MAX_NR_OF_MAPCODE_RESULTS
+ *      mapcodes        - a pointer to an Mapcodes, allocated by the caller.
+ *      lat             - Latitude, in degrees. Range: -90..90.
+ *      lon             - Longitude, in degrees. Range: -180..180.
+ *      territoryCode   - Territory code (obtained from convertTerritoryIsoNameToCode), used as encoding context.
+ *                        Pass 0 to get Mapcodes for all territories.
+ *      extraDigits     - Number of extra "digits" to add to the generated mapcode. The preferred default is 0.
+ *                        Other valid values are 1 and 2, which will add extra letters to the mapcodes to
+ *                        make them represent the coordinate more accurately.
+ *
+ * Returns:
+ *      Number of results stored in parameter results. Always >= 0 (0 if no encoding was possible or an error occurred).
+ *      The results are stored as pairs (Mapcode, territory name) in:
+ *          (results[0], results[1])...(results[(2 * N) - 2], results[(2 * N) - 1])
+ */
+
+int encodeLatLonToMapcodes(
+    Mapcodes* mapcodes,
+    double lat,
+    double lon,
+    int tc,
+    int extraDigits);
+
+/**
+ * WARNING: This method is deprecated and should no longer be used, as it is not thread-safe. Use the version
+ * specified above.
+ *
+ * Encode a latitude, longitude pair (in degrees) to a set of Mapcodes. Not thread-safe!
+ *
+ * Arguments:
+ *      results         - Results set of Mapcodes. The caller must pass an array of at least 2 * MAX_NR_OF_MAPCODE_RESULTS
  *                        string points, which must NOT be allocated or de-allocated by the caller.
  *                        The resulting strings are statically allocated by the library and will be overwritten
  *                        by the next call to this method!
@@ -47,7 +88,7 @@
  *      The results are stored as pairs (Mapcode, territory name) in:
  *          (results[0], results[1])...(results[(2 * N) - 2], results[(2 * N) - 1])
  */
-int encodeLatLonToMapcodes(
+int encodeLatLonToMapcodes(     // Warning: this method is deprecated and not thread-safe.
     char**  results,
     double  lat,
     double  lon,
@@ -135,13 +176,19 @@ int convertTerritoryIsoNameToCode(
  * Convert a territory name to a territory code.
  *
  * Arguments:
+ *      result          - String to store result
  *      territoryCode   - Territory code.
  *      format          - Pass 0 for full name, 1 for short name (state codes may be ambiguous).
  *
  * Returns:
- *      Static result string or 0 if failed. The string is allocated by the library and must NOT be
- *      de-allocated by the caller. It will be overwritten by a subsequent call to this method!
+ *      Pointer to result. Empty if territoryCode illegal.
  */
+char* getTerritoryIsoName(
+    char *result,
+    int tc,
+    int format);
+
+// the old, non-threadsafe routine which uses static storage, overwritten at each call:
 const char *convertTerritoryCodeToIsoName(
     int territoryCode,
     int format);
@@ -168,7 +215,7 @@ int getCountryOrParentCountry(int territoryCode);
  * Returns:
  *      Territory code of the parent country; <0 if the territoryCode was not a state or it was invalid.
  */
-int getParentCountryOfState(int territoryCode);
+int getParentCountryOf(int territoryCode);
 
 /**
  * Alphabets:
@@ -195,10 +242,17 @@ int getParentCountryOfState(int territoryCode);
  * Decode a string to Roman characters.
  *
  * Arguments:
- *      string - String to decode.
+ *      string   - String to decode.
+ *      asciibuf - Buffer to be filled with the result
+ *      maxlen   - Size of asciibuf
  *
  * Returns:
- *      Decoded string. The string is allocated by the library and must NOT be
+ *      pointer to asciibuf, which holds the result
+ */
+char *convertToRoman(char *asciibuf, int maxlen, const UWORD* string);
+/**
+ * old variant, not thread-safe: uses a pre-allocated static buffer, overwritten by the next call
+ *      Returns converted string. allocated by the library. String must NOT be
  *      de-allocated by the caller. It will be overwritten by a subsequent call to this method!
  */
 const char* decodeToRoman(const UWORD* string);
@@ -207,15 +261,25 @@ const char* decodeToRoman(const UWORD* string);
  * Encode a string to Alphabet characters for a language.
  *
  * Arguments:
- *      string      - String to encode.
- *      alphabet    - Alphabet to use. Currently supported are:
+ *      string     - String to encode.
+ *      alphabet   - Alphabet to use. Currently supported are:
  *                      0 = roman, 2 = cyrillic, 4 = hindi, 12 = gurmukhi.
+ *      unibuf     - Buffer to be filled with the result
+ *      maxlen     - Size of unibuf
+ *
  *
  * Returns:
  *      Encoded string. The string is allocated by the library and must NOT be
  *      de-allocated by the caller. It will be overwritten by a subsequent call to this method!
  */
-const UWORD* encodeToAlphabet(const char* mapcode, int alphabet);
+UWORD* convertToAlphabet(UWORD* unibuf, int maxlength, const char *string,int alphabet);
+
+/**
+ * old variant, not thread-safe: uses a pre-allocated static buffer, overwritten by the next call
+ *      Returns converted string. allocated by the library. String must NOT be
+ *      de-allocated by the caller. It will be overwritten by a subsequent call to this method!
+ */
+const UWORD* encodeToAlphabet(const char* string, int alphabet);
 
 
 /**
@@ -227,14 +291,14 @@ const UWORD* encodeToAlphabet(const char* mapcode, int alphabet);
 /**
  * list of #defines to support legacy systems
  */
-#define coord2mc(results,lat,lon,territoryCode)  encodeLatLonToMapcodes(results,lat,lon,territoryCode,0)
-#define coord2mc1(results,lat,lon,territoryCode) encodeLatLonToSingleMapcode(results,lat,lon,territoryCode,0)
+#define coord2mc(results, lat, lon, territoryCode)  encodeLatLonToMapcodes(results, lat, lon,territoryCode, 0)
+#define coord2mc1(results, lat, lon, territoryCode) encodeLatLonToSingleMapcode(results, lat, lon, territoryCode, 0)
 #define mc2coord decodeMapcodeToLatLon
 #define lookslikemapcode compareWithMapcodeFormat
 #define text2tc convertTerritoryIsoNameToCode
 #define tc2text convertTerritoryCodeToIsoName
 #define tccontext getCountryOrParentCountry
-#define tcparent getParentCountryOfState
+#define tcparent getParentCountryOf
 #define decode_to_roman decodeToRoman
 #define encode_to_alphabet encodeToAlphabet
 #define MAX_MAPCODE_TERRITORY_CODE MAX_CCODE
diff --git a/utility/mapcode.cpp b/utility/mapcode.cpp
index 573cce7..1c65193 100644
--- a/utility/mapcode.cpp
+++ b/utility/mapcode.cpp
@@ -196,7 +196,7 @@ static void convertLatLonToXYZ(double latDeg, double lonDeg, double* x, double*
  */
 static void selfCheckLatLonToMapcode(const double lat, double lon, const char* territory, const char* mapcode, int extraDigits) {
     int context = convertTerritoryIsoNameToCode(territory, 0);
-    char* results[MAX_NR_OF_MAPCODE_RESULTS];
+    char* results[2 * MAX_NR_OF_MAPCODE_RESULTS];
     const double limitLat = (lat < -90.0) ? -90.0 : ((lat > 90.0) ? 90.0 : lat);
     const double limitLon = (lon < -180.0) ? -180.0 : ((lon > 180.0) ? 180.0 : lon);
     const int nrResults = encodeLatLonToMapcodes(results, limitLat, limitLon, context, extraDigits);
@@ -276,7 +276,7 @@ static void selfCheckMapcodeToLatLon(const char* territory, const char* mapcode,
 
 static void generateAndOutputMapcodes(double lat, double lon, int iShowError, int extraDigits, int useXYZ) {
 
-    char* results[MAX_NR_OF_MAPCODE_RESULTS];
+    char* results[2 * MAX_NR_OF_MAPCODE_RESULTS];
     int context = 0;
 
     while (lon > 180) {
@@ -507,7 +507,7 @@ int main(const int argc, const char** argv)
         }
 
         // Encode the lat/lon to a set of Mapcodes.
-        char* results[MAX_NR_OF_MAPCODE_RESULTS];
+        char* results[2 * MAX_NR_OF_MAPCODE_RESULTS];
         const int nrResults = encodeLatLonToMapcodes(results, lat, lon, context, extraDigits);
         if (nrResults <= 0) {
             fprintf(stderr, "error: cannot encode lat=%.12g, lon=%.12g (default territory=%s)\n",
@@ -642,7 +642,7 @@ int main(const int argc, const char** argv)
 
         int gridX = 0;
         int gridY = 0;
-        int line = my_round(sqrt((double)totalNrOfPoints));
+        int line = my_round(sqrt((double) totalNrOfPoints));
         for (int i = 0; i < totalNrOfPoints; ++i) {
             double lat;
             double lon;

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



More information about the Pkg-grass-devel mailing list