Skip to content

Commit 3543e6f

Browse files
authored
go: use floor for conversion, use integer tests (#729)
1 parent d3972a3 commit 3543e6f

File tree

3 files changed

+54
-15
lines changed

3 files changed

+54
-15
lines changed

go/encode.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,13 @@ func Encode(lat, lng float64, codeLen int) string {
4242
// This allows us to use only integer operations, so avoiding any accumulation of floating point representation errors.
4343
latVal := latitudeAsInteger(lat)
4444
lngVal := longitudeAsInteger(lng)
45-
// Clip the code length to legal values.
46-
codeLen = clipCodeLen(codeLen)
4745
// Call the integer based encoding method.
4846
return integerEncode(latVal, lngVal, codeLen)
4947
}
5048

5149
func integerEncode(latVal, lngVal int64, codeLen int) string {
50+
// Clip the code length to legal values.
51+
codeLen = clipCodeLen(codeLen)
5252
// Use a char array so we can build it up from the end digits, without having to keep reallocating strings.
5353
// Prime it with padding and separator.
5454
var code []byte = []byte("00000000+0012345")

go/olc.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ func normalizeLng(value float64) float64 {
232232
// latitudeAsInteger converts a latitude in degrees into the integer representation.
233233
// It will be clipped into the degree range -90<=x<90 (actually 0-180*2.5e7-1).
234234
func latitudeAsInteger(latDegrees float64) int64 {
235-
latVal := int64(math.Round(latDegrees * finalLatPrecision))
235+
latVal := int64(math.Floor(latDegrees * finalLatPrecision))
236236
latVal += latMax * finalLatPrecision
237237
if latVal < 0 {
238238
latVal = 0
@@ -245,7 +245,7 @@ func latitudeAsInteger(latDegrees float64) int64 {
245245
// longitudeAsInteger converts a longitude in degrees into the integer representation.
246246
// It will be normalised into the degree range -180<=x<180 (actually 0-360*8.192e6).
247247
func longitudeAsInteger(lngDegrees float64) int64 {
248-
lngVal := int64(math.Round(lngDegrees * finalLngPrecision))
248+
lngVal := int64(math.Floor(lngDegrees * finalLngPrecision))
249249
lngVal += lngMax * finalLngPrecision
250250
if lngVal <= 0 {
251251
lngVal = lngVal%(2*lngMax*finalLngPrecision) + 2*lngMax*finalLngPrecision

go/olc_test.go

Lines changed: 50 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package olc
1717
import (
1818
"bufio"
1919
"encoding/csv"
20+
"fmt"
2021
"math"
2122
"math/rand"
2223
"os"
@@ -41,9 +42,10 @@ type (
4142
}
4243

4344
encodingTest struct {
44-
lat, lng float64
45-
length int
46-
code string
45+
latDeg, lngDeg float64
46+
latInt, lngInt int64
47+
length int
48+
code string
4749
}
4850

4951
decodingTest struct {
@@ -80,10 +82,12 @@ func init() {
8082
defer wg.Done()
8183
for _, cols := range mustReadLines("encoding.csv") {
8284
encoding = append(encoding, encodingTest{
83-
lat: mustFloat(cols[0]),
84-
lng: mustFloat(cols[1]),
85-
length: mustInt(cols[2]),
86-
code: cols[3],
85+
latDeg: mustFloat(cols[0]),
86+
lngDeg: mustFloat(cols[1]),
87+
latInt: mustInt64(cols[2]),
88+
lngInt: mustInt64(cols[3]),
89+
length: mustInt(cols[4]),
90+
code: cols[5],
8791
})
8892
}
8993
}()
@@ -127,12 +131,39 @@ func TestCheck(t *testing.T) {
127131
}
128132
}
129133

130-
func TestEncode(t *testing.T) {
134+
func TestEncodeDegrees(t *testing.T) {
135+
const allowedErrRate float64 = 0.05
136+
var badCodes int
131137
for i, elt := range encoding {
132-
got := Encode(elt.lat, elt.lng, elt.length)
138+
got := Encode(elt.latDeg, elt.lngDeg, elt.length)
133139
if got != elt.code {
134-
t.Errorf("%d. got %q for (%v,%v,%d), wanted %q.", i, got, elt.lat, elt.lng, elt.length, elt.code)
135-
t.FailNow()
140+
fmt.Printf("ENCODING DIFFERENCE %d. got %q for Encode(%v,%v,%d), wanted %q\n", i, got, elt.latDeg, elt.lngDeg, elt.length, elt.code)
141+
badCodes++
142+
}
143+
}
144+
if errRate := float64(badCodes) / float64(len(encoding)); errRate > allowedErrRate {
145+
t.Errorf("Too many errors in encoding degrees (got %f, allowed %f)", errRate, allowedErrRate)
146+
}
147+
}
148+
149+
func TestEncodeIntegers(t *testing.T) {
150+
for i, elt := range encoding {
151+
got := integerEncode(elt.latInt, elt.lngInt, elt.length)
152+
if got != elt.code {
153+
t.Errorf("%d. got %q for integerEncode(%v,%v,%d), wanted %q", i, got, elt.latInt, elt.lngInt, elt.length, elt.code)
154+
}
155+
}
156+
}
157+
158+
func TestConvertDegrees(t *testing.T) {
159+
for i, elt := range encoding {
160+
got := latitudeAsInteger(elt.latDeg)
161+
if got > elt.latInt || got < elt.latInt-1 {
162+
t.Errorf("%d. got %d for latitudeAsInteger(%v), wanted %d", i, got, elt.latDeg, elt.latInt)
163+
}
164+
got = longitudeAsInteger(elt.lngDeg)
165+
if got > elt.lngInt || got < elt.lngInt-1 {
166+
t.Errorf("%d. got %d for longitudeAsInteger(%v), wanted %d", i, got, elt.lngDeg, elt.lngInt)
136167
}
137168
}
138169
}
@@ -212,6 +243,14 @@ func mustInt(a string) int {
212243
return f
213244
}
214245

246+
func mustInt64(a string) int64 {
247+
f, err := strconv.ParseInt(a, 10, 64)
248+
if err != nil {
249+
panic(err)
250+
}
251+
return f
252+
}
253+
215254
func TestFuzzCrashers(t *testing.T) {
216255
for i, code := range []string{
217256
"975722X9+88X29qqX297" +

0 commit comments

Comments
 (0)