Primitive root of a number - matlab

I have tried to implement the algorithm described in here to find primitive roots for a prime number.
It works for small prime numbers, however as I try big numbers, it doesn't return correct answers anymore.
I then notice that a^(p-1)/pi tends to be a big number, it returns inf in MATLAB, so I thought factorizing (p-1) could help, but I am failing to see how.
I wrote a small piece of code in MATLABand here it is.
clear all
clc
%works with prime =23,31,37,etc.
prime=761; %doesn't work for this value
F=factor(prime-1); % the factors of prime-1
for i = 2: prime-1
a=i;
tag =1;
for j= 1 :prime-1
if (isprime(j))
p_i = j;
if(mod(a^((prime-1)/p_i),prime)== 1)
tag=0;
break
else
tag = tag +1;
end
end
end
if (tag > 1 )
a %it should only print the primitive root
break
end
end
Any input is welcome.
Thanks

What Matlab does in this case is it calculates a^((p-1)/p) before taking the modulus. As a^((p-1)/p) quite quickly becomes too large to handle, Matlab seems to resolve this by turning it into a floating point number, losing some resolution and yielding the wrong result when you take the modulus.
As mentioned by #rayreng, you could use an arbitrary precision toolbox to resolve this.
Alternatively, you could split the exponentiation into parts, taking the modulus at each stage. This should be faster, as it is less memory intensive. You could dump this in a function and just call that.
% Calculates a^b mod c
i = 0;
result = 1;
while i < b
result = mod(result*a, c);
i = i + 1;
end

Related

Simulating the exponential function with pertubation

for some simulations, I need to make use of an approximation of the exponential function. Now, the problem that I have is that:
function s=expone(N,k)
s=0
for j=1:k
s=s+(exp(-N+j*log(N)-log(factorial(j))));
end
end
is a pretty stable, in the sense that it is almost 1 for k large enough. However, as soon as N is bigger than 200, it quickly drops to zero. How can I improve that, I need large N. I cannot really change the mathematical why of writing this, since I have an additional pertubation, my final code will look something lie:
function s=expone(N,k)
s=0
for j=1:k
s=s+(exp(-N+j*log(N)-log(factorial(j))))*pertubation(N,k);
end
end
THe pertubation is between 0 and 1, so that's no problem, but the prefactor seems not to work for N>200. Can anyone help?
Thanks a lot!
The function log(x) - x has positive and negative part
Graphic in Wolframalpha
while x - log(x!) is negative for x>= 0
Graphic in Wolframalpha
So the problem arise when (N - log(N) ) is much greater than (j - log(j) ). So the solution is to choose a j much bigger than N . Exp(negative) tends to zero
for example expone(20,1) = 7.1907e-05 but expone(20,20) = 0.5591 and expone (20,50) = 1.000
As conclusion, if you want to work with N big, j should be bigger, and as an extra tip you may want to change you function to avoid for loops:
function s = expone(N,k)
j = 1:k;
s = sum ((exp(-N+j*log(N)-log(factorial(j)))));
end

Basic structure of a for loop

I am trying to write a MATLAB function that accepts non-integer, n, and then returns the factorial of it, n!. I am supposed to use a for loop. I tried with
"for n >= 0"
but this did not work. Is there a way how I can fix this?
I wrote this code over here but this doesn't give me the correct answer..
function fact = fac(n);
for fact = n
if n >=0
factorial(n)
disp(n)
elseif n < 0
disp('Cannot take negative integers')
break
end
end
Any kind of help will be highly appreciated.
You need to read the docs and I would highly recommend doing a basic tutorial. The docs state
for index = values
statements
end
So your first idea of for n >= 0 is completely wrong because a for doesn't allow for the >. That would be the way you would write a while loop.
Your next idea of for fact = n does fit the pattern of for index = values, however, your values is a single number, n, and so this loop will only have one single iteration which is obviously not what you want.
If you wanted to loop from 1 to n you need to create a vector, (i.e. the values from the docs) that contains all the numbers from 1 to n. In MATLAB you can do this easily like this: values = 1:n. Now you can call for fact = values and you will iterate all the way from 1 to n. However, it is very strange practice to use this intermediary variable values, I was just using it to illustrate what the docs are talking about. The correct standard syntax is
for fact = 1:n
Now, for a factorial (although technically you'll get the same thing), it is clearer to actually loop from n down to 1. So we can do that by declaring a step size of -1:
for fact = n:-1:1
So now we can find the factorial like so:
function output = fac(n)
output = n;
for iter = n-1:-1:2 %// note there is really no need to go to 1 since multiplying by 1 doesn't change the value. Also start at n-1 since we initialized output to be n already
output = output*iter;
end
end
Calling the builtin factorial function inside your own function really defeats the purpose of this exercise. Lastly I see that you have added a little error check to make sure you don't get negative numbers, that is good however the check should not be inside the loop!
function output = fac(n)
if n < 0
error('Input n must be greater than zero'); %// I use error rather than disp here as it gives clearer feedback to the user
else if n == 0
output = 1; %// by definition
else
output = n;
for iter = n-1:-1:2
output = output*iter;
end
end
end
I don't get the point, what you are trying to do with "for". What I think, what you want to do is:
function fact = fac(n);
if n >= 0
n = floor(n);
fact = factorial(n);
disp(fact)
elseif n < 0
disp('Cannot take negative integers')
return
end
end
Depending on your preferences you can replace floor(round towards minus infinity) by round(round towards nearest integer) or ceil(round towards plus infinity). Any round operation is necessary to ensure n is an integer.

MATLAB Piecewise function

I have to construct the following function in MATLAB and am having trouble.
Consider the function s(t) defined for t in [0,4) by
{ sin(pi*t/2) , for t in [0,1)
s(t) = { -(t-2)^3 , for t in [1,3)*
{ sin(pi*t/2) , for t in [3,4)
(i) Generate a column vector s consisting of 512 uniform
samples of this function over the interval [0,4). (This
is best done by concatenating three vectors.)
I know it has to be something of the form.
N = 512;
s = sin(5*t/N).' ;
But I need s to be the piecewise function, can someone provide assistance with this?
If I understand correctly, you're trying to create 3 vectors which calculate the specific function outputs for all t, then take slices of each and concatenate them depending on the actual value of t. This is inefficient as you're initialising 3 times as many vectors as you actually want (memory), and also making 3 times as many calculations (CPU), most of which will just be thrown away. To top it off, it'll be a bit tricky to use concatenate if your t is ever not as you expect (i.e. monotonically increasing). It might be an unlikely situation, but better to be general.
Here are two alternatives, the first is imho the nice Matlab way, the second is the more conventional way (you might be more used to that if you're coming from C++ or something, I was for a long time).
function example()
t = linspace(0,4,513); % generate your time-trajectory
t = t(1:end-1); % exclude final value which is 4
tic
traj1 = myFunc(t);
toc
tic
traj2 = classicStyle(t);
toc
end
function trajectory = myFunc(t)
trajectory = zeros(size(t)); % since you know the size of your output, generate it at the beginning. More efficient than dynamically growing this.
% you could put an assert for t>0 and t<3, otherwise you could end up with 0s wherever t is outside your expected range
% find the indices for each piecewise segment you care about
idx1 = find(t<1);
idx2 = find(t>=1 & t<3);
idx3 = find(t>=3 & t<4);
% now calculate each entry apprioriately
trajectory(idx1) = sin(pi.*t(idx1)./2);
trajectory(idx2) = -(t(idx2)-2).^3;
trajectory(idx3) = sin(pi.*t(idx3)./2);
end
function trajectory = classicStyle(t)
trajectory = zeros(size(t));
% conventional way: loop over each t, and differentiate with if-else
% works, but a lot more code and ugly
for i=1:numel(t)
if t(i)<1
trajectory(i) = sin(pi*t(i)/2);
elseif t(i)>=1 & t(i)<3
trajectory(i) = -(t(i)-2)^3;
elseif t(i)>=3 & t(i)<4
trajectory(i) = sin(pi*t(i)/2);
else
error('t is beyond bounds!')
end
end
end
Note that when I tried it, the 'conventional way' is sometimes faster for the sampling size you're working on, although the first way (myFunc) is definitely faster as you scale up really a lot. In anycase I recommend the first approach, as it is much easier to read.

Wrong value while summing floats in matlab

while (tempsumf ~= sum)
iter = iter + 1;
tempsumf = tempsumf + fitness(iter, 1);
if (tempsumf > sel1)
break;
end
end
I have an array(fitness) of floats here (mostly with exponent -6/-5) which i am summing up in tempsumf ... now when the loop goes to the second iteration, i get the value 5.000 which is utterly wrong. I can figure out the issue.
This is probably due to floating point precision. You shouldn't do equality or inequality tests on double precision numbers. Instead of while (tempsumf ~= sum), use while (abs(tempsumf - sum))>1e-6) or whatever threshold you deem appropriate.
See the MATLAB wiki entry on this topic for more information.
Second possible cause of the error: you are overwriting the built-in function sum with your variable sum. Don't do that! Call your variable my_sum or something similar.

Nearest column in matlab

I want to find the nearest column of a matrix with a vector.
Consider the matrix is D and the vector is y. I want an acceleration method for this function
function BOOLEAN = IsExsist(D,y)
[~, Ysize, ~] = size(D);
BOOLEAN = 0;
MIN = 1.5;
for i=1:Ysize
if(BOOLEAN == 1)
break;
end;
if(norm(y - D(:,i),1) < MIN )
BOOLEAN = 1;
end;
end;
end
I am assuming you are looking to "accelerate" this procedure. For the same, try this -
[~,nearest_column_number] = min(sum(abs(bsxfun(#minus,D,y))))
The above code uses 1-Norm (as used by you) along all the columns of D w.r.t. y. nearest_column_number is your desired output.
If you are interested in using a threshold MIN for the getting the first nearest column number, you may use the following code -
normvals = sum(abs(bsxfun(#minus,D,y)))
nearest_column_number = find(normvals<MIN,1)
BOOLEAN = ~isempty(nearest_column_number)
nearest_column_number and BOOLEAN are the outputs you might be interested in.
If you are looking to make a function out of it, just wrap in the above code into the function format you were using, as you already have the desired output from the code.
Edit 1: If you are using this procedure for a case with large D matrices with sizes like 9x88800, use this -
normvals = sum(abs(bsxfun(#minus,D,y)));
BOOLEAN = false;
for k = 1:numel(normvals)
if normvals(k) < MIN
BOOLEAN = true;
break;
end
end
Edit 2: It appears that you are calling this procedure/function a lot of times, which is the bottleneck here. So, my suggestion at this point would be to look into your calling function and see if you could reduce the number of calls, otherwise use your own code or try this slight modified version of it -
BOOLEAN = false;
for k = 1:numel(y)
if norm(y - D(:,k),1) < MIN %// You can try replacing this with "if sum(abs(y - D(:,i),1)) < MIN" to see if it gives any performance improvement
BOOLEAN = true;
break;
end
end
To find the nearest column of a matrix D to a column vector y, with respect to 1-norm distance, you can use pdist2:
[~, index] = min(pdist2(y.',D.','minkowski',1));
What you are currently trying to do is optimize your Matlab implementation of linear search.
No matter how much you optimize that it will always need to calculate all D=88800 distances over all d=9 dimensions for each search.
Now that's easy to implement in Matlab as discussed in the other answer, but if you are planning to do many such searches, I would recommend to use a different data-structure and search-algorithm instead.
A good canditate would be (binary) space partioning which recursively splits your space into two parts along your dimensions. This adds quite some intial overhead to create the tree and makes insert- and remove-operations a bit more expensive. But as I understand your comments, searches are much more frequent and their execution will reduce in complexits from O(D) downto O(log(D)) which is a tremendous improvement for this problem size.
I think that there should be some usable Matlab-implementations of BSP around, e.g. on Mathworks file-exchange.
But if you don't manage to find one, I'd be happy to provide some pointers as well.