[mapcode] 02/04: Rewrote fraction floating points to integer arithmetic
Stefan Fritsch
sf at moszumanska.debian.org
Wed Nov 2 23:28:11 UTC 2016
This is an automated email from the git hooks/post-receive script.
sf pushed a commit to tag v2.1.2
in repository mapcode.
commit 99a9165be5e0ffa71e6f734e6f4a16ce4b9acc8a
Author: Mapcode C Developer <pieter.geelen at mapcode.com>
Date: Mon Aug 24 22:30:39 2015 +0200
Rewrote fraction floating points to integer arithmetic
---
mapcodelib/mapcoder.c | 67 +++++++++++++++++++++------------------------------
unitttest/unittest.c | 6 +++--
2 files changed, 32 insertions(+), 41 deletions(-)
diff --git a/mapcodelib/mapcoder.c b/mapcodelib/mapcoder.c
index eb49459..22c0d59 100644
--- a/mapcodelib/mapcoder.c
+++ b/mapcodelib/mapcoder.c
@@ -50,7 +50,7 @@ typedef struct { // point
typedef struct {
// input
point32 coord32;
- double fraclat, fraclon;
+ double fraclat, fraclon; // fractions, pre-multiplied into integers
// output
Mapcodes *mapcodes;
} encodeRec;
@@ -311,10 +311,10 @@ static void encodeExtension(char *result, int extrax4, int extray, int dividerx4
{
if (extraDigits > 0) { // anything to do?
char *s = result + strlen(result);
- int factorx = MAX_PRECISION_FACTOR * dividerx4; // 30^4
- int factory = MAX_PRECISION_FACTOR * dividery; // 30^4
- int valx = (int) floor(MAX_PRECISION_FACTOR * (extrax4 + 4 * enc->fraclon));
- int valy = (int) floor(MAX_PRECISION_FACTOR * (extray + enc->fraclat * ydirection));
+ double factorx = MAX_PRECISION_FACTOR * dividerx4; // perfect integer!
+ double factory = MAX_PRECISION_FACTOR * dividery; // perfect integer!
+ double valx = (MAX_PRECISION_FACTOR * extrax4) + enc->fraclon; // perfect integer!
+ double valy = (MAX_PRECISION_FACTOR * extray ) + (ydirection * enc->fraclat); // perfect integer!
// protect against floating point errors
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
int gx, gy, column1, column2, row1, row2;
factorx /= 30;
- gx = (valx / factorx);
+ gx = (int)(valx / factorx);
valx -= factorx * gx;
factory /= 30;
- gy = (valy / factory);
+ gy = (int)(valy / factory);
valy -= factory * gy;
column1 = (gx / 6);
@@ -390,8 +390,8 @@ static int decodeExtension(decodeRec *dec, int dividerx4, int dividery0, int lon
lat32 = lat32 * 30 + row1 * 5 + row2;
}
- dec->result.lon = dec->coord32.lon + (lon32 * dividerx / processor) + lon_offset4 / 4.0;
- dec->result.lat = dec->coord32.lat + (lat32 * dividery / processor);
+ dec->result.lon = dec->coord32.lon + ((lon32 * dividerx) / processor) + lon_offset4 / 4.0;
+ dec->result.lat = dec->coord32.lat + ((lat32 * dividery) / processor);
#ifdef FORCE_RECODE
dec->range_min.lon = dec->result.lon;
@@ -1109,7 +1109,7 @@ static void encodeNameless(char *result, const encodeRec *enc, int input_ctry, i
int v = storage_offset;
int dividerx4 = xDivider4(b->miny, b->maxy); // *** note: dividerx4 is 4 times too large!
- int xFracture = (int) (4 * enc->fraclon);
+ int xFracture = (int)(enc->fraclon / MAX_PRECISION_FACTOR);
int dx = (4 * (enc->coord32.lon - b->minx) + xFracture) / dividerx4; // div with quarters
int extrax4 = (enc->coord32.lon - b->minx) * 4 - dx * dividerx4; // mod with quarters
@@ -1526,7 +1526,7 @@ static int decoderEngine(decodeRec *dec) {
}
}
#ifdef FORCE_RECODE
- if (err==0 && !fitssomewhere) {
+ if (!fitssomewhere) {
for (j = from; j < i; j++) { // try all smaller rectangles j
if (!isRestricted(j)) {
const mminforec *b = boundaries(j);
@@ -1900,37 +1900,26 @@ static int encodeLatLonToMapcodes_internal(char **v, Mapcodes *mapcodes, double
enc.mapcodes = mapcodes;
enc.mapcodes->count = 0;
- if (lat < -90) { lat = -90; } else if (lat > 90) { lat = 90; }
- lat += 90; // lat now [0..180]
- lon -= (360.0 * floor(lon / 360)); // lon now in [0..360>
-
- lat *= 1000000;
- lon *= 1000000;
- enc.coord32.lat = (int) lat;
- enc.coord32.lon = (int) lon;
- enc.fraclat = lat - enc.coord32.lat;
- enc.fraclon = lon - enc.coord32.lon;
{
double f;
- // for 8-digit precision, cells are divided into 810,000 by 810,000 minicells.
- f = enc.fraclat * MAX_PRECISION_FACTOR;
- if (f < 1) { enc.fraclat = 0; } else {
- if (f >= (MAX_PRECISION_FACTOR - 0.5)) {
- enc.fraclat = 0;
- enc.coord32.lat++;
- }
- }
- f = enc.fraclon * MAX_PRECISION_FACTOR;
- if (f < 1) { enc.fraclon = 0; } else {
- if (f >= (MAX_PRECISION_FACTOR - 0.5)) {
- enc.fraclon = 0;
- enc.coord32.lon++;
- }
- }
+ if (lat < -90) { lat = -90; } else if (lat > 90) { lat = 90; }
+ lat += 90; // lat now [0..180]
+ lat *= (double) 810000000000;
+ enc.fraclat = floor(lat+0.1);
+ f = enc.fraclat / (double) 810000;
+ enc.coord32.lat = (int)f;
+ enc.fraclat -= (double)enc.coord32.lat * (double) 810000;
+ enc.coord32.lat -= 90000000;
+
+ lon -= (360.0 * floor(lon / 360)); // lon now in [0..360>
+ lon *= (double)3240000000000;
+ enc.fraclon = floor(lon+0.1);
+ f = enc.fraclon / (double)3240000;
+ enc.coord32.lon = (int)f;
+ enc.fraclon -= (double)enc.coord32.lon * (double)3240000;
+ if (enc.coord32.lon >= 180000000)
+ enc.coord32.lon -= 360000000;
}
- enc.coord32.lat -= 90000000;
- if (enc.coord32.lon >= 180000000)
- enc.coord32.lon -= 360000000;
if (tc <= 0) // ALL results?
{
diff --git a/unitttest/unittest.c b/unitttest/unittest.c
index 2d85af9..fdbd728 100644
--- a/unitttest/unittest.c
+++ b/unitttest/unittest.c
@@ -249,7 +249,7 @@ static void testEncodeAndDecode(const char *str, double y, double x, int localso
}
// test all global solutions at all precisions...
- for (precision = 0; precision < 8; precision++) {
+ for (precision = 0; precision <= 8; precision++) {
nrresults = encodeLatLonToMapcodes(&mapcodes, y, x, 0, precision);
for (i = 0; i < nrresults; i++) {
const char *str = mapcodes.mapcode[i];
@@ -304,7 +304,9 @@ static void testEncodeAndDecode(const char *str, double y, double x, int localso
// report if decode doesnt encode back to the same mapcode
nrTests++;
if (!found) {
- printf("*** WARNING *** %s does not re-encode(%f,%f) (%f,%f)\n", str, y, x, lat, lon);
+ printf("*** WARNING *** %s does not re-encode (%0.15f,%0.15f) from (%0.15f,%0.15f)\n", str, lat, lon, y, x);
+ printGeneratedMapcodes(&mapcodes2);
+ printGeneratedMapcodes(&mapcodes);
nrWarnings++;
if (nrWarnings > 16) {
printf("*** ERROR *** too many warnings...\n");
--
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