I wrote some code to determine the nth Fibonacci number using the nice blog post given in the accepted answer to this question: Finding out nth fibonacci number for very large 'n'. I am doing this as a way of practising a more difficult recursion problem given on projecteuler but that is not really relevant. The method relies on changing the problem to a small linear algebra problem of the form
Fn = T^n F1
where F1 = (1 1)^t and Fn contains the nth and (n-1)th Fibonacci number. The term T^n can then be determined in O(log n) time. I implemented this succesfully and it seems to work fine. When I perform the matrix exponentiation I use %10000 so I get the last 4 digits only, which seems to work (I checked against some large Fibonacci numbers). However, I wanted to try to get more last digits by increasing the number 10000. This doesn't seem to work however. I no longer get the correct answer. Here is my code
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
const unsigned long M = 10000;
unsigned long int * matProd(unsigned long int * A, unsigned long int * B){
unsigned long int * C;
C = malloc(4*sizeof(unsigned long int));
C[0] = ((A[0]*B[0]%M) + (A[1]*B[2]%M)) % M;
C[1] = ((A[0]*B[1]%M) + (A[1]*B[3]%M)) % M;
C[2] = ((A[2]*B[0]%M) + (A[3]*B[2]%M)) % M;
C[3] = ((A[2]*B[1]%M) + (A[3]*B[3]%M)) % M;
return C;
}
unsigned long int * matExp(unsigned long int *A, unsigned long int n){
if (n==1){
return A;
}
if (n%2==0){
return matExp(matProd(A,A),n/2);
}
return matProd(A,matExp(A,n-1));
}
unsigned long int findFib(unsigned long int n){
unsigned long int A[4] = {0, 1, 1, 1};
unsigned long int * C;
C = malloc(4*sizeof(unsigned long int));
C = matExp(A,n-2);
return (C[2]+C[3]);
}
main(){
unsigned long int n = 300;
printf("%ld\n",findFib(n));
}
There are probably several issues there with regards to proper coding conventions and things that can be improved. I thought changing to long int might solve the problem but this does not seem to do the trick. So basically the problem is that increasing M to for instance 1000000 does not give me more digits but instead gives me nonsense. What mistake am I making?
P.S. sorry for the poor math formatting, I am used to math.stackexchange.