%---------------------------------------------------------------------------%
% vim: ts=4 sw=4 et ft=mercury
%---------------------------------------------------------------------------%

:- module transpose_impl.

:- interface.

:- import_module list.

:- pred transpose(list(list(T)), list(list(T))).
:- mode transpose(in(matrix9), out) is nondet.
:- mode transpose(in, out) is nondet.

:- inst matrix9 == bound([list9, ground, ground]).
:- inst list9 == bound([ground, ground, ground, ground, ground, ground, ground,
    ground, ground]).

:- inst [A | B]
    --->    [A | B].
:- inst []
    --->    [].

:- implementation.

transpose(Xs, []) :-
    nullrows(Xs).
transpose(Xs, [Y | Ys]) :-
    makerow(Xs, Y, Zs),
    transpose(Zs, Ys).

:- pred makerow(list(list(T)), list(T), list(list(T))).
:- mode makerow(in, out, out) is semidet.
:- mode makerow(in(matrix9), out, out) is semidet.

makerow([], [], []).
makerow([[X | Xs] | Ys], [X | Xs1], [Xs | Zs]) :-
    makerow(Ys, Xs1, Zs).

:- pred nullrows(list(list(T))).
:- mode nullrows(in) is semidet.
:- mode nullrows(in(list9)) is semidet.

nullrows([]).
nullrows([[] | Ns]) :-
    nullrows(Ns).
