diff --git a/.formatter.exs b/.formatter.exs new file mode 100644 index 0000000..d2cda26 --- /dev/null +++ b/.formatter.exs @@ -0,0 +1,4 @@ +# Used by "mix format" +[ + inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] +] diff --git a/.gitignore b/.gitignore index ba47db6..fdaf4aa 100644 --- a/.gitignore +++ b/.gitignore @@ -1,14 +1,17 @@ # The directory Mix will write compiled artifacts to. -/_build +/_build/ # If you run "mix test --cover", coverage assets end up here. -/cover +/cover/ # The directory Mix downloads your dependencies sources to. -/deps +/deps/ -# Where 3rd-party dependencies like ExDoc output generated docs. -/doc +# Where third-party dependencies like ExDoc output generated docs. +/doc/ + +# Ignore .fetch files in case you like to edit your project deps locally. +/.fetch # If the VM crashes, it generates a dump, let's ignore it too. erl_crash.dump @@ -16,6 +19,13 @@ erl_crash.dump # Also ignore archive artifacts (built via "mix archive.build"). *.ez -.elixir_ls +# Ignore package tarball (built via "mix hex.build"). +vector-*.tar + +# Temporary files for e.g. tests. +/tmp/ -.DS_Store \ No newline at end of file +# Misc. +.DS_Store +.elixir_ls/ +/bench/snapshots/ diff --git a/LICENSE b/LICENSE.md similarity index 100% rename from LICENSE rename to LICENSE.md diff --git a/README.md b/README.md index bf768ad..62f4a73 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,30 @@ # Vector Math Library for Elixir [![Build Status](https://travis-ci.org/pkinney/vector_ex.svg?branch=master)](https://travis-ci.org/pkinney/vector_ex) -[![Hex.pm](https://img.shields.io/hexpm/v/vector.svg)](https://hex.pm/packages/vector) +[![Module Version](https://img.shields.io/hexpm/v/vector.svg)](https://hex.pm/packages/vector) +[![Hex Docs](https://img.shields.io/badge/hex-docs-lightgreen.svg)](https://hexdocs.pm/vector/) +[![Total Download](https://img.shields.io/hexpm/dt/vector.svg)](https://hex.pm/packages/vector) +[![License](https://img.shields.io/hexpm/l/vector.svg)](https://github.com/pkinney/vector/blob/master/LICENSE) +[![Last Updated](https://img.shields.io/github/last-commit/pkinney/vector_ex.svg)](https://github.com/pkinney/vector_ex/commits/master) + Library of common vector functions for use in geometric or graphical calculations. ## Installation +The package can be installed by adding `:vector` to your list of dependencies +in `mix.exs`: + ```elixir defp deps do - [{:vector, "~> 1.0"}] + [ + {:vector, "~> 1.0"} + ] end ``` ## Usage -**[Full Documentation](https://hexdocs.pm/vector/Vector.html)** - The `Vector` module contains several functions that take one or more vectors. Each vector can be a 2- or 3-element tuple. It is possible to mix two- and three-dimensional vectors, in which case the `z` of the two-dimensional vector @@ -32,12 +40,44 @@ Vector.subtract({2, 0, -1}, {1, 3}) #=> {1, -3, 1} Vector.component({2, 3, -2}, :y) #=> 3 ``` -## Tests +Included in the project are a suite of +[algebraic identities](https://en.wikipedia.org/wiki/Vector_algebra_relations#Addition_and_multiplication_of_vectors) that can be run against a large generated set of vectors. + +## Benchmark ```bash -> mix test +$ mix bench + +Settings: + duration: 1.0 s + +## VectorBench +[03:00:07] 1/8: A . (B x C) +[03:00:09] 2/8: A . B +[03:00:10] 3/8: A x (B x C) +[03:00:12] 4/8: A x B +[03:00:14] 5/8: B (A . C) - C (A . B) +[03:00:16] 6/8: unit vector +[03:00:20] 7/8: zero-vector cross 2D +[03:00:31] 8/8: zero-vector cross 3D + +Finished in 25.05 seconds + +## VectorBench +benchmark name iterations average time +zero-vector cross 2D 100000000 0.10 µs/op +zero-vector cross 3D 10000000 0.13 µs/op +A . B 1000 1091.15 µs/op +A x B 1000 1476.54 µs/op +unit vector 500 7180.52 µs/op +A x (B x C) 10 164521.80 µs/op +A . (B x C) 5 272087.20 µs/op +B (A . C) - C (A . B) 2 619590.00 µs/op ``` -Included in the project are a suite of -[algebraic identities](https://en.wikipedia.org/wiki/Vector_algebra_relations#Addition_and_multiplication_of_vectors) -that can be run against a large generated set of vectors. +## Copyright and License + +Copyright (c) 2017 Powell Kinney + +This library is released under the MIT License. See the [LICENSE.md](./LICENSE.md) file +for further details. diff --git a/doc/.build b/doc/.build deleted file mode 100644 index 0a55033..0000000 --- a/doc/.build +++ /dev/null @@ -1,12 +0,0 @@ -dist/html-399e30b9b028e3059575.css -dist/html-399e30b9b028e3059575.js -dist/html/fonts/icomoon.eot -dist/html/fonts/icomoon.svg -dist/html/fonts/icomoon.ttf -dist/html/fonts/icomoon.woff -dist/sidebar_items-71d22232a3.js -api-reference.html -search.html -404.html -Vector.html -index.html diff --git a/doc/404.html b/doc/404.html deleted file mode 100644 index 26f8b56..0000000 --- a/doc/404.html +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - - - 404 — vector v1.0.1 - - - - - - - - -
- - - - -
-
-
- - -

Page not found

- -

Sorry, but the page you were trying to get to, does not exist. You -may want to try searching this site using the sidebar - or using our API Reference page -to find what you were looking for.

- - -
-
-
-
- - - diff --git a/doc/Vector.html b/doc/Vector.html deleted file mode 100644 index 6883e0b..0000000 --- a/doc/Vector.html +++ /dev/null @@ -1,743 +0,0 @@ - - - - - - - - Vector — vector v1.0.1 - - - - - - - - -
- - - - -
-
-
- - -

- vector v1.0.1 -Vector

- - -
-

A library of two- and three-dimensional vector operations. All vectors -are represented as tuples with either two or three elements.

-

- - Examples -

- -
iex> # Vector Tripple Product Identity
-...> a = {2, 3, 1}
-...> b = {1, 4, -2}
-...> c = {-1, 2, 1}
-...> Vector.equal?(
-...>   Vector.cross(Vector.cross(a, b), c),
-...>   Vector.subtract(Vector.multiply(b, Vector.dot(a, c)), Vector.multiply(a, Vector.dot(b, c))))
-true
-
- -
-

- - - Link to this section - - Summary -

-
-

- Types -

-
- -
-
-
- vector() -
-
-
-
-

- Functions -

-
- -

Adds two vectors

-
-
-
- -

Returns the basis vector for the given axis

-
-
-
- -

Returns the scalar component for the axis given

-
-
-
- -

Returns the cross product of two vectors AB

-
-
-
- -

Returns the norm (magnitude) of the cross product of two vectors AB

-
-
-
- -

Divide a vector by scalar value s

-
-
-
- -

Returns the dot product of two vectors AB

-
-
-
- -

Compares two vectors for euqality, with an optional tolerance

-
-
-
- -

Multiply a vector by scalar value s

-
-
-
-
- norm(arg) -
-

Returns the norm (magnitude) of a vector

-
-
-
- -

Returns the square of the norm norm (magnitude) of a vector

-
-
-
- -

Returns a new coordinate by projecting a given length distance from -coordinate start along vector

-
-
-
- -

Reverses a vector

-
-
-
- -

Subtract vector B from vector A. Equivalent to Vector.add(A, Vector.revers(B))

-
-
-
-
- unit(v) -
-

Returns the unit vector parallel ot the given vector. -This will raise an ArithmeticError if a zero-magnitude vector is given. -Use unit_safe if there is a chance that a zero-magnitude vector -will be sent

-
-
-
- -

Returns the unit vector parallel ot the given vector, but will handle -the vectors {0, 0} and {0, 0, 0} by returning the same vector

-
-
-
-
- -
-

- - - Link to this section - -Types

-
-
-
- - - Link to this type - -

location() - -
-
location() :: {number(), number()} | {number(), number(), number()}
-
-

-
-
-
-
-
- - - Link to this type - -

vector() - -
-
vector() :: {number(), number()} | {number(), number(), number()}
-
-

-
-
-
-
-
-
-

- - - Link to this section - -Functions

-
-
-
- - - Link to this function - -

add(arg1, arg2) - -
-
add(vector(), vector()) :: vector()
-
-

-
-

Adds two vectors

-

- - Examples -

- -
iex> Vector.add({3, -4}, {2, 1})
-{5,-3}
-iex> Vector.add({-2, 0, 5}, {0, 0, 0})
-{-2, 0, 5}
-iex> Vector.add({2, 1, -2}, Vector.reverse({2, 1, -2}))
-{0, 0, 0}
-
-
-
-
- - - Link to this function - -

basis(atom) - -
-
basis(atom()) :: vector()
-
-

-
-

Returns the basis vector for the given axis

-

- - Examples -

- -
iex> Vector.basis(:x)
-{1, 0, 0}
-iex> Vector.basis(:y)
-{0, 1, 0}
-iex> Vector.component(Vector.basis(:y), :y)
-1
-
-
-
-
- - - Link to this function - -

component(arg, atom) - -
-
component(vector(), atom()) :: number()
-
-

-
-

Returns the scalar component for the axis given

-

- - Examples -

- -
iex> Vector.component({3, -4}, :y)
--4
-iex> Vector.component({-6, 0, 8}, :z)
-8
-iex> Vector.component({1, -2}, :z)
-0
-iex> Vector.component(Vector.basis(:x), :z)
-0
-
-
-
-
- - - Link to this function - -

cross(arg1, arg2) - -
-
cross(vector(), vector()) :: vector()
-
-

-
-

Returns the cross product of two vectors AB

-

- - Examples -

- -
iex> Vector.cross({2, 3}, {1, 4})
-{0, 0, 5}
-iex> Vector.cross({2, 2, -1}, {1, 4, 2})
-{8, -5, 6}
-iex> Vector.cross({3, -3, 1}, {4, 9, 2})
-{-15, -2, 39}
-
-
-
-
- - - Link to this function - -

cross_norm(arg1, arg2) - -
-
cross_norm(vector(), vector()) :: number()
-
-

-
-

Returns the norm (magnitude) of the cross product of two vectors AB

-

- - Examples -

- -
iex> Vector.cross_norm({2, 3}, {1, 4})
-5
-iex> Vector.cross_norm({1, 4}, {2, 2})
-6
-iex> Vector.cross_norm({2, 0, -1}, {0, 3, 3})
-9.0
-iex> Float.floor(:math.pow(Vector.cross_norm({2, 2, -1}, {1, 4, 2}), 2))
-125.0
-
-
-
-
- - - Link to this function - -

divide(arg, s) - -
-
divide(vector(), number()) :: vector()
-
-

-
-

Divide a vector by scalar value s

-

- - Examples -

- -
iex> Vector.divide({3, -4}, 2.5)
-{1.2, -1.6}
-iex> Vector.divide({-2, 0, 5}, -2)
-{1.0, 0.0, -2.5}
-
-
-
-
- - - Link to this function - -

dot(arg1, arg2) - -
-
dot(vector(), vector()) :: number()
-
-

-
-

Returns the dot product of two vectors AB

-

- - Examples -

- -
iex> Vector.dot({2, 3}, {1, 4})
-14
-iex> Vector.dot({1, 4}, {2, 2})
-10
-iex> Vector.dot({2, 0, -1}, {0, 3, 3})
--3
-
-
-
- - -
- - - Link to this function - -

equal?(a, b, tolerance \\ 0.0) - -
-
equal?(vector(), vector(), number()) :: boolean()
-
-

-
-

Compares two vectors for euqality, with an optional tolerance

-

- - Examples -

- -
iex> Vector.equal?({3, -4}, {3, -4})
-true
-iex> Vector.equal?({3, -4}, {3.0001, -3.9999})
-false
-iex> Vector.equal?({3, -4}, {3.0001, -3.9999}, 0.001)
-true
-iex> Vector.equal?({3, -4, 1}, {3.0001, -3.9999, 1.0}, 0.001)
-true
-
-
-
-
- - - Link to this function - -

multiply(arg, s) - -
-
multiply(vector(), number()) :: vector()
-
-

-
-

Multiply a vector by scalar value s

-

- - Examples -

- -
iex> Vector.multiply({3, -4}, 2.5)
-{7.5, -10.0}
-iex> Vector.multiply({-2, 0, 5}, -2)
-{4, 0, -10}
-
-
-
-
- - - Link to this function - -

norm(arg) - -
-
norm(vector()) :: number()
-
-

-
-

Returns the norm (magnitude) of a vector

-

- - Examples -

- -
iex> Vector.norm({3, 4})
-5.0
-iex> Vector.norm({-1, 0})
-1
-iex> Vector.norm({0, -2, 0})
-2
-
-
-
-
- - - Link to this function - -

norm_squared(arg) - -
-
norm_squared(vector()) :: number()
-
-

-
-

Returns the square of the norm norm (magnitude) of a vector

-

- - Examples -

- -
iex> Vector.norm_squared({3, 4})
-25
-iex> Vector.norm_squared({1, 0})
-1
-iex> Vector.norm_squared({2, 0, -1})
-5
-iex> Vector.norm_squared({-2, 3, 1})
-14
-
-
-
-
- - - Link to this function - -

project(vector, start, distance) - -
-
project(vector(), location(), number()) :: location()
-
-

-
-

Returns a new coordinate by projecting a given length distance from -coordinate start along vector

-

- - Examples -

- -
iex> Vector.project({3, -4}, {-1, 1}, 4)
-{1.4, -2.2}
-iex> Vector.project({-6, 0, 8}, {1, -2, 0.4}, 2.5)
-{-0.5, -2.0, 2.4}
-iex> Vector.project({-2, 1, 3}, {0, 0, 0}, 2.5) |> Vector.norm()
-2.5
-
-
-
-
- - - Link to this function - -

reverse(arg) - -
-
reverse(vector()) :: vector()
-
-

-
-

Reverses a vector

-

- - Examples -

- -
iex> Vector.reverse({3, -4})
-{-3, 4}
-iex> Vector.reverse({-2, 0, 5})
-{2, 0, -5}
-iex> Vector.cross_norm({-2, 3, 5}, Vector.reverse({-2, 3, 5}))
-0
-
-
-
-
- - - Link to this function - -

subtract(a, b) - -
-
subtract(vector(), vector()) :: vector()
-
-

-
-

Subtract vector B from vector A. Equivalent to Vector.add(A, Vector.revers(B))

-

- - Examples -

- -
iex> Vector.subtract({3, -4}, {2, 1})
-{1,-5}
-iex> Vector.subtract({-2, 0, 5}, {-3, 1, 2})
-{1, -1, 3}
-
-
-
-
- - - Link to this function - -

unit(v) - -
-
unit(vector()) :: vector()
-
-

-
-

Returns the unit vector parallel ot the given vector. -This will raise an ArithmeticError if a zero-magnitude vector is given. -Use unit_safe if there is a chance that a zero-magnitude vector -will be sent.

-

- - Examples -

- -
iex> Vector.unit({3, 4})
-{0.6, 0.8}
-iex> Vector.unit({8, 0, 6})
-{0.8, 0.0, 0.6}
-iex> Vector.unit({-2, 0, 0})
-{-1.0, 0.0, 0.0}
-iex> Vector.unit({0, 0, 0})
-** (ArithmeticError) bad argument in arithmetic expression
-
-
-
-
- - - Link to this function - -

unit_safe(v) - -
-
unit_safe(vector()) :: vector()
-
-

-
-

Returns the unit vector parallel ot the given vector, but will handle -the vectors {0, 0} and {0, 0, 0} by returning the same vector

-

- - Examples -

- -
iex> Vector.unit_safe({3, 4})
-{0.6, 0.8}
-iex> Vector.unit_safe({0, 0})
-{0, 0}
-iex> Vector.unit_safe({0, 0, 0})
-{0, 0, 0}
-
-
-
-
- -
-
-
-
- - - - diff --git a/doc/api-reference.html b/doc/api-reference.html deleted file mode 100644 index c6b7d8f..0000000 --- a/doc/api-reference.html +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - - - API Reference — vector v1.0.1 - - - - - - - - -
- - - - -
-
-
- - -

- vector v1.0.1 - API Reference -

- -
-

- - Modules -

- -
-
-
- Vector -
-

A library of two- and three-dimensional vector operations. All vectors -are represented as tuples with either two or three elements

-
-
-
-
- - - -
-
-
-
- - - - diff --git a/doc/index.html b/doc/index.html deleted file mode 100644 index 14644de..0000000 --- a/doc/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - vector v1.0.1 — Documentation - - - - - - diff --git a/doc/search.html b/doc/search.html deleted file mode 100644 index 19fba92..0000000 --- a/doc/search.html +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - Search — vector v1.0.1 - - - - - - - - -
- - - - -
-
-
- - - -
-
-
-
- - - diff --git a/lib/vector.ex b/lib/vector.ex index 59078fc..b04d250 100644 --- a/lib/vector.ex +++ b/lib/vector.ex @@ -5,6 +5,7 @@ defmodule Vector do are represented as tuples with either two or three elements. ## Examples + iex> # Vector Tripple Product Identity ...> a = {2, 3, 1} ...> b = {1, 4, -2} @@ -19,16 +20,19 @@ defmodule Vector do @type location :: {number, number} | {number, number, number} @doc ~S""" - Returns the cross product of two vectors *A*⨯*B* + Returns the cross product of two vectors *A*⨯*B*. ## Examples iex> Vector.cross({2, 3}, {1, 4}) {0, 0, 5} + iex> Vector.cross({2, 2, -1}, {1, 4, 2}) {8, -5, 6} + iex> Vector.cross({3, -3, 1}, {4, 9, 2}) {-15, -2, 39} + """ @spec cross(vector, vector) :: vector def cross({x1, y1}, {x2, y2}), do: {0, 0, x1 * y2 - y1 * x2} @@ -41,18 +45,22 @@ defmodule Vector do end @doc ~S""" - Returns the norm (magnitude) of the cross product of two vectors *A*⨯*B* + Returns the norm (magnitude) of the cross product of two vectors *A*⨯*B*. ## Examples iex> Vector.cross_norm({2, 3}, {1, 4}) 5 + iex> Vector.cross_norm({1, 4}, {2, 2}) 6 + iex> Vector.cross_norm({2, 0, -1}, {0, 3, 3}) 9.0 + iex> Float.floor(:math.pow(Vector.cross_norm({2, 2, -1}, {1, 4, 2}), 2)) 125.0 + """ @spec cross_norm(vector, vector) :: number def cross_norm({x1, y1}, {x2, y2}), do: cross_norm({x1, y1, 0}, {x2, y2, 0}) @@ -61,16 +69,19 @@ defmodule Vector do end @doc ~S""" - Returns the dot product of two vectors *A*⨯*B* + Returns the dot product of two vectors *A*⨯*B*. ## Examples iex> Vector.dot({2, 3}, {1, 4}) 14 + iex> Vector.dot({1, 4}, {2, 2}) 10 + iex> Vector.dot({2, 0, -1}, {0, 3, 3}) -3 + """ @spec dot(vector, vector) :: number def dot({x1, y1}, {x2, y2}), do: dot({x1, y1, 0}, {x2, y2, 0}) @@ -81,16 +92,19 @@ defmodule Vector do end @doc ~S""" - Returns the norm (magnitude) of a vector + Returns the norm (magnitude) of a vector. ## Examples iex> Vector.norm({3, 4}) 5.0 + iex> Vector.norm({-1, 0}) 1 + iex> Vector.norm({0, -2, 0}) 2 + """ @spec norm(vector) :: number def norm({x, y}), do: norm({x, y, 0}) @@ -100,18 +114,22 @@ defmodule Vector do def norm({x, y, z}), do: :math.sqrt(norm_squared({x, y, z})) @doc ~S""" - Returns the square of the norm norm (magnitude) of a vector + Returns the square of the norm norm (magnitude) of a vector. ## Examples iex> Vector.norm_squared({3, 4}) 25 + iex> Vector.norm_squared({1, 0}) 1 + iex> Vector.norm_squared({2, 0, -1}) 5 + iex> Vector.norm_squared({-2, 3, 1}) 14 + """ @spec norm_squared(vector) :: number def norm_squared({x, y}), do: norm_squared({x, y, 0}) @@ -120,8 +138,10 @@ defmodule Vector do end @doc ~S""" - Returns the unit vector parallel ot the given vector. + Returns the unit vector parallel to the given vector. + This will raise an `ArithmeticError` if a zero-magnitude vector is given. + Use `unit_safe` if there is a chance that a zero-magnitude vector will be sent. @@ -129,12 +149,16 @@ defmodule Vector do iex> Vector.unit({3, 4}) {0.6, 0.8} + iex> Vector.unit({8, 0, 6}) {0.8, 0.0, 0.6} + iex> Vector.unit({-2, 0, 0}) {-1.0, 0.0, 0.0} + iex> Vector.unit({0, 0, 0}) ** (ArithmeticError) bad argument in arithmetic expression + """ @spec unit(vector) :: vector def unit({x, 0, 0}), do: {x / abs(x), 0.0, 0.0} @@ -143,17 +167,20 @@ defmodule Vector do def unit(v), do: divide(v, norm(v)) @doc ~S""" - Returns the unit vector parallel ot the given vector, but will handle - the vectors `{0, 0}` and `{0, 0, 0}` by returning the same vector + Returns the unit vector parallel to the given vector, but will handle + the vectors `{0, 0}` and `{0, 0, 0}` by returning the same vector. ## Examples iex> Vector.unit_safe({3, 4}) {0.6, 0.8} + iex> Vector.unit_safe({0, 0}) {0, 0} + iex> Vector.unit_safe({0, 0, 0}) {0, 0, 0} + """ @spec unit_safe(vector) :: vector def unit_safe({0, 0}), do: {0, 0} @@ -161,32 +188,38 @@ defmodule Vector do def unit_safe(v), do: unit(v) @doc ~S""" - Reverses a vector + Reverses a vector. ## Examples iex> Vector.reverse({3, -4}) {-3, 4} + iex> Vector.reverse({-2, 0, 5}) {2, 0, -5} + iex> Vector.cross_norm({-2, 3, 5}, Vector.reverse({-2, 3, 5})) 0 + """ @spec reverse(vector) :: vector def reverse({x, y}), do: {-x, -y} def reverse({x, y, z}), do: {-x, -y, -z} @doc ~S""" - Adds two vectors + Adds two vectors. ## Examples iex> Vector.add({3, -4}, {2, 1}) {5,-3} + iex> Vector.add({-2, 0, 5}, {0, 0, 0}) {-2, 0, 5} + iex> Vector.add({2, 1, -2}, Vector.reverse({2, 1, -2})) {0, 0, 0} + """ @spec add(vector, vector) :: vector def add({x1, y1}, {x2, y2}), do: {x1 + x2, y1 + y2} @@ -195,41 +228,47 @@ defmodule Vector do def add({x1, y1, z1}, {x2, y2, z2}), do: {x1 + x2, y1 + y2, z1 + z2} @doc ~S""" - Subtract vector *B* from vector *A*. Equivalent to `Vector.add(A, Vector.revers(B))` + Subtract vector *B* from vector *A*. Equivalent to `Vector.add(A, Vector.revers(B))`. ## Examples iex> Vector.subtract({3, -4}, {2, 1}) {1,-5} + iex> Vector.subtract({-2, 0, 5}, {-3, 1, 2}) {1, -1, 3} + """ @spec subtract(vector, vector) :: vector def subtract(a, b), do: add(a, reverse(b)) @doc ~S""" - Multiply a vector by scalar value `s` + Multiply a vector by scalar value `s`. ## Examples iex> Vector.multiply({3, -4}, 2.5) {7.5, -10.0} + iex> Vector.multiply({-2, 0, 5}, -2) {4, 0, -10} + """ @spec multiply(vector, number) :: vector def multiply({x, y}, s), do: {x * s, y * s} def multiply({x, y, z}, s), do: {x * s, y * s, z * s} @doc ~S""" - Divide a vector by scalar value `s` + Divide a vector by scalar value `s`. ## Examples iex> Vector.divide({3, -4}, 2.5) {1.2, -1.6} + iex> Vector.divide({-2, 0, 5}, -2) {1.0, 0.0, -2.5} + """ @spec divide(vector, number) :: vector def divide({x, y}, s), do: {x / s, y / s} @@ -237,16 +276,19 @@ defmodule Vector do @doc ~S""" Returns a new coordinate by projecting a given length `distance` from - coordinate `start` along `vector` + coordinate `start` along `vector`. ## Examples iex> Vector.project({3, -4}, {-1, 1}, 4) {1.4, -2.2} + iex> Vector.project({-6, 0, 8}, {1, -2, 0.4}, 2.5) {-0.5, -2.0, 2.4} + iex> Vector.project({-2, 1, 3}, {0, 0, 0}, 2.5) |> Vector.norm() 2.5 + """ @spec project(vector, location, number) :: location def project(vector, start, distance) do @@ -257,18 +299,22 @@ defmodule Vector do end @doc ~S""" - Compares two vectors for equality, with an optional tolerance + Compares two vectors for equality, with an optional tolerance. ## Examples iex> Vector.equal?({3, -4}, {3, -4}) true + iex> Vector.equal?({3, -4}, {3.0001, -3.9999}) false + iex> Vector.equal?({3, -4}, {3.0001, -3.9999}, 0.001) true + iex> Vector.equal?({3, -4, 1}, {3.0001, -3.9999, 1.0}, 0.001) true + """ @spec equal?(vector, vector, number) :: boolean def equal?(a, b, tolerance \\ 0.0) do @@ -276,18 +322,22 @@ defmodule Vector do end @doc ~S""" - Returns the scalar component for the axis given + Returns the scalar component for the axis given. ## Examples iex> Vector.component({3, -4}, :y) -4 + iex> Vector.component({-6, 0, 8}, :z) 8 + iex> Vector.component({1, -2}, :z) 0 + iex> Vector.component(Vector.basis(:x), :z) 0 + """ @spec component(vector, atom) :: number def component({x, _}, :x), do: x @@ -298,16 +348,19 @@ defmodule Vector do def component({_, _, z}, :z), do: z @doc ~S""" - Returns the basis vector for the given axis + Returns the basis vector for the given axis. ## Examples iex> Vector.basis(:x) {1, 0, 0} + iex> Vector.basis(:y) {0, 1, 0} + iex> Vector.component(Vector.basis(:y), :y) 1 + """ @spec basis(atom) :: vector def basis(:x), do: {1, 0, 0} diff --git a/mix.exs b/mix.exs index 228376b..0d99dba 100644 --- a/mix.exs +++ b/mix.exs @@ -1,31 +1,34 @@ defmodule Vector.Mixfile do use Mix.Project + @source_url "https://github.com/pkinney/vector_ex" + @version "1.0.1" + def project do - [app: :vector, - version: "1.0.1", - elixir: "~> 1.2", - description: description(), - package: package(), - build_embedded: Mix.env == :prod, - start_permanent: Mix.env == :prod, - test_coverage: [tool: ExCoveralls], - preferred_cli_env: [coveralls: :test], - dialyzer: [plt_add_apps: [:poison, :mix]], - deps: deps()] + [ + app: :vector, + version: @version, + elixir: "~> 1.2", + build_embedded: Mix.env() == :prod, + start_permanent: Mix.env() == :prod, + test_coverage: [tool: ExCoveralls], + preferred_cli_env: [coveralls: :test], + dialyzer: [plt_add_apps: [:poison, :mix]], + package: package(), + deps: deps(), + docs: docs() + ] end - # Configuration for the OTP application - # - # Type "mix help compile.app" for more information def application do - [applications: [:logger]] + [ + applications: [:logger] + ] end defp deps do [ - {:earmark, "~> 1.0", only: :dev}, - {:ex_doc, "~> 0.18", only: :dev}, + {:ex_doc, ">= 0.0.0", only: :dev, runtime: false}, {:benchfella, "~> 0.3", only: :dev}, {:excoveralls, "~> 0.4", only: :test}, {:dialyxir, "~> 0.4", only: [:dev], runtime: false}, @@ -33,19 +36,30 @@ defmodule Vector.Mixfile do ] end - defp description do - """ - Library of common vector functions for use in geometric or graphical calculations. - """ - end - defp package do [ + description: + "Library of common vector functions for use in geometric or graphical calculations.", files: ["lib", "mix.exs", "README*"], maintainers: ["Powell Kinney"], licenses: ["MIT"], - links: %{ "GitHub" => "https://github.com/pkinney/vector_ex", - "Docs" => "https://hexdocs.pm/vector/Vector.html"} + links: %{ + "GitHub" => @source_url, + "Docs" => "https://hexdocs.pm/vector/Vector.html" + } + ] + end + + defp docs do + [ + extras: [ + "LICENSE.md": [title: "License"], + "README.md": [title: "Overview"] + ], + main: "readme", + source_url: @source_url, + api_reference: false, + formatters: ["html"] ] end end diff --git a/mix.lock b/mix.lock index 8800ed7..f545360 100644 --- a/mix.lock +++ b/mix.lock @@ -1,21 +1,23 @@ %{ - "benchfella": {:hex, :benchfella, "0.3.5", "b2122c234117b3f91ed7b43b6e915e19e1ab216971154acd0a80ce0e9b8c05f5", [:mix], []}, - "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], []}, - "certifi": {:hex, :certifi, "2.0.0", "a0c0e475107135f76b8c1d5bc7efb33cd3815cb3cf3dea7aefdd174dabead064", [:rebar3], []}, - "credo": {:hex, :credo, "0.8.6", "335f723772d35da499b5ebfdaf6b426bfb73590b6fcbc8908d476b75f8cbca3f", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, optional: false]}]}, - "dialyxir": {:hex, :dialyxir, "0.5.1", "b331b091720fd93e878137add264bac4f644e1ddae07a70bf7062c7862c4b952", [:mix], []}, - "earmark": {:hex, :earmark, "1.3.1", "73812f447f7a42358d3ba79283cfa3075a7580a3a2ed457616d6517ac3738cb9", [:mix], [], "hexpm"}, - "ex_doc": {:hex, :ex_doc, "0.19.3", "3c7b0f02851f5fc13b040e8e925051452e41248f685e40250d7e40b07b9f8c10", [:mix], [{:earmark, "~> 1.2", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.10", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"}, - "excoveralls": {:hex, :excoveralls, "0.7.2", "f69ede8c122ccd3b60afc775348a53fc8c39fe4278aee2f538f0d81cc5e7ff3a", [:mix], [{:exjsx, ">= 3.0.0", [hex: :exjsx, optional: false]}, {:hackney, ">= 0.12.0", [hex: :hackney, optional: false]}]}, - "exjsx": {:hex, :exjsx, "4.0.0", "60548841e0212df401e38e63c0078ec57b33e7ea49b032c796ccad8cde794b5c", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, optional: false]}]}, - "hackney": {:hex, :hackney, "1.9.0", "51c506afc0a365868469dcfc79a9d0b94d896ec741cfd5bd338f49a5ec515bfe", [:rebar3], [{:certifi, "2.0.0", [hex: :certifi, optional: false]}, {:idna, "5.1.0", [hex: :idna, optional: false]}, {:metrics, "1.0.1", [hex: :metrics, optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, optional: false]}]}, - "idna": {:hex, :idna, "5.1.0", "d72b4effeb324ad5da3cab1767cb16b17939004e789d8c0ad5b70f3cea20c89a", [:rebar3], [{:unicode_util_compat, "0.3.1", [hex: :unicode_util_compat, optional: false]}]}, - "jsx": {:hex, :jsx, "2.8.2", "7acc7d785b5abe8a6e9adbde926a24e481f29956dd8b4df49e3e4e7bcc92a018", [:mix, :rebar3], []}, - "makeup": {:hex, :makeup, "0.8.0", "9cf32aea71c7fe0a4b2e9246c2c4978f9070257e5c9ce6d4a28ec450a839b55f", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"}, - "makeup_elixir": {:hex, :makeup_elixir, "0.13.0", "be7a477997dcac2e48a9d695ec730b2d22418292675c75aa2d34ba0909dcdeda", [:mix], [{:makeup, "~> 0.8", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm"}, - "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], []}, - "mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], []}, - "nimble_parsec": {:hex, :nimble_parsec, "0.5.0", "90e2eca3d0266e5c53f8fbe0079694740b9c91b6747f2b7e3c5d21966bba8300", [:mix], [], "hexpm"}, - "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], []}, - "unicode_util_compat": {:hex, :unicode_util_compat, "0.3.1", "a1f612a7b512638634a603c8f401892afbf99b8ce93a45041f8aaca99cadb85e", [:rebar3], []}, + "benchfella": {:hex, :benchfella, "0.3.5", "b2122c234117b3f91ed7b43b6e915e19e1ab216971154acd0a80ce0e9b8c05f5", [:mix], [], "hexpm", "23f27cbc482cbac03fc8926441eb60a5e111759c17642bac005c3225f5eb809d"}, + "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"}, + "certifi": {:hex, :certifi, "2.0.0", "a0c0e475107135f76b8c1d5bc7efb33cd3815cb3cf3dea7aefdd174dabead064", [:rebar3], [], "hexpm", "fdc6066ceeccb3aa14049ab6edf0b9af3b64ae1b0db2a92d5c52146f373bbb1c"}, + "credo": {:hex, :credo, "0.8.6", "335f723772d35da499b5ebfdaf6b426bfb73590b6fcbc8908d476b75f8cbca3f", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}], "hexpm", "14dde2b851709115a578e43158c13ad97724eceb70320c51784952b88ee64814"}, + "dialyxir": {:hex, :dialyxir, "0.5.1", "b331b091720fd93e878137add264bac4f644e1ddae07a70bf7062c7862c4b952", [:mix], [], "hexpm", "6c32a70ed5d452c6650916555b1f96c79af5fc4bf286997f8b15f213de786f73"}, + "earmark": {:hex, :earmark, "1.3.1", "73812f447f7a42358d3ba79283cfa3075a7580a3a2ed457616d6517ac3738cb9", [:mix], [], "hexpm", "000aaeff08919e95e7aea13e4af7b2b9734577b3e6a7c50ee31ee88cab6ec4fb"}, + "earmark_parser": {:hex, :earmark_parser, "1.4.13", "0c98163e7d04a15feb62000e1a891489feb29f3d10cb57d4f845c405852bbef8", [:mix], [], "hexpm", "d602c26af3a0af43d2f2645613f65841657ad6efc9f0e361c3b6c06b578214ba"}, + "ex_doc": {:hex, :ex_doc, "0.24.2", "e4c26603830c1a2286dae45f4412a4d1980e1e89dc779fcd0181ed1d5a05c8d9", [:mix], [{:earmark_parser, "~> 1.4.0", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "e134e1d9e821b8d9e4244687fb2ace58d479b67b282de5158333b0d57c6fb7da"}, + "excoveralls": {:hex, :excoveralls, "0.7.2", "f69ede8c122ccd3b60afc775348a53fc8c39fe4278aee2f538f0d81cc5e7ff3a", [:mix], [{:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: false]}, {:hackney, ">= 0.12.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "ef8fc1c6014b16a68dccfba3513aa41283d731eeaf8a1b704bbb072cb1ab89cb"}, + "exjsx": {:hex, :exjsx, "4.0.0", "60548841e0212df401e38e63c0078ec57b33e7ea49b032c796ccad8cde794b5c", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, repo: "hexpm", optional: false]}], "hexpm", "32e95820a97cffea67830e91514a2ad53b888850442d6d395f53a1ac60c82e07"}, + "hackney": {:hex, :hackney, "1.9.0", "51c506afc0a365868469dcfc79a9d0b94d896ec741cfd5bd338f49a5ec515bfe", [:rebar3], [{:certifi, "2.0.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "5.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm", "e38f4a7937b6dfc5fa87403ece26b1826bc81838f09ac57fabf2f7a9885fe818"}, + "idna": {:hex, :idna, "5.1.0", "d72b4effeb324ad5da3cab1767cb16b17939004e789d8c0ad5b70f3cea20c89a", [:rebar3], [{:unicode_util_compat, "0.3.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "fc1a2f7340c422650504b1662f28fdf381f34cbd30664e8491744e52c9511d40"}, + "jsx": {:hex, :jsx, "2.8.2", "7acc7d785b5abe8a6e9adbde926a24e481f29956dd8b4df49e3e4e7bcc92a018", [:mix, :rebar3], [], "hexpm", "b4c5d3230b397c8d95579e4a3d72826bb6463160130ccf4182f5be8579b5f44c"}, + "makeup": {:hex, :makeup, "1.0.5", "d5a830bc42c9800ce07dd97fa94669dfb93d3bf5fcf6ea7a0c67b2e0e4a7f26c", [:mix], [{:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cfa158c02d3f5c0c665d0af11512fed3fba0144cf1aadee0f2ce17747fba2ca9"}, + "makeup_elixir": {:hex, :makeup_elixir, "0.15.1", "b5888c880d17d1cc3e598f05cdb5b5a91b7b17ac4eaf5f297cb697663a1094dd", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.1", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "db68c173234b07ab2a07f645a5acdc117b9f99d69ebf521821d89690ae6c6ec8"}, + "makeup_erlang": {:hex, :makeup_erlang, "0.1.1", "3fcb7f09eb9d98dc4d208f49cc955a34218fc41ff6b84df7c75b3e6e533cc65f", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "174d0809e98a4ef0b3309256cbf97101c6ec01c4ab0b23e926a9e17df2077cbb"}, + "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"}, + "mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], [], "hexpm", "7a4c8e1115a2732a67d7624e28cf6c9f30c66711a9e92928e745c255887ba465"}, + "nimble_parsec": {:hex, :nimble_parsec, "1.1.0", "3a6fca1550363552e54c216debb6a9e95bd8d32348938e13de5eda962c0d7f89", [:mix], [], "hexpm", "08eb32d66b706e913ff748f11694b17981c0b04a33ef470e33e11b3d3ac8f54b"}, + "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], [], "hexpm", "4f8805eb5c8a939cf2359367cb651a3180b27dfb48444846be2613d79355d65e"}, + "unicode_util_compat": {:hex, :unicode_util_compat, "0.3.1", "a1f612a7b512638634a603c8f401892afbf99b8ce93a45041f8aaca99cadb85e", [:rebar3], [], "hexpm", "da1d9bef8a092cc7e1e51f1298037a5ddfb0f657fe862dfe7ba4c5807b551c29"}, }