I'm finishing up my header file for a Linear Congruential Generator (LCG) based cipher program. It receives two unsigned long values (m and c) and generates the LCG struct using these values. In my getA() I'm trying to have it add the temp variable to the uPrimes array (in case it cannot be reduced to 1, so it can be included when calculating p) but I keep receiving the error: "Floating point exception (core dumped)". It will run to completion, but does not perform as it needs to, if I do not try to do this. In this latest iteration I attempted to assign the first value of the uPrimes array as 1, and once the while loop finishes it assigns the value of temp to the first value, with the same result. Any help would be greatly appreciated! (I apologize ahead of time for the mismatched variable declarations, I was toying around with the data types haphazardly to try and solve the problem)
/* Header guard prevents errors if header is included twice */
#ifndef LCG_H
#define LCG_H
#include <stdlib.h>
struct LinearCongruentialGenerator
{
unsigned long m; /* modulus */
unsigned long c; /* increment */
unsigned long a; /* multiplier */
unsigned long x; /* value in sequence */
};
/***************************************************************/
/* Initialize an LCG with modulus m and increment c. */
/* Calculate multiplier a such that: */
/* a = 1+2p, if 4 is a factor of m, otherwise, a = 1+p. */
/* p = (product of m’s unique prime factors). */
/* a < m */
/* Seed value x is same as increment c. */
/* If values are invalid for LCG, set all fields to zero. */
/***************************************************************/
struct LinearCongruentialGenerator makeLCG(unsigned long m, unsigned long c);
/* Update lcg and return next value in the sequence. */
unsigned long getNextRandomValue(struct LinearCongruentialGenerator* lcg);
unsigned long getA(unsigned long m);
int checkInput(unsigned long m, unsigned long c);
struct LinearCongruentialGenerator makeLCG(unsigned long m, unsigned long c)
{
struct LinearCongruentialGenerator lcg;
if(checkInput(m,c) && (getA(m)<m && getA(m)>0))
{
lcg.m = m;
lcg.c = c;
lcg.a = getA(m);
lcg.x = c;
} else
{
lcg.m = 0; lcg.c = 0;
lcg.a = 0; lcg.x = 0;
}
return lcg;
}
unsigned long getNextRandomValue(struct LinearCongruentialGenerator* lcg)
{
lcg->x = ((lcg->a*lcg->x)+lcg->c)%lcg->m;
return lcg->x;
}
unsigned long getA(unsigned long m)
{
unsigned long primes[15] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47};
int uPrimes[63];
unsigned long temp = m; int y = 0; int p = 1;
int prev; int z; unsigned long a; int q = 1;
uPrimes[0] = 1;
while(y < 16)
{
if(temp % primes[y] == 0)
{
if(primes[y] != prev)
{
uPrimes[q] = primes[y];
prev = primes[y];
q++; y++;
printf("Unique Prime for %lu is: %d\n", m, uPrimes[q-1]);
} else temp = temp/primes[y];
} else y++;
}
uPrimes[0] = temp;
for(z = 0; z < q; z++)
{
p = p * uPrimes[z];
printf("P for %lu is %d\n", m, p);
}
if(m % 4 == 0){a = 1+(2*p);}
else a = 1+p;
if(a < m && a > 0){return a;}
else return 0;
}
int checkInput(unsigned long m, unsigned long c)
{
int x = 2;
if(c > m || c <= 0){return 0;}
else
{
while(x < c)
{
if(m % x == 0 && c % x == 0)
{return 0;}
else x++;
}
return 1;
}
}
#endif
This is the test file I've been given to verify my header file works as needed:
#include <stdio.h>
#include "lcg.h"
/* Print LCG values along with a message */
void printLCG(struct LinearCongruentialGenerator* lcg, char* msg)
{
printf("%s (m=%lu,a=%lu,c=%lu,x=%lu)\n", msg, lcg->m, lcg->a, lcg->c, lcg->x);
}
/* Print message and n values generated by the LCG */
void testValues(struct LinearCongruentialGenerator* lcg, char* msg, int n)
{
int i;
printf("%s\n", msg);
for(i = 0; i < n; ++i)
{
unsigned long x = getNextRandomValue(lcg);
printf("%lu\n", x);
}
}
/* Create and test a few LCGs */
int main()
{
struct LinearCongruentialGenerator lcg1 = makeLCG(126,25);
struct LinearCongruentialGenerator lcg2 = makeLCG(38875,1234);
struct LinearCongruentialGenerator lcg3 = makeLCG(4611686018427387904,961168601842738797);
/* Some error cases */
struct LinearCongruentialGenerator lcg4 = makeLCG(4,3);
struct LinearCongruentialGenerator lcg5 = makeLCG(0,5);
struct LinearCongruentialGenerator lcg6 = makeLCG(5,0);
printLCG(&lcg1, "initialized lcg1");
printLCG(&lcg2, "initialized lcg2");
printLCG(&lcg3, "initialized lcg3");
printLCG(&lcg4, "initialized error test lcg4");
printLCG(&lcg5, "initialized error test lcg5");
printLCG(&lcg6, "initialized error test lcg6");
testValues(&lcg1, "test lcg1", 10);
testValues(&lcg2, "test lcg2", 10);
testValues(&lcg3, "test lcg3", 10);
printLCG(&lcg1, "lcg1 after first test");
printLCG(&lcg2, "lcg2 after first test");
printLCG(&lcg3, "lcg3 after first test");
testValues(&lcg1, "test lcg1 again", 20);
printLCG(&lcg1, "lcg1 after second test");
return 0;
}