Skip to content

Instantly share code, notes, and snippets.

@ear7h
Last active June 23, 2020 21:38
Show Gist options
  • Save ear7h/4448880ed4ff20eac3110244dd64b854 to your computer and use it in GitHub Desktop.
Save ear7h/4448880ed4ff20eac3110244dd64b854 to your computer and use it in GitHub Desktop.
geohash into 32 bits
package main
import (
"fmt"
)
func main() {
geohash := "u4pruydqqvj"
for i := range geohash {
fmt.Println(geohash[:i+1], "\t", geohash2bits(geohash[:i+1]))
}
}
func geohash2bits(s string) int64 {
ret := int64(0)
byt := []byte(s)
// a single base32 character is 5 bits
// and our destination is the 63 least significant bits of an int64
// so, we can fit 12 3/5 characters in the int
for i := 0; i < len(byt) && i < 12; i++ {
ret = (base32[byt[i]] << (i*5)) | ret
}
return ret
}
var base32 = [256]int64{
'0': 0,
'1': 1,
'2': 2,
'3': 3,
'4': 4,
'5': 5,
'6': 6,
'7': 7,
'8': 8,
'9': 9,
'b': 10,
'c': 11,
'd': 12,
'e': 13,
'f': 14,
'g': 15,
'h': 16,
'j': 17,
'k': 18,
'm': 19,
'n': 20,
'p': 21,
'q': 22,
'r': 23,
's': 24,
't': 25,
'u': 26,
'v': 27,
'w': 28,
'x': 29,
'y': 30,
'z': 31,
}
CREATE OR REPLACE FUNCTION base32_decode(IN hash text) RETURNS bigint AS $$
DECLARE
tbl bigint[] := ARRAY[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 10, 11, 12, 13, 14, 15, 16, 0, 17, 18, 0, 19, 20, 0,
21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
ret bigint := 0;
it integer := 0;
BEGIN
-- a single base32 character is 5 bits
-- and our destination is the 63 least significant bits of and int64
--
-- so we can fit 12 3/5 characters in our destination. To prevent overflow
-- into the sign bit, we use 12 characters
WHILE it < LENGTH(hash) AND it < 12 LOOP
ret := (tbl[1+ASCII(SUBSTRING(hash, it+1, 1))] << (it * 5)) | ret;
it := it+1;
END LOOP;
RETURN ret;
END;
$$ LANGUAGE plpgsql IMMUTABLE;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment