mod wrap; use std::ops::RangeInclusive; use s2::{cellid::CellID, latlng::LatLng}; use words::Word; pub(crate) const TWELVE_BITS: u64 = 0b1111_1111_1111; pub(crate) const THIRTEEN_BITS: u64 = 0b1_1111_1111_1111; use crate::Error; pub fn lat_lon_to_cellid(lat: f64, lon: f64) -> Result { // Wrap the latitudes and longitudes let (lat, lon) = wrap::wrap_latlon(lat, lon); if !lat.is_finite() || !lon.is_finite() { return Err(Error::NaNLatLng); } Ok(CellID::from(LatLng::from_degrees(lat, lon))) } pub fn extract_binary(number: u64, range: RangeInclusive) -> u64 { (number >> range.start()) & (u64::MAX >> (63 - (range.end() - range.start()))) } #[cfg(test)] mod tests { use super::*; #[test] fn test_extract_binary() { assert_eq!(extract_binary(0b0, 0..=0), 0b0); assert_eq!(extract_binary(0b11_1111_11, 2..=5), 0b1111); assert_eq!(extract_binary(0b11_0101_11, 2..=5), 0b0101); assert_eq!(extract_binary(0b11_1100_11, 2..=5), 0b1100); assert_eq!(extract_binary(0b111_10011_, 0..=4), 0b10011); assert_eq!(extract_binary(0b111100_1_1, 1..=1), 0b1); assert_eq!(extract_binary(0b111100_0_1, 1..=1), 0b0); // A full test from the docs let cellid = 0b0100101110101000_1011100010010011_1001001100100100_1100000000000000_u64; assert_eq!(extract_binary(cellid, 15..=24), 0b10_01001001); assert_eq!(extract_binary(cellid, 25..=37), 0b01001_11001001); assert_eq!(extract_binary(cellid, 38..=50), 0b00010_11100010); assert_eq!(extract_binary(cellid, 51..=63), 0b01001_01110101); } }