Skip to content

Commit 99a9165

Browse files
Rewrote fraction floating points to integer arithmetic
1 parent 90966d0 commit 99a9165

File tree

2 files changed

+32
-41
lines changed

2 files changed

+32
-41
lines changed

mapcodelib/mapcoder.c

Lines changed: 28 additions & 39 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;
@@ -311,10 +311,10 @@ static void encodeExtension(char *result, int extrax4, int extray, int dividerx4
311311
{
312312
if (extraDigits > 0) { // anything to do?
313313
char *s = result + strlen(result);
314-
int factorx = MAX_PRECISION_FACTOR * dividerx4; // 30^4
315-
int factory = MAX_PRECISION_FACTOR * dividery; // 30^4
316-
int valx = (int) floor(MAX_PRECISION_FACTOR * (extrax4 + 4 * enc->fraclon));
317-
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!
318318

319319
// protect against floating point errors
320320
if (valx<0) { valx=0; } else if (valx>=factorx) { valx=factorx-1; }
@@ -332,11 +332,11 @@ static void encodeExtension(char *result, int extrax4, int extray, int dividerx4
332332
int gx, gy, column1, column2, row1, row2;
333333

334334
factorx /= 30;
335-
gx = (valx / factorx);
335+
gx = (int)(valx / factorx);
336336
valx -= factorx * gx;
337337

338338
factory /= 30;
339-
gy = (valy / factory);
339+
gy = (int)(valy / factory);
340340
valy -= factory * gy;
341341

342342
column1 = (gx / 6);
@@ -390,8 +390,8 @@ static int decodeExtension(decodeRec *dec, int dividerx4, int dividery0, int lon
390390
lat32 = lat32 * 30 + row1 * 5 + row2;
391391
}
392392

393-
dec->result.lon = dec->coord32.lon + (lon32 * dividerx / processor) + lon_offset4 / 4.0;
394-
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);
395395

396396
#ifdef FORCE_RECODE
397397
dec->range_min.lon = dec->result.lon;
@@ -1109,7 +1109,7 @@ static void encodeNameless(char *result, const encodeRec *enc, int input_ctry, i
11091109
int v = storage_offset;
11101110

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

@@ -1526,7 +1526,7 @@ static int decoderEngine(decodeRec *dec) {
15261526
}
15271527
}
15281528
#ifdef FORCE_RECODE
1529-
if (err==0 && !fitssomewhere) {
1529+
if (!fitssomewhere) {
15301530
for (j = from; j < i; j++) { // try all smaller rectangles j
15311531
if (!isRestricted(j)) {
15321532
const mminforec *b = boundaries(j);
@@ -1900,37 +1900,26 @@ static int encodeLatLonToMapcodes_internal(char **v, Mapcodes *mapcodes, double
19001900
enc.mapcodes = mapcodes;
19011901
enc.mapcodes->count = 0;
19021902

1903-
if (lat < -90) { lat = -90; } else if (lat > 90) { lat = 90; }
1904-
lat += 90; // lat now [0..180]
1905-
lon -= (360.0 * floor(lon / 360)); // lon now in [0..360>
1906-
1907-
lat *= 1000000;
1908-
lon *= 1000000;
1909-
enc.coord32.lat = (int) lat;
1910-
enc.coord32.lon = (int) lon;
1911-
enc.fraclat = lat - enc.coord32.lat;
1912-
enc.fraclon = lon - enc.coord32.lon;
19131903
{
19141904
double f;
1915-
// for 8-digit precision, cells are divided into 810,000 by 810,000 minicells.
1916-
f = enc.fraclat * MAX_PRECISION_FACTOR;
1917-
if (f < 1) { enc.fraclat = 0; } else {
1918-
if (f >= (MAX_PRECISION_FACTOR - 0.5)) {
1919-
enc.fraclat = 0;
1920-
enc.coord32.lat++;
1921-
}
1922-
}
1923-
f = enc.fraclon * MAX_PRECISION_FACTOR;
1924-
if (f < 1) { enc.fraclon = 0; } else {
1925-
if (f >= (MAX_PRECISION_FACTOR - 0.5)) {
1926-
enc.fraclon = 0;
1927-
enc.coord32.lon++;
1928-
}
1929-
}
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;
19301922
}
1931-
enc.coord32.lat -= 90000000;
1932-
if (enc.coord32.lon >= 180000000)
1933-
enc.coord32.lon -= 360000000;
19341923

19351924
if (tc <= 0) // ALL results?
19361925
{

unitttest/unittest.c

Lines changed: 4 additions & 2 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");

0 commit comments

Comments
 (0)