# Creating function with matrix argument

I am completely new to programming, so I apologize in advance for a stupid question.

I want to program an algorithm for computing invariant factors of a finitely generated abelian group, so in essence I want to feed the algorithm a matrix of relations and get the reduced form of this matrix.

I have compiled a cumbersome code which makes the first step of the procedure, namely it takes a matrix and produces a matrix, in which the upper-left element divides all the elements in first row and in a first columm:

M = {{120, 51, 72, 33}, {30, 15, 18, 9}, {60, 30, 36, 18}};
If[FreeQ[M, 0], ## &[], Print [First[Dimensions[M]]]];
L = SparseArray[M]["NonzeroPositions"];
i = First[First[L]];
j = Part[First[L], 2];
M2 = M;
M2[[{1, i}]] = M2[[{i, 1}]];
M2[[All, {1, j}]] = M2[[All, {j, 1}]];
If[M2[[1, 1]] > 0, ## &[],
M2 = M2*Normal[
SparseArray[{1 -> -1, i_ -> 1}, First[Dimensions[M2]]]]];
A = Table[0, {First[Dimensions[M2]] - 1}];

For[i = 2, i <= First[Dimensions[M2]], i++,
A[[i - 1]] = Boole[Divisible[M2[[i, 1]], M2[[1, 1]]]]];

While[A != Table[1, {First[Dimensions[M2]] - 1}],
For[i = 2, i <= First[Dimensions[M2]], i++,
If[Divisible[M2[[i, 1]], M2[[1, 1]]], ## &[],
M3 = M2*Normal[
SparseArray[{1 -> Quotient[M2[[i, 1]], M2[[1, 1]]]},
First[Dimensions[M2]]]] ; M3[[{1, i}]] = M3[[{i, 1}]];
M2 = M2 - M3; M2[[{1, i}]] = M2[[{i, 1}]]]];
For[i = 2, i <= First[Dimensions[M2]], i++,
A[[i - 1]] = Boole[Divisible[M2[[i, 1]], M2[[1, 1]]]]]];


So on the matrix M = {{120, 51, 72, 33}, {30, 15, 18, 9}, {60, 30, 36, 18}} it gives {{30, 15, 18, 9}, {120, 51, 72, 33}, {60, 30, 36, 18}}.

Now I want to iterate this procedure, so I want to feed an arbitrary matrix into this code as a function. I got stuck on this problem for several hours, so I hope you could help me solve this.

Put everything in a Module to localize your Symbols:

fn[m_?MatrixQ] :=
Module[{M = m, L, i, j, M2, M3, A},
If[FreeQ[M, 0], ## &[], Print[First[Dimensions[M]]]];
L = SparseArray[M]["NonzeroPositions"];
i = First[First[L]];
j = Part[First[L], 2];
M2 = M;
M2[[{1, i}]] = M2[[{i, 1}]];
M2[[All, {1, j}]] = M2[[All, {j, 1}]];
If[M2[[1, 1]] > 0, ## &[],
M2 = M2*Normal[SparseArray[{1 -> -1, i_ -> 1}, First[Dimensions[M2]]]]];
A = Table[0, {First[Dimensions[M2]] - 1}];
For[i = 2, i <= First[Dimensions[M2]], i++,
A[[i - 1]] = Boole[Divisible[M2[[i, 1]], M2[[1, 1]]]]];
While[A != Table[1, {First[Dimensions[M2]] - 1}],
For[i = 2, i <= First[Dimensions[M2]], i++,
If[Divisible[M2[[i, 1]], M2[[1, 1]]], ## &[],
M3 = M2*Normal[
SparseArray[{1 -> Quotient[M2[[i, 1]], M2[[1, 1]]]}, First[Dimensions[M2]]]];
M3[[{1, i}]] = M3[[{i, 1}]];
M2 = M2 - M3; M2[[{1, i}]] = M2[[{i, 1}]]]];
For[i = 2, i <= First[Dimensions[M2]], i++,
A[[i - 1]] = Boole[Divisible[M2[[i, 1]], M2[[1, 1]]]]]];
{A, M2}
]


Now:

fn[
{{120, 51, 72, 33}, {30, 15, 18, 9}, {60, 30, 36, 18}}
]

{{1, 1}, {{30, 15, 18, 9}, {120, 51, 72, 33}, {60, 30, 36, 18}}}


I didn't attempt to understand your operation; I assumed that you wanted both A and M2 for output.

A very crude way to do this would be:

func[mat_] := With[{M = mat},
If[FreeQ[M, 0], ## &[], Print[First[Dimensions[M]]]];
L = SparseArray[M]["NonzeroPositions"];
i = First[First[L]];
j = Part[First[L], 2];
M2 = M;
M2[[{1, i}]] = M2[[{i, 1}]];
M2[[All, {1, j}]] = M2[[All, {j, 1}]];
If[M2[[1, 1]] > 0, ## &[],
M2 = M2*Normal[
SparseArray[{1 -> -1, i_ -> 1}, First[Dimensions[M2]]]]];
A = Table[0, {First[Dimensions[M2]] - 1}];

For[i = 2, i <= First[Dimensions[M2]], i++,
A[[i - 1]] = Boole[Divisible[M2[[i, 1]], M2[[1, 1]]]]];

While[A != Table[1, {First[Dimensions[M2]] - 1}],
For[i = 2, i <= First[Dimensions[M2]], i++,
If[Divisible[M2[[i, 1]], M2[[1, 1]]], ## &[],
M3 = M2*Normal[
SparseArray[{1 -> Quotient[M2[[i, 1]], M2[[1, 1]]]},
First[Dimensions[M2]]]]; M3[[{1, i}]] = M3[[{i, 1}]];
M2 = M2 - M3; M2[[{1, i}]] = M2[[{i, 1}]]]];
For[i = 2, i <= First[Dimensions[M2]], i++,
A[[i - 1]] = Boole[Divisible[M2[[i, 1]], M2[[1, 1]]]]]];
M2]


so that:

func[{{120, 51, 72, 33}, {30, 15, 18, 9}, {60, 30, 36, 18}}]
(*{{30, 15, 18, 9}, {120, 51, 72, 33}, {60, 30, 36, 18}} *)


There is no attempt here to localize the variables (which can be done within a Module, for example) and you should consider reading the documentation and examples as you refactor your code.