Current section

Files

Jump to
astro lib astro utils.ex
Raw

lib/astro/utils.ex

defmodule Astro.Utils do
@moduledoc false
import Astro.Guards
@radians_to_degrees 180.0 / :math.pi()
def to_degrees(radians) do
radians * @radians_to_degrees
end
def to_radians(degrees) do
degrees / @radians_to_degrees
end
@doc """
Calculates the modulo of a number (integer, float).
Note that this function uses `floored division` whereas the builtin `rem`
function uses `truncated division`. See `Decimal.rem/2` if you want a
`truncated division` function for Decimals that will return the same value as
the BIF `rem/2` but in Decimal form.
See [Wikipedia](https://en.wikipedia.org/wiki/Modulo_operation) for an
explanation of the difference.
## Examples
iex> Cldr.Math.mod(1234.0, 5)
4.0
iex> Cldr.Math.mod(Decimal.new("1234.456"), 5)
#Decimal<4.456>
iex> Cldr.Math.mod(Decimal.new("123.456"), Decimal.new("3.4"))
#Decimal<1.056>
iex> Cldr.Math.mod Decimal.new("123.456"), 3.4
#Decimal<1.056>
"""
@spec mod(number, number) :: number
def mod(number, modulus) when is_float(number) and is_number(modulus) do
number - Float.floor(number / modulus) * modulus
end
def mod(number, modulus) when is_integer(number) and is_integer(modulus) do
modulo =
number
|> Integer.floor_div(modulus)
|> Kernel.*(modulus)
number - modulo
end
def mod(number, modulus) when is_integer(number) and is_number(modulus) do
modulo =
number
|> Kernel./(modulus)
|> Float.floor()
|> Kernel.*(modulus)
number - modulo
end
@doc """
Returns the remainder and dividend of two numbers.
"""
@spec div_mod(number, number) :: {number, number}
def div_mod(n1, n2) when is_integer(n1) and is_integer(n2) do
div = div(n1, n2)
mod = n2 - div * n2
{div, mod}
end
def div_mod(n1, n2) when is_number(n1) and is_number(n2) do
div = n1 / n2
mod = n2 - div * n2
{div, mod}
end
def normalize_location({lng, lat, alt}) when is_lat(lat) and is_lng(lng) and is_alt(alt) do
%Geo.PointZ{coordinates: {lng, lat, alt}}
end
def normalize_location({lng, lat}) when is_lat(lat) and is_lng(lng) do
%Geo.PointZ{coordinates: {lng, lat, 0.0}}
end
def normalize_location(%Geo.Point{coordinates: {lng, lat}}) when is_lat(lat) and is_lng(lng) do
%Geo.PointZ{coordinates: {lng, lat, 0.0}}
end
def cos(degrees) do
degrees
|> to_radians
|> :math.cos()
end
end