Reputation: 7188
I would like to write a function in MATLAB to determine whether an array contains at least one coprime pair. Formally, two integers n
and m
are co-prime if gcd(m,n)==1.
The function that I am building should input a vector x
, and return a true/false
value. This value will be true if x
contains two distinct elements n
,m
such that gcd(n,m)==1.
It should return false otherwise. Thus, we need it to behave as:
x = [1,2,3,4];
iscoprime(x)
> true
and
x = 2*[1,2,3,4];
iscoprime(x)
> false
My current best attempt at this is the following function.
function value = has_coprime_pair(x)
%take out zeros
x(x==0) = [];
%take absolute value
x = abs(x);
%make sure we have elements
if isempty(x)
value = true;
%make sure all elements are integers
elseif any(x~=floor(x))
value = false;
%check if any element = 1
elseif any(x==1)
value = true;
%check if any pair of elements is coprime
else
%get prime factors of all elements
prime_factors = arrayfun(@(x) factor(x), x, 'UniformOutput', false);
all_factors = unique(cell2mat(prime_factors));
%remove 1 from the list of all prime factors
all_factors(all_factors==1) = [];
%x does not contain coprime pair if each element has the same prime factor
value = true;
for f = all_factors
can_be_factored_by_f = cellfun(@(p) any(f==p),prime_factors,'UniformOutput',true);
if all(can_be_factored_by_f)
value = false;
break
end
end
end
end
Can anyone suggest a faster method?
Upvotes: 1
Views: 637
Reputation: 112749
I don't know if this is faster, but it's definitely simpler:
function result = has_coprime_pair(x)
for ii = 2:numel(x)
result = false;
if any(gcd(x(ii),x(1:ii-1)) > 1) %// test each pair of nunmbers only once
result = true;
break
end
end
Upvotes: 2
Reputation: 283733
If you're worried about correctness, you should know that your existing code fails for:
>> has_coprime_pair([6 10 15]) ans = 1
If speed is more important than correctness, you could just use
function value = has_coprime_pair(x)
value = true;
end
To directly implement your definition:
value = any(any(1 == bsxfun(@gcd, x, x')))
Not sure about the speed, but it has the virtue of being correct:
EDU>> has_coprime_pair([6 10 15]) ans = 0 EDU>> has_coprime_pair([1 2 3 4]) ans = 1 EDU>> has_coprime_pair(2*[1 2 3 4]) ans = 0
Upvotes: 2