[postgis-tickets] r15875 - Use type-pun to avoid memcpy in building morton key (Closes #3871)
Paul Ramsey
pramsey at cleverelephant.ca
Mon Oct 2 15:01:27 PDT 2017
Author: pramsey
Date: 2017-10-02 15:01:27 -0700 (Mon, 02 Oct 2017)
New Revision: 15875
Modified:
trunk/liblwgeom/g_serialized.c
Log:
Use type-pun to avoid memcpy in building morton key (Closes #3871)
Fix from Komzpa at https://github.com/postgis/postgis/pull/144
Modified: trunk/liblwgeom/g_serialized.c
===================================================================
--- trunk/liblwgeom/g_serialized.c 2017-10-02 22:00:36 UTC (rev 15874)
+++ trunk/liblwgeom/g_serialized.c 2017-10-02 22:01:27 UTC (rev 15875)
@@ -243,8 +243,14 @@
uint64_t gbox_get_sortable_hash(const GBOX *g)
{
- uint32_t ux, uy;
- float fx, fy;
+ union x {
+ uint32_t u;
+ float f
+ };
+ union y {
+ uint32_t u;
+ float f
+ };
/*
* Since in theory the bitwise representation of an IEEE
@@ -261,19 +267,20 @@
p.z = (g->zmax + g->zmin) / 2.0;
normalize(&p);
cart2geog(&p, &gpt);
- fx = gpt.lon;
- fy = gpt.lat;
- memcpy(&ux, &fx, sizeof(uint32_t));
- memcpy(&uy, &fy, sizeof(uint32_t));
+ x.f = gpt.lon;
+ y.f = gpt.lat;
}
else
{
- fx = (g->xmax + g->xmin) / 2.0;
- fy = (g->ymax + g->ymin) / 2.0;
- memcpy(&ux, &fx, sizeof(uint32_t));
- memcpy(&uy, &fy, sizeof(uint32_t));
+ /*
+ * Here we'd like to get two ordinates from 4 in the box.
+ * Since it's just a sortable bit representation we can omit division from (A+B)/2.
+ * All it should do is subtract 1 from exponent anyways.
+ */
+ x.f = g->xmax + g->xmin;
+ y.f = g->ymax + g->ymin;
}
- return uint32_interleave_2(ux, uy);
+ return uint32_interleave_2(x.u, y.u);
}
int gserialized_cmp(const GSERIALIZED *g1, const GSERIALIZED *g2)
@@ -300,13 +307,13 @@
/* Empty == Empty */
if (g1_is_empty && g2_is_empty)
- {
- /* POINT EMPTY == POINT EMPTY */
- /* POINT EMPTY < LINESTRING EMPTY */
- uint32_t t1 = gserialized_get_type(g1);
- uint32_t t2 = gserialized_get_type(g2);
+ {
+ /* POINT EMPTY == POINT EMPTY */
+ /* POINT EMPTY < LINESTRING EMPTY */
+ uint32_t t1 = gserialized_get_type(g1);
+ uint32_t t2 = gserialized_get_type(g2);
return t1 == t2 ? 0 : (t1 < t2 ? -1 : 1);
- }
+ }
/* Empty < Non-empty */
if (g1_is_empty)
@@ -322,8 +329,8 @@
return 0;
/* Using the centroids, calculate somewhat sortable */
- /* hash key. The key doesn't provide good locality over */
- /* the +/- boundary, but otherwise is pretty OK */
+ /* hash key. The key doesn't provide good locality over */
+ /* the +/- boundary, but otherwise is pretty OK */
hash1 = gbox_get_sortable_hash(&box1);
hash2 = gbox_get_sortable_hash(&box2);
More information about the postgis-tickets
mailing list