|
1 | 1 | #include "point.h"
|
2 | 2 | #include "pgs_util.h"
|
| 3 | +#include <utils/float.h> |
| 4 | +#include <common/hashfn.h> |
3 | 5 | #include <catalog/namespace.h>
|
4 | 6 |
|
5 | 7 | /* This file contains definitions for spherical point functions. */
|
@@ -314,9 +316,31 @@ spherepoint_equal(PG_FUNCTION_ARGS)
|
314 | 316 | Datum
|
315 | 317 | spherepoint_hash32(PG_FUNCTION_ARGS)
|
316 | 318 | {
|
317 |
| - SPoint *p1 = (SPoint *) PG_GETARG_POINTER(0); |
318 |
| - Datum h1 = DirectFunctionCall1(hashfloat8, p1->lat); |
319 |
| - Datum h2 = DirectFunctionCall1(hashfloat8, p1->lng); |
| 319 | + SPoint *p1 = (SPoint *) PG_GETARG_POINTER(0); |
| 320 | + const uint32 h1 = pgs_hashfloat8(p1->lat); |
| 321 | + const uint32 h2 = pgs_hashfloat8(p1->lng); |
| 322 | + |
| 323 | + PG_RETURN_INT32(h1 ^ h2); |
| 324 | +} |
320 | 325 |
|
321 |
| - PG_RETURN_INT32(DatumGetInt32(h1) ^ DatumGetInt32(h2)); |
| 326 | +uint32 |
| 327 | +pgs_hashfloat8(float8 key) |
| 328 | +{ |
| 329 | + /* |
| 330 | + * On IEEE-float machines, minus zero and zero have different bit patterns |
| 331 | + * but should compare as equal. We must ensure that they have the same |
| 332 | + * hash value, which is most reliably done this way: |
| 333 | + */ |
| 334 | + if (key == (float8) 0) |
| 335 | + PG_RETURN_UINT32(0); |
| 336 | + |
| 337 | + /* |
| 338 | + * Similarly, NaNs can have different bit patterns but they should all |
| 339 | + * compare as equal. For backwards-compatibility reasons we force them to |
| 340 | + * have the hash value of a standard NaN. |
| 341 | + */ |
| 342 | + if (isnan(key)) |
| 343 | + key = get_float8_nan(); |
| 344 | + |
| 345 | + return hash_bytes((unsigned char *) &key, sizeof(key)); |
322 | 346 | }
|
0 commit comments