Files
mercury/benchmarks/progs/icfp2000_par/vector.m
Julien Fischer 05e16d889c Avoid potentially ambiguous pragmas in benchmarks.
benchmarks/*/*.m:
    As above.
2021-06-19 21:45:36 +10:00

139 lines
3.1 KiB
Mathematica

%---------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et
%---------------------------------------------------------------------------%
:- module vector.
% a 3D vector module.
:- interface.
:- import_module float, pair.
:- type real == float.
:- type vector ---> point(real, real, real).
:- type position == point.
:- type point == vector.
:- func '+'(vector, vector) = vector.
:- func '-'(vector, vector) = vector.
:- func '-'(vector) = vector.
:- func dot(vector, vector) = real.
% Dot product, but zeroed if not positive.
:- func positive_dot(vector, vector) = real.
:- func cross(vector, vector) = vector.
:- func mag(vector) = real.
% The square of the magnitude.
:- func mag2(vector) = real.
% The square of the distance between two points.
:- func distance_squared(point, point) = real.
:- func unit(vector) = vector.
:- func scale(real, vector) = vector.
:- func angle(vector, vector) = real.
% ProjectedV1 = project(V1, V2)
% Find the projection of V1 onto V2
:- func project(vector, vector) = vector.
% Project vector onto XY plane.
:- func projectXY(vector) = vector.
:- func projectXZ(vector) = vector.
:- func projectZY(vector) = vector.
% Return a pair containing the X and Y coords of the vector.
:- func xy(vector) = pair(real).
:- func xz(vector) = pair(real).
:- func zy(vector) = pair(real).
% Some useful constants.
:- func zero = vector.
:- func i = vector.
:- func j = vector.
:- func k = vector.
:- func real_epsilon = real.
:- func real_max = real.
:- implementation.
:- import_module math.
point(Ax, Ay, Az) + point(Bx, By, Bz) = point(Ax+Bx, Ay+By, Az+Bz).
point(Ax, Ay, Az) - point(Bx, By, Bz) = point(Ax-Bx, Ay-By, Az-Bz).
-point(X, Y, Z) = point(-X, -Y, -Z).
dot(point(Ax, Ay, Az), point(Bx, By, Bz)) = Ax*Bx + Ay*By + Az*Bz.
positive_dot(A, B) = PosDot :-
dot(A, B) = Dot,
( Dot < 0.0 ->
PosDot = 0.0
;
PosDot = Dot
).
cross(point(Ax, Ay, Az), point(Bx, By, Bz)) = point(Cx, Cy, Cz) :-
Cx = Ay*Bz - Az*By,
Cy = Az*Bx - Ax*Bz,
Cz = Ax*By - Ay*Bx.
mag(V) = math__sqrt(mag2(V)).
:- pragma inline(func(mag2/1)).
mag2(point(Ax, Ay, Az)) = Ax*Ax + Ay*Ay + Az*Az.
distance_squared(point(X1, Y1, Z1), point(X2, Y2, Z2)) = DistanceSquared :-
DX = X1 - X2,
DY = Y1 - Y2,
DZ = Z1 - Z2,
DistanceSquared = DX * DX + DY * DY + DZ * DZ.
:- pragma inline(func(unit/1)).
unit(point(Ax, Ay, Az)) = point(Ax/Mag, Ay/Mag, Az/Mag) :-
Mag = mag(point(Ax, Ay, Az)).
scale(S, point(Ax, Ay, Az)) = point(S*Ax, S*Ay, S*Az).
% calculate angle between 2 vectors
angle(V1, V2) = math__acos(dot(V1, V2) / mag(V1) / mag(V2)).
project(V1, V2) = Projection :-
UnitV2 = unit(V2),
Projection = scale(dot(V1, UnitV2), UnitV2).
projectXY(point(X, Y, _)) = point(X, Y, 0.0).
projectXZ(point(X, _, Z)) = point(X, 0.0, Z).
projectZY(point(_, Y, Z)) = point(0.0, Y, Z).
xy(point(X, Y, _)) = X - Y.
xz(point(X, _, Z)) = X - Z.
zy(point(_, Y, Z)) = Z - Y.
zero = point(0.0, 0.0, 0.0).
i = point(1.0, 0.0, 0.0).
j = point(0.0, 1.0, 0.0).
k = point(0.0, 0.0, 1.0).
real_epsilon = float__epsilon.
real_max = float__max.