Skip to content

Commit 62813b4

Browse files
Merge pull request #19 from mapcode-foundation/dev
2.1.2. Rewrote fraction floating points to integer arithmetic
2 parents 4de5545 + 1132cbc commit 62813b4

File tree

3 files changed

+38
-45
lines changed

3 files changed

+38
-45
lines changed

mapcodelib/mapcoder.c

Lines changed: 32 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ typedef struct { // point
5050
typedef struct {
5151
// input
5252
point32 coord32;
53-
double fraclat, fraclon;
53+
double fraclat, fraclon; // fractions, pre-multiplied into integers
5454
// output
5555
Mapcodes *mapcodes;
5656
} encodeRec;
@@ -309,17 +309,18 @@ static void encodeExtension(char *result, int extrax4, int extray, int dividerx4
309309
int ydirection,
310310
const encodeRec *enc) // append extra characters to result for more precision
311311
{
312+
if (extraDigits > 0) { // anything to do?
312313
char *s = result + strlen(result);
313-
int factorx = MAX_PRECISION_FACTOR * dividerx4; // 30^4
314-
int factory = MAX_PRECISION_FACTOR * dividery; // 30^4
315-
int valx = (int) floor(MAX_PRECISION_FACTOR * (extrax4 + 4 * enc->fraclon));
316-
int valy = (int) floor(MAX_PRECISION_FACTOR * (extray + enc->fraclat * ydirection));
314+
double factorx = MAX_PRECISION_FACTOR * dividerx4; // perfect integer!
315+
double factory = MAX_PRECISION_FACTOR * dividery; // perfect integer!
316+
double valx = (MAX_PRECISION_FACTOR * extrax4) + enc->fraclon; // perfect integer!
317+
double valy = (MAX_PRECISION_FACTOR * extray ) + (ydirection * enc->fraclat); // perfect integer!
317318

318319
// protect against floating point errors
319320
if (valx<0) { valx=0; } else if (valx>=factorx) { valx=factorx-1; }
320321
if (valy<0) { valy=0; } else if (valy>=factory) { valy=factory-1; }
321322

322-
if (extraDigits < 0) { extraDigits = 0; } else if (extraDigits > MAX_PRECISION_DIGITS) {
323+
if (extraDigits > MAX_PRECISION_DIGITS) {
323324
extraDigits = MAX_PRECISION_DIGITS;
324325
}
325326

@@ -331,11 +332,11 @@ static void encodeExtension(char *result, int extrax4, int extray, int dividerx4
331332
int gx, gy, column1, column2, row1, row2;
332333

333334
factorx /= 30;
334-
gx = (valx / factorx);
335+
gx = (int)(valx / factorx);
335336
valx -= factorx * gx;
336337

337338
factory /= 30;
338-
gy = (valy / factory);
339+
gy = (int)(valy / factory);
339340
valy -= factory * gy;
340341

341342
column1 = (gx / 6);
@@ -347,8 +348,9 @@ static void encodeExtension(char *result, int extrax4, int extray, int dividerx4
347348
if (extraDigits-- > 0) {
348349
*s++ = encode_chars[row2 * 6 + column2];
349350
}
350-
*s = 0;
351351
}
352+
*s = 0; // terminate the result
353+
}
352354
}
353355

354356
#define decodeChar(c) decode_chars[(unsigned char)c] // force c to be in range of the index, between 0 and 255
@@ -388,8 +390,8 @@ static int decodeExtension(decodeRec *dec, int dividerx4, int dividery0, int lon
388390
lat32 = lat32 * 30 + row1 * 5 + row2;
389391
}
390392

391-
dec->result.lon = dec->coord32.lon + (lon32 * dividerx / processor) + lon_offset4 / 4.0;
392-
dec->result.lat = dec->coord32.lat + (lat32 * dividery / processor);
393+
dec->result.lon = dec->coord32.lon + ((lon32 * dividerx) / processor) + lon_offset4 / 4.0;
394+
dec->result.lat = dec->coord32.lat + ((lat32 * dividery) / processor);
393395

394396
#ifdef FORCE_RECODE
395397
dec->range_min.lon = dec->result.lon;
@@ -1107,7 +1109,7 @@ static void encodeNameless(char *result, const encodeRec *enc, int input_ctry, i
11071109
int v = storage_offset;
11081110

11091111
int dividerx4 = xDivider4(b->miny, b->maxy); // *** note: dividerx4 is 4 times too large!
1110-
int xFracture = (int) (4 * enc->fraclon);
1112+
int xFracture = (int)(enc->fraclon / MAX_PRECISION_FACTOR);
11111113
int dx = (4 * (enc->coord32.lon - b->minx) + xFracture) / dividerx4; // div with quarters
11121114
int extrax4 = (enc->coord32.lon - b->minx) * 4 - dx * dividerx4; // mod with quarters
11131115

@@ -1524,7 +1526,7 @@ static int decoderEngine(decodeRec *dec) {
15241526
}
15251527
}
15261528
#ifdef FORCE_RECODE
1527-
if (err==0 && !fitssomewhere) {
1529+
if (!fitssomewhere) {
15281530
for (j = from; j < i; j++) { // try all smaller rectangles j
15291531
if (!isRestricted(j)) {
15301532
const mminforec *b = boundaries(j);
@@ -1898,37 +1900,26 @@ static int encodeLatLonToMapcodes_internal(char **v, Mapcodes *mapcodes, double
18981900
enc.mapcodes = mapcodes;
18991901
enc.mapcodes->count = 0;
19001902

1901-
if (lat < -90) { lat = -90; } else if (lat > 90) { lat = 90; }
1902-
lat += 90; // lat now [0..180]
1903-
lon -= (360.0 * floor(lon / 360)); // lon now in [0..360>
1904-
1905-
lat *= 1000000;
1906-
lon *= 1000000;
1907-
enc.coord32.lat = (int) lat;
1908-
enc.coord32.lon = (int) lon;
1909-
enc.fraclat = lat - enc.coord32.lat;
1910-
enc.fraclon = lon - enc.coord32.lon;
19111903
{
19121904
double f;
1913-
// for 8-digit precision, cells are divided into 810,000 by 810,000 minicells.
1914-
f = enc.fraclat * MAX_PRECISION_FACTOR;
1915-
if (f < 1) { enc.fraclat = 0; } else {
1916-
if (f >= (MAX_PRECISION_FACTOR - 0.5)) {
1917-
enc.fraclat = 0;
1918-
enc.coord32.lat++;
1919-
}
1920-
}
1921-
f = enc.fraclon * MAX_PRECISION_FACTOR;
1922-
if (f < 1) { enc.fraclon = 0; } else {
1923-
if (f >= (MAX_PRECISION_FACTOR - 0.5)) {
1924-
enc.fraclon = 0;
1925-
enc.coord32.lon++;
1926-
}
1927-
}
1905+
if (lat < -90) { lat = -90; } else if (lat > 90) { lat = 90; }
1906+
lat += 90; // lat now [0..180]
1907+
lat *= (double) 810000000000;
1908+
enc.fraclat = floor(lat+0.1);
1909+
f = enc.fraclat / (double) 810000;
1910+
enc.coord32.lat = (int)f;
1911+
enc.fraclat -= (double)enc.coord32.lat * (double) 810000;
1912+
enc.coord32.lat -= 90000000;
1913+
1914+
lon -= (360.0 * floor(lon / 360)); // lon now in [0..360>
1915+
lon *= (double)3240000000000;
1916+
enc.fraclon = floor(lon+0.1);
1917+
f = enc.fraclon / (double)3240000;
1918+
enc.coord32.lon = (int)f;
1919+
enc.fraclon -= (double)enc.coord32.lon * (double)3240000;
1920+
if (enc.coord32.lon >= 180000000)
1921+
enc.coord32.lon -= 360000000;
19281922
}
1929-
enc.coord32.lat -= 90000000;
1930-
if (enc.coord32.lon >= 180000000)
1931-
enc.coord32.lon -= 360000000;
19321923

19331924
if (tc <= 0) // ALL results?
19341925
{

mapcodelib/mapcoder.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
extern "C" {
1919
#endif
2020

21-
#define mapcode_cversion "2.1.0"
21+
#define mapcode_cversion "2.1.2"
2222

2323
#define UWORD unsigned short int // 2-byte unsigned integer.
2424

unitttest/unittest.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ static void testEncodeAndDecode(const char *str, double y, double x, int localso
249249
}
250250

251251
// test all global solutions at all precisions...
252-
for (precision = 0; precision < 8; precision++) {
252+
for (precision = 0; precision <= 8; precision++) {
253253
nrresults = encodeLatLonToMapcodes(&mapcodes, y, x, 0, precision);
254254
for (i = 0; i < nrresults; i++) {
255255
const char *str = mapcodes.mapcode[i];
@@ -304,7 +304,9 @@ static void testEncodeAndDecode(const char *str, double y, double x, int localso
304304
// report if decode doesnt encode back to the same mapcode
305305
nrTests++;
306306
if (!found) {
307-
printf("*** WARNING *** %s does not re-encode(%f,%f) (%f,%f)\n", str, y, x, lat, lon);
307+
printf("*** WARNING *** %s does not re-encode (%0.15f,%0.15f) from (%0.15f,%0.15f)\n", str, lat, lon, y, x);
308+
printGeneratedMapcodes(&mapcodes2);
309+
printGeneratedMapcodes(&mapcodes);
308310
nrWarnings++;
309311
if (nrWarnings > 16) {
310312
printf("*** ERROR *** too many warnings...\n");
@@ -503,7 +505,7 @@ void main() {
503505
#ifdef XSIDE3
504506
const char *mapcode_dataversion = "undefined";
505507
#endif
506-
printf("Mapcode C Library Unit test 2.1.1\n");
508+
printf("Mapcode C Library Unit test 2.1.2\n");
507509
printf("Library version %s (Data version %s)\n", mapcode_cversion, mapcode_dataversion);
508510

509511
printf("-----------------------------------------------------------\nAlphabet tests\n");

0 commit comments

Comments
 (0)