<commit_before>#![doc(html_root_url = "https://urschrei.github.io/lonlat_bng/")]
//! The `lonlat_bng` crate provides functions that convert decimal longitude
//! and latitude coordinates into [British National Grid](https://en.wikipedia.org/wiki/Ordnance_Survey_National_Grid) coordinates, and vice versa.  
//! This library makes use of the [OSTN02](https://www.ordnancesurvey.co.uk/business-and-government/help-and-support/navigation-technology/os-net/surveying.html) transformations
//! for the following functions:
//!
//! - [`convert_osgb36`](fn.convert_osgb36.html)
//! - [`convert_ETRS89_to_OSGB36`](fn.convert_ETRS89_to_OSGB36.html)
//! - [`convert_to_osgb36_threaded`](fn.convert_to_osgb36_threaded.html)
//! - [`convert_to_osgb36_threaded_vec`](fn.convert_to_osgb_threaded_vec.html)
//! - [`convert_ETRS89_to_OSGB36_threaded`](fn.convert_ETRS89_to_OSGB36_threaded.html)
//! - [`convert_ETRS89_to_OSGB36_threaded_vec`](fn.convert_ETRS89_to_OSGB36_threaded_vec.html)
//!
//! These functions transform input longitude and latitude coordinates to OSGB36 Eastings and Northings with high accuracy, and are suitable for use in surveying and construction. Please run your own tests, though.
//! **Note that `lon`, `lat` coordinates outside the UK bounding box will be transformed to `(9999, 9999)`, which cannot be mapped.**
//!
//! # Examples
//!
//! ```
//! // Convert single Longitude, Latitude values to OSGB36 Eastings and Northings
//! assert_eq!((651409.792, 313177.448), lonlat_bng::ostn02::convert_osgb36(&1.716073973, &52.658007833).unwrap());
//! ```
//! ```
//! // Convert single Longitude, Latitude values to BNG Eastings and Northings (Fast, but only accurate within ~7m)
//! assert_eq!((516276, 173141), lonlat_bng::convert_bng(&-0.32824866, &51.44533267).unwrap());
//! ```
//! ```
//! Convert single BNG values to Longitude, Latitude (Fast, but only accurate within ~7m)
//! assert_eq!((-0.328248, 51.44534), lonlat_bng::convert_lonlat(&516276, &173141));
//! ```
//! ```
//! // Convert vectors using threaded functions
//! lonlat_bng::convert_to_bng_threaded_vec(vec![&-0.32824866], vec![&51.44533267]);
//! ```
//! ```
//! lonlat_bng::convert_to_lonlat_threaded_vec(vec![&516276], vec![&173141]);
//! ```
//! The crate also provides C-compatible wrapper functions, which are intended for use with FFI.
//! An example implementation using Python can be found at [Convertbng](https://github.com/urschrei/convertbng).
use std::f64;
use std::mem;
use std::slice;
use std::fmt;

extern crate libc;
use libc::{c_void, c_float, c_double, c_int};

extern crate ostn02_phf;

extern crate rand;

extern crate crossbeam;
use crossbeam::scope;

extern crate num_cpus;

mod ostn02;
pub use ostn02::convert_etrs89;
pub use ostn02::convert_osgb36;
pub use ostn02::convert_ETRS89_to_OSGB36;
use ostn02::round_to_nearest_mm;
// Constants used for coordinate conversions
//
// Ellipsoids
pub const AIRY_1830_SEMI_MAJOR: f64 = 6377563.396;
pub const AIRY_1830_SEMI_MINOR: f64 = 6356256.909;
pub const GRS80_SEMI_MAJOR: f64 = 6378137.000;
pub const GRS80_SEMI_MINOR: f64 = 6356752.3141;
// Northing & easting of true origin (m)
pub const TRUE_ORIGIN_NORTHING: f64 = -100000.;
pub const TRUE_ORIGIN_EASTING: f64 = 400000.;
// For Helmert Transform to OSGB36, translations along the x, y, z axes
// When transforming to WGS84, reverse the signs
pub const TX: f64 = -446.448;
pub const TY: f64 = 125.157;
pub const TZ: f64 = -542.060;
// Rotations along the x, y, z axes, in seconds
pub const RXS: f64 = -0.1502;
pub const RYS: f64 = -0.2470;
pub const RZS: f64 = -0.8421;

pub const s: f64 = 20.4894 * 0.000001;
// etc
pub const PI: f64 = f64::consts::PI;
pub const RAD: f64 = PI / 180.;

pub const MAX_EASTING: i32 = 700000;
pub const MAX_NORTHING: i32 = 1250000;

pub const MIN_LONGITUDE: f64 = -6.379880;
pub const MAX_LONGITUDE: f64 = 1.768960;
pub const MIN_LATITUDE: f64 = 49.871159;
pub const MAX_LATITUDE: f64 = 55.811741;
// OSGB bounds according to Spatialreference: -6.2400, 1.7800, 49.9400, 58.6700

#[repr(C)]
pub struct Array {
    pub data: *const c_void,
    pub len: libc::size_t,
}


// fn helmert(lon_vec: Vec<&f32>, lat_vec: Vec<&f32>) -> (Vec<f32>, Vec<f32>) {
//     let t_array = Vec3::new(TX, TY, TZ);
//     let params = Mat3::new(1. + s, RZS, -RYS, -RZS, 1. + s, RXS, RYS, -RXS, 1. + s);
//     // let zeros: Vec<&f32> = vec![&1.; lon_vec.len()];
//     let test = vec![1, 2, 3, 4, 5, 6];
//     // let mut combined: Vec<&f32> = lon_vec.extend(lat_vec.iter()).collect();
//     // combined.extend(zeros.iter().cloned());
//     // let tmat = DMat::from_row_vec(3, zeros.len(), &combined);
//     let tmat = DMat::from_row_vec(3, 2, &test);
//     // build input vector of x, y, and z columns
//     // let inp = DMat::from_row_vec(3, 1, vec![lon_vec, lat_vec, h_vec]);
//     (vec![1.], vec![2.])
// }

/// Free memory which Rust has allocated across the FFI boundary (i32 values)
///
/// # Examples
///
/// ```
/// # extern crate libc;
/// let lon_vec: Vec<f64> = vec![-2.0183041005533306];
/// let lat_vec: Vec<f64> = vec![54.589097162646141];
/// let lon_arr = Array {
///     data: lon_vec.as_ptr() as *const libc::c_void,
///     len: lon_vec.len() as libc::size_t,
/// };
/// let lat_arr = Array {
///     data: lat_vec.as_ptr() as *const libc::c_void,
///     len: lat_vec.len() as libc::size_t,
/// };
/// let (eastings, northings) = convert_to_bng_threaded(lon_arr, lat_arr);
/// drop_int_array(eastings, northings);
/// ```
/// # Safety
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data 
#[no_mangle]
pub extern "C" fn drop_int_array(eastings: Array, northings: Array) {
    if eastings.data.is_null() {
        return;
    }
    if northings.data.is_null() {
        return;
    }
    unsafe { Vec::from_raw_parts(eastings.data as *mut c_int, eastings.len, eastings.len) };
    unsafe { Vec::from_raw_parts(northings.data as *mut c_int, northings.len, northings.len) };
}

/// Free memory which Rust has allocated across the FFI boundary (f32 values)
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data 
#[no_mangle]
pub extern "C" fn drop_float_array(lons: Array, lats: Array) {
    if lons.data.is_null() {
        return;
    }
    if lats.data.is_null() {
        return;
    }
    unsafe { Vec::from_raw_parts(lons.data as *mut c_double, lons.len, lons.len) };
    unsafe { Vec::from_raw_parts(lats.data as *mut c_double, lats.len, lats.len) };
}

impl Array {
    unsafe fn as_f64_slice(&self) -> &[f64] {
        assert!(!self.data.is_null());
        slice::from_raw_parts(self.data as *const f64, self.len as usize)
    }
    unsafe fn as_i32_slice(&self) -> &[i32] {<commit_msg>Fix typo<commit_after>#![doc(html_root_url = "https://urschrei.github.io/lonlat_bng/")]
//! The `lonlat_bng` crate provides functions that convert decimal longitude
//! and latitude coordinates into [British National Grid](https://en.wikipedia.org/wiki/Ordnance_Survey_National_Grid) coordinates, and vice versa.  
//! This library makes use of the [OSTN02](https://www.ordnancesurvey.co.uk/business-and-government/help-and-support/navigation-technology/os-net/surveying.html) transformations
//! for the following functions:
//!
//! - [`convert_osgb36`](fn.convert_osgb36.html)
//! - [`convert_ETRS89_to_OSGB36`](fn.convert_ETRS89_to_OSGB36.html)
//! - [`convert_to_osgb36_threaded`](fn.convert_to_osgb36_threaded.html)
//! - [`convert_to_osgb36_threaded_vec`](fn.convert_to_osgb_threaded_vec.html)
//! - [`convert_ETRS89_to_OSGB36_threaded`](fn.convert_ETRS89_to_OSGB36_threaded.html)
//! - [`convert_ETRS89_to_OSGB36_threaded_vec`](fn.convert_ETRS89_to_OSGB36_threaded_vec.html)
//!
//! These functions transform input longitude and latitude coordinates to OSGB36 Eastings and Northings with high accuracy, and are suitable for use in surveying and construction. Please run your own tests, though.
//! **Note that `lon`, `lat` coordinates outside the UK bounding box will be transformed to `(9999, 9999)`, which cannot be mapped.**
//!
//! # Examples
//!
//! ```
//! // Convert single Longitude, Latitude values to OSGB36 Eastings and Northings
//! assert_eq!((651409.792, 313177.448), lonlat_bng::ostn02::convert_osgb36(&1.716073973, &52.658007833).unwrap());
//! ```
//! ```
//! // Convert single Longitude, Latitude values to BNG Eastings and Northings (Fast, but only accurate within ~7m)
//! assert_eq!((516276, 173141), lonlat_bng::convert_bng(&-0.32824866, &51.44533267).unwrap());
//! ```
//! ```
//! Convert single BNG values to Longitude, Latitude (Fast, but only accurate within ~7m)
//! assert_eq!((-0.328248, 51.44534), lonlat_bng::convert_lonlat(&516276, &173141));
//! ```
//! ```
//! // Convert vectors using threaded functions
//! lonlat_bng::convert_to_bng_threaded_vec(vec![&-0.32824866], vec![&51.44533267]);
//! ```
//! ```
//! lonlat_bng::convert_to_lonlat_threaded_vec(vec![&516276], vec![&173141]);
//! ```
//! The crate also provides C-compatible wrapper functions, which are intended for use with FFI.
//! An example implementation using Python can be found at [Convertbng](https://github.com/urschrei/convertbng).
use std::f64;
use std::mem;
use std::slice;
use std::fmt;

extern crate libc;
use libc::{c_void, c_float, c_double, c_int};

extern crate ostn02_phf;

extern crate rand;

extern crate crossbeam;
use crossbeam::scope;

extern crate num_cpus;

mod ostn02;
pub use ostn02::convert_etrs89;
pub use ostn02::convert_osgb36;
pub use ostn02::convert_ETRS89_to_OSGB36;
use ostn02::round_to_nearest_mm;
// Constants used for coordinate conversions
//
// Ellipsoids
pub const AIRY_1830_SEMI_MAJOR: f64 = 6377563.396;
pub const AIRY_1830_SEMI_MINOR: f64 = 6356256.909;
pub const GRS80_SEMI_MAJOR: f64 = 6378137.000;
pub const GRS80_SEMI_MINOR: f64 = 6356752.3141;
// Northing & easting of true origin (m)
pub const TRUE_ORIGIN_NORTHING: f64 = -100000.;
pub const TRUE_ORIGIN_EASTING: f64 = 400000.;
// For Helmert Transform to OSGB36, translations along the x, y, z axes
// When transforming to WGS84, reverse the signs
pub const TX: f64 = -446.448;
pub const TY: f64 = 125.157;
pub const TZ: f64 = -542.060;
// Rotations along the x, y, z axes, in seconds
pub const RXS: f64 = -0.1502;
pub const RYS: f64 = -0.2470;
pub const RZS: f64 = -0.8421;

pub const s: f64 = 20.4894 * 0.000001;
// etc
pub const PI: f64 = f64::consts::PI;
pub const RAD: f64 = PI / 180.;
pub const DAR: f64 = 180. / PI;
pub const MAX_EASTING: i32 = 700000;
pub const MAX_NORTHING: i32 = 1250000;

pub const MIN_LONGITUDE: f64 = -6.379880;
pub const MAX_LONGITUDE: f64 = 1.768960;
pub const MIN_LATITUDE: f64 = 49.871159;
pub const MAX_LATITUDE: f64 = 55.811741;
// OSGB bounds according to Spatialreference: -6.2400, 1.7800, 49.9400, 58.6700

#[repr(C)]
pub struct Array {
    pub data: *const c_void,
    pub len: libc::size_t,
}


// fn helmert(lon_vec: Vec<&f32>, lat_vec: Vec<&f32>) -> (Vec<f32>, Vec<f32>) {
//     let t_array = Vec3::new(TX, TY, TZ);
//     let params = Mat3::new(1. + s, RZS, -RYS, -RZS, 1. + s, RXS, RYS, -RXS, 1. + s);
//     // let zeros: Vec<&f32> = vec![&1.; lon_vec.len()];
//     let test = vec![1, 2, 3, 4, 5, 6];
//     // let mut combined: Vec<&f32> = lon_vec.extend(lat_vec.iter()).collect();
//     // combined.extend(zeros.iter().cloned());
//     // let tmat = DMat::from_row_vec(3, zeros.len(), &combined);
//     let tmat = DMat::from_row_vec(3, 2, &test);
//     // build input vector of x, y, and z columns
//     // let inp = DMat::from_row_vec(3, 1, vec![lon_vec, lat_vec, h_vec]);
//     (vec![1.], vec![2.])
// }

/// Free memory which Rust has allocated across the FFI boundary (i32 values)
///
/// # Examples
///
/// ```
/// # extern crate libc;
/// let lon_vec: Vec<f64> = vec![-2.0183041005533306];
/// let lat_vec: Vec<f64> = vec![54.589097162646141];
/// let lon_arr = Array {
///     data: lon_vec.as_ptr() as *const libc::c_void,
///     len: lon_vec.len() as libc::size_t,
/// };
/// let lat_arr = Array {
///     data: lat_vec.as_ptr() as *const libc::c_void,
///     len: lat_vec.len() as libc::size_t,
/// };
/// let (eastings, northings) = convert_to_bng_threaded(lon_arr, lat_arr);
/// drop_int_array(eastings, northings);
/// ```
/// # Safety
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data 
#[no_mangle]
pub extern "C" fn drop_int_array(eastings: Array, northings: Array) {
    if eastings.data.is_null() {
        return;
    }
    if northings.data.is_null() {
        return;
    }
    unsafe { Vec::from_raw_parts(eastings.data as *mut c_int, eastings.len, eastings.len) };
    unsafe { Vec::from_raw_parts(northings.data as *mut c_int, northings.len, northings.len) };
}

/// Free memory which Rust has allocated across the FFI boundary (f64 values)
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data 
#[no_mangle]
pub extern "C" fn drop_float_array(lons: Array, lats: Array) {
    if lons.data.is_null() {
        return;
    }
    if lats.data.is_null() {
        return;
    }
    unsafe { Vec::from_raw_parts(lons.data as *mut c_double, lons.len, lons.len) };
    unsafe { Vec::from_raw_parts(lats.data as *mut c_double, lats.len, lats.len) };
}

impl Array {
    unsafe fn as_f64_slice(&self) -> &[f64] {
        assert!(!self.data.is_null());
        slice::from_raw_parts(self.data as *const f64, self.len as usize)
    }
    unsafe fn as_i32_slice(&self) -> &[i32] {
{'fraction_non_alphanumeric': 0.16019848911272405, 'fraction_numerical': 0.07635905791734558, 'mean_word_length': 3.8173385658223333, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 25, 'https://': 8, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '164061', 'n_tokens_mistral': 5770, 'n_tokens_neox': 5015, 'n_words': 1279}