OJ Reeves avatar OJ Reeves committed e5420c8

Initial commit. Basic vector library created with some tests.

Comments (0)

Files changed (6)

+syntax: glob
+*.beam
+.eunit
+*.swp
+~*
+{application, ert,
+ [
+  {description, ""},
+  {vsn, "1"},
+  {modules, [
+             ert_app,
+             ert_sup,
+             ert_vector
+            ]},
+  {registered, []},
+  {applications, [
+                  kernel,
+                  stdlib
+                 ]},
+  {mod, { ert_app, []}},
+  {env, []}
+ ]}.
+-module(ert_app).
+
+-behaviour(application).
+
+%% Application callbacks
+-export([start/2, stop/1]).
+
+%% ===================================================================
+%% Application callbacks
+%% ===================================================================
+
+start(_StartType, _StartArgs) ->
+    ert_sup:start_link().
+
+stop(_State) ->
+    ok.
+
+-module(ert_sup).
+
+-behaviour(supervisor).
+
+%% API
+-export([start_link/0]).
+
+%% Supervisor callbacks
+-export([init/1]).
+
+%% Helper macro for declaring children of supervisor
+-define(CHILD(I, Type), {I, {I, start_link, []}, permanent, 5000, Type, [I]}).
+
+%% ===================================================================
+%% API functions
+%% ===================================================================
+
+start_link() ->
+    supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
+%% ===================================================================
+%% Supervisor callbacks
+%% ===================================================================
+
+init([]) ->
+    {ok, { {one_for_one, 5, 10}, []} }.
+

src/ert_vector.erl

+%% @author OJ Reeves <oj@buffered.io>
+%% @copyright 2010 Oliver Reeves
+%% @doc Module that handles 3D vector functionality.
+
+-module(ert_vector).
+-author('OJ Reeves <oj@buffered.io>').
+
+-export([vec/3, vx/1, vy/1, vz/1]).
+-export([vlen/1, vlensq/1, vdist/2, vnorm/1]).
+-export([vadd/2, vsub/2, vmul/2, vdiv/2, vdot/2, vcross/2, vneg/1]).
+
+-ifdef(TEST).
+-compile(export_all).
+-endif.
+
+%% @spec vec(float, float, float) -> vector()
+%% @doc Creates a vector from the X, Y and Z components.
+vec(X, Y, Z) ->
+  {X, Y, Z}.
+
+%% @spec vx(vector()) -> float
+%% @doc Extracts the X component from a vector.
+vx({X, _Y, _Z}) ->
+  X.
+
+%% @spec vy(vector()) -> float
+%% @doc Extracts the Y component from a vector.
+vy({_X, Y, _Z}) ->
+  Y.
+
+%% @spec vz(vector()) -> float
+%% @doc Extracts the Z component from a vector.
+vz({_X, _Y, Z}) ->
+  Z.
+
+%% @spec vnorm(vector()) -> vector()
+%% @doc Normalises a vector.
+vnorm(V) ->
+  vmul(V, 1/vlen(V)).
+
+%% @spec vlensq(vector()) -> float
+%% @doc Gets the squared length of the vector.
+vlensq(V) ->
+  vdot(V, V).
+
+%% @spec vlen(vector()) -> float
+%% @doc Gets the actual length of the vector.
+vlen(V) ->
+  math:sqrt(vlensq(V)).
+
+%% @spec vadd(vector(), vector()) -> vector()
+%% @doc Adds two vector instances together.
+vadd({X1, Y1, Z1}, {X2, Y2, Z2}) ->
+  {X1 + X2, Y1 + Y2, Z1 + Z2};
+
+%% @spec vadd(vector(), float) -> vector()
+%% @doc Adds a scalar value to each vector component.
+vadd({X, Y, Z}, S) when is_float(S) ->
+  {X + S, Y + S, Z + S}.
+
+%% @spec vsub(vector(), vector()) -> vector()
+%% @doc Subtracts one vector from another.
+vsub({X1, Y1, Z1}, {X2, Y2, Z2}) ->
+  {X1 - X2, Y1 - Y2, Z1 - Z2};
+
+%% @spec vsub(vector(), float) -> vector()
+%% @doc Subtracts a scalar value from each vector component.
+vsub({X, Y, Z}, S) when is_float(S) ->
+  {X - S, Y - S, Z - S}.
+
+%% @spec vmul(vector(), vector()) -> vector()
+%% @doc Multiplies two vectors together. This is not the cross-product.
+vmul({X1, Y1, Z1}, {X2, Y2, Z2}) ->
+  {X1 * X2, Y1 * Y2, Z1 * Z2};
+
+%% @spec vmul(vector(), float) -> vector()
+%% @doc Multiplies each vector component by a scalar value.
+vmul({X, Y, Z}, S) when is_float(S) ->
+  {X * S, Y * S, Z * S}.
+
+%% @spec vdiv(vector(), vector()) -> vector()
+%% @doc Divides one vector by another.
+vdiv({X1, Y1, Z1}, {X2, Y2, Z2}) ->
+  {X1 / X2, Y1 / Y2, Z1 / Z2};
+
+%% @spec vdiv(vector(), float) -> vector()
+%% @doc Divides each vector component by a scalar value.
+vdiv({X, Y, Z}, S) when is_float(S) ->
+  {X / S, Y / S, Z / S}.
+
+%% @spec vdot(vector(), vector()) -> float
+%% @doc Calculates the dot product of two vectors.
+vdot({X1, Y1, Z1}, {X2, Y2, Z2}) ->
+  X1 * X2 + Y1 * Y2 + Z1 * Z2.
+
+%% @spec vcross(vector(), vector()) -> vector()
+vcross({X1, Y1, Z1}, {X2, Y2, Z2}) ->
+  { Y1 * Z2 - Z1 * Y2, Z1 * X2 - X1 * Z2, X1 * Y2 - Y1 * X2 }.
+
+%% @spec vdist(vector(), vector()) -> vector()
+%% @doc Calculates the magnitude of the distance between two vectors.
+vdist(V1, V2) ->
+  vlen(vsub(V2, V1)).
+
+%% @spec vneg(vector()) -> vector()
+%% @doc Negates all components of a vector.
+vneg({X, Y, Z}) ->
+  {-X, -Y, -Z}.
+

test/ert_vector_tests.erl

+-module(ert_vector_tests).
+-include_lib("eunit/include/eunit.hrl").
+
+-import(ert_vector, [vec/3, vx/1, vy/1, vz/1]).
+-import(ert_vector, [vlen/1, vlensq/1, vdist/2, vnorm/1]).
+-import(ert_vector, [vadd/2, vsub/2, vmul/2, vdiv/2, vdot/2, vcross/2, vneg/1]).
+
+v1() -> {10.0, -3.5, 22.33}.
+v2() -> {14.2, 5.0, 18.1}.
+
+are_equal(X, Y) -> 0.000001 >= abs(X - Y).
+
+vadd_test() ->
+  {X, Y, Z} = vadd(v1(), v2()),
+  ?assert(are_equal(X, 24.2)),
+  ?assert(are_equal(Y, 1.5)),
+  ?assert(are_equal(Z, 40.43)).
+
+vsub_test() ->
+  {X, Y, Z} = vsub(v1(), v2()),
+  ?assert(are_equal(X, -4.2)),
+  ?assert(are_equal(Y, -8.5)),
+  ?assert(are_equal(Z, 4.23)).
+
+vdot_test() ->
+  ?assert(are_equal(vdot(v1(), v2()), 528.673)).
+
+vneg_test() ->
+  ?assertEqual(vneg(v1()), {-10.0, 3.5, -22.33}).
+
+vdist_test() ->
+  ?assertEqual(vdist(v1(), v2()), 10.381854362299634).
+
+vlen_test() ->
+  ?assertEqual(1.0, vlen({1.0, 0.0, 0.0})),
+  ?assertEqual(1.0, vlen({0.0, 1.0, 0.0})),
+  ?assertEqual(1.0, vlen({0.0, 0.0, 1.0})).
+
+vlensq_test() ->
+  ?assertEqual(1.0, vlensq({1.0, 0.0, 0.0})),
+  ?assertEqual(1.0, vlensq({0.0, 1.0, 0.0})),
+  ?assertEqual(1.0, vlensq({0.0, 0.0, 1.0})).
+
+vnorm_test() ->
+  ?assert(are_equal(1.0, vlensq(vnorm(v1())))).
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.