# Flecks of Rust #6: Math fun in Rust with geodesy

Math in Rust is a little bit different in Rust than other languages you may be familiar with. For example in Python if you want to compute the sine for an angle of 55 degrees, you would first import the `math` module, convert the angle to radians and then use the value of the `math.sin()` function:

```>>> # NOTE: Python example! Not Rust!
>>> import math
>>> angle = 55
0.8191520442889917
```

In Rust you use the methods of the numeric type you are working with. For example, the `f32` type is good for math unless you absolutely need the added precision of the `f64` type. So, you could declare your angle as `f32`. Then you would use the `to_radians` function of that type to convert degrees to radians, and finally you would take the sine of that:

```fn main() {
let angle = 55f32;
}
```
`0.81915206`

You will soon get used to starting with the value.

The Rust Cookbook has an example of computing the distance between two geographic locations using the Haversine formula. The result is accurate for the purpose, as it is rarely possible to follow the shortest path when travelling from one location to another. However, the example uses a fixed value for Earth's radius, but that can vary depending on the latitude.

Here is a function to compute the value of Earth's radius in kilometers at a given latitude. You could pass in the latitude component of either of the geographic coordinates, or perhaps their average. The function also depends on two constants defined as values in kilometers.

```const EARTH_EQUATORIAL_RADIUS: f32 = 6378.1370;

// Computes the geocentric radius of the Earth for the given latitude.
// See https://rust-lang-nursery.github.io/rust-cookbook/science/mathematics/trigonometry.html
fn earth_geocentric_radius(latitude_degrees: f32) -> f32 {

let t1a = a.powi(2) * latitude.cos();
let t1b = b.powi(2) * latitude.sin();
let t1 = t1a.powi(2) + t1b.powi(2);

let t2a = a * latitude.cos();
let t2b = b * latitude.sin();
let t2 = t2a.powi(2) + t2b.powi(2);

(t1 / t2).sqrt()
}
```

If you replace the value of `earth_radius_kilometer` in the Rust Cookbook example with the value obtained from the `earth_geocentric_radius` function above (with the latitude given as the average of the latitudes of Paris and London), you will find that the result differs by 0.3 kilometers, which is hardly significant in this case:

```Earth's geocentric radius for latitude 50.18097 degrees is 6365.565 kilometers
Distance between Paris and London on the surface of Earth is 334.7 kilometers
```

What is more interesting here is the way that the various mathematical functions are used in Rust. The standard library defines the usual trigonometic functions for the floating-point types, and many more.

Since the formula for computing Earth's geocentric radius requires some values to be squared, the function uses the `powi` function of the `f32` type, which uses an integer exponent, and should be faster than the `powf` function which allows you to use a floating-point exponent.

Another special feature of Rust worth mentioning is the return value of the function. While Rust does have a `return` statement, the idiomatic way is to let the last expression in the function act as the return value. Here the expression `(t1 / t2).sqrt()` is that return value.

Finally, here is a complete example that implements the Haversine formula as a function. It gives you another idea of how the Rust mathematical functions are used.

```// A coordinate point, with latitude and longitude in degrees.
struct Coordinates {
latitude: f32,
longitude: f32,
}

// Computes the distance between two geographical points in kilometers.
// The coordinate values are expressed in degrees.
// Uses the haversine formula (see http://en.wikipedia.org/wiki/Haversine_formula).
// This implementation is derived from the JavaScript code
// by Andrew Hedges at http://andrew.hedges.name/experiments/haversine/.
// For added accuracy, you may want pass an Earth radius value more suitable for the
// latitudes of the points you are processing.
fn haversine(point1: Coordinates, point2: Coordinates, earth_radius: f32) -> f32 {

let dlon = lon2 - lon1;
let dlat = lat2 - lat1;
let a = ((dlat / 2.0).sin()).powi(2) + lat1.cos() * lat2.cos() * ((dlon / 2.0).sin()).powi(2);
let c = 2.0 * a.sqrt().atan2((1.0 - a).sqrt());
}

fn main() {
let paris = Coordinates { latitude: 48.85341, longitude: -2.34880 };
let london = Coordinates { latitude: 51.50853, longitude: -0.12574 };

let average_latitude = (paris.latitude + london.latitude) / 2.0;