Skip to content

Commit 4940e8f

Browse files
authored
modify integer conversion for rust (#694)
1 parent 36671cb commit 4940e8f

File tree

1 file changed

+21
-12
lines changed

1 file changed

+21
-12
lines changed

rust/src/interface.rs

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -107,22 +107,31 @@ pub fn is_full(code: &str) -> bool {
107107
pub fn encode(pt: Point<f64>, code_length: usize) -> String {
108108
let (lng, lat) = pt.x_y();
109109

110-
let mut lat = clip_latitude(lat);
111-
let lng = normalize_longitude(lng);
112-
113110
let trimmed_code_length = min(max(code_length, MIN_CODE_LENGTH), MAX_CODE_LENGTH);
114111

115-
// Latitude 90 needs to be adjusted to be just less, so the returned code
116-
// can also be decoded.
117-
if lat > LATITUDE_MAX || (LATITUDE_MAX - lat) < 1e-10f64 {
118-
lat -= compute_latitude_precision(trimmed_code_length);
112+
// This approach converts each value to an integer after multiplying it by the final precision.
113+
// This allows us to use only integer operations, so avoiding any accumulation of floating
114+
// point representation errors.
115+
116+
// Convert latitude into a positive integer clipped into the range 0-(just under 180*2.5e7).
117+
// Latitude 90 needs to be adjusted to be just less, so the returned code can also be decoded.
118+
let mut lat_val = (lat * LAT_INTEGER_MULTIPLIER as f64).round() as i64;
119+
lat_val += LATITUDE_MAX as i64 * LAT_INTEGER_MULTIPLIER;
120+
if lat_val < 0 {
121+
lat_val = 0
122+
} else if lat_val >= 2 * LATITUDE_MAX as i64 * LAT_INTEGER_MULTIPLIER {
123+
lat_val = 2 * LATITUDE_MAX as i64 * LAT_INTEGER_MULTIPLIER - 1;
119124
}
120125

121-
// Convert to integers.
122-
let mut lat_val =
123-
(((lat + LATITUDE_MAX) * LAT_INTEGER_MULTIPLIER as f64 * 1e6).round() / 1e6f64) as i64;
124-
let mut lng_val =
125-
(((lng + LONGITUDE_MAX) * LNG_INTEGER_MULTIPLIER as f64 * 1e6).round() / 1e6f64) as i64;
126+
// Convert longitude into a positive integer and normalise it into the range 0-360*8.192e6.
127+
let mut lng_val = (lng * LNG_INTEGER_MULTIPLIER as f64).round() as i64;
128+
lng_val += LONGITUDE_MAX as i64 * LNG_INTEGER_MULTIPLIER;
129+
if lng_val < 0 {
130+
lng_val = lng_val % (2 * LONGITUDE_MAX as i64 * LNG_INTEGER_MULTIPLIER)
131+
+ (2 * LONGITUDE_MAX as i64 * LNG_INTEGER_MULTIPLIER)
132+
} else if lng_val >= 2 * LONGITUDE_MAX as i64 * LNG_INTEGER_MULTIPLIER {
133+
lng_val = lng_val % (2 * LONGITUDE_MAX as i64 * LNG_INTEGER_MULTIPLIER)
134+
}
126135

127136
// Compute the code digits. This largely ignores the requested length - it
128137
// generates either a 10 digit code, or a 15 digit code, and then truncates

0 commit comments

Comments
 (0)