Since you don't like loops, what about recursive functions?
iif = @(varargin) varargin{2 * find([varargin{1:2:end}], 1, 'first')}(); gcdrec=@ (v,gcdr) iif(length(v)==1,v, ... v(1)==1,1, ... length(v)==2,@()gcd(v(1),v(2)), ... true,@()gcdr([gcd(v(1),v(2)),v(3:end)],gcdr)); mygcd=@ (v)gcdrec(v(:)',gcdrec); A=[0,0,0; 2,4,2;-2,0,8]; divisor=mygcd(A); A=A/divisor;
The first iif function will define an inline conditional construct. This allows you to define the gcdrec recursive function to find the largest common divisor of your array. This iif works as follows: it checks if the first argument is true , if it is, then it returns the second argument. Otherwise, it checks the third argument, and if it is true , then it returns the fourth, etc. You need to protect recursive functions, and sometimes other quantities appearing inside it, with @() , otherwise you may get errors.
Using iif , the recursive gcdrec function works as follows:
- if the input vector is a scalar, it returns it
- else, if the first component of the vector is 1, there is no way to restore, so it returns 1 (allows you to quickly return large matrices)
- else, if the input vector is 2, it returns the greatest common factor through
gcd - else he calls himself an abbreviated vector in which the first two elements are replaced by their largest common divisor.
The mygcd function is just an interface for convenience.
It should be pretty fast, and I think that only the depth of the recursion can be a problem for very big problems. I did a quick time check to compare with the cyclic version of @Adriaan using A=randi(100,N,N)-50 , with N=100 , N=1000 and N=5000 and tic / toc .
N=100 :- looping 0.008 seconds
- recursive 0.002 seconds
N=1000 :- 0.46 second cycle
- recursive 0.04 seconds
N=5000 :- 11.8 seconds cycle
- recursive 0.6 seconds
Refresh . Interestingly, the only reason I did not exceed the recursion limit (500 by default) is because my data did not have a common divisor. By setting a random matrix and doubling it, it will lead to reaching the recursion limit already for N=100 . Therefore, for large matrices this will not work. Again, for small matrices, @Adriaan's solution is fine.
I also tried to rewrite it to half the input vector at each recursive step: this really solves the recursion restriction problem, but it is very slow (2 seconds for N=100 , 261 seconds for N=1000 ). Somewhere somewhere there may be a middle place where the size of the matrix is ββlarge (ish) and the execution time is not so bad, but I have not found it yet.