Suppose we have a FORTRAN subroutine that multiplies a 3-element vector by a 3-by-3 matrix, returning a 3-element vector. This situation is then represented by the following code:
C code
typedef double vec_3[3];
typedef double mat_3_3[3][3];
vec_3 *make_vec(a, b, c)
double a, b, c;
{
register vec_3 *x;
x = (vec_3*)malloc(sizeof(vec_3));
(*x)[0] = a, (*x)[1] = b, (*x)[2] = c;
return x;
}
mat_3_3 *make_mat(a0, a1, a2, b0, b1, b2, c0, c1, c2)
double a0, a1, a2, b0, b1, b2, c0, c1, c2;
{
register mat_3_3 *x;
x = (mat_3_3*)malloc(sizeof(mat_3_3));
(*x)[0][0] = a0, (*x)[0][1] = a1, (*x)[0][2] = a2,
(*x)[1][0] = b0, (*x)[1][1] = b1, (*x)[1][2] = b2,
(*x)[2][0] = c0, (*x)[2][1] = c1, (*x)[2][2] = c2;
return x;
}
FORTRAN code
subroutine matvec(mat, vec, ans)
real mat(3,3), vec(3), ans(3)
ans(1) = mat(1,1)*vec(1)+mat(2,1)*vec(2)+mat(3,1)*vec(3)
ans(2) = mat(1,2)*vec(2)+mat(2,2)*vec(2)+mat(3,2)*vec(3)
ans(3) = mat(1,3)*vec(3)+mat(2,3)*vec(2)+mat(3,3)*vec(3)
return
end
Prolog Code:
foreign(make_vec, c, make_vec(+float,+float,+float,
[-address(vec_3)])).
foreign(make_mat, c, make_mat(+float,+float,+float,
+float,+float,+float,
+float,+float,+float,
[-address(mat_3_3)])).
foreign(matvec_, fortran, matvec(+address(float),+address(float),
+address(float))). % note all +!
make_vec([A,B,C], X) :-
make_vec(A, B, C, X).
make_mat([[A0,A1,A2],[B0,B1,B2],[C0,C1,C2]], X) :-
make_mat(A0,A1,A2, B0,B1,B2, C0,C1,C2, X).
do_matvec(Vec, Mat, AnsObj) :-
make_vec(Vec, VecObj),
make_mat(Mat, MatObj),
make_vec(0.0, 0.0, 0.0, AnsObj),
matvec(VecObj, MatObj, AnsObj).