Non-deterministic output of simple C program - c

This is an unfinished program I'm writing to learn C (only checks multiples of 2 currently...)
Ultimately, I want this to be an implementation of the Sieve of Eratosthenes (prime numbers)
The problem I'm having is that the output is non-deterministic: sometimes the output includes 11, other times it does not - This happens for a handful of numbers. I have experimented by changing a few things, such as actually initializing the array of booleans to false.
Any ideas why this might be happening?
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int main(int argc, char *argv[]) {
int n = atoi(argv[1]);
int initialPrimeIterator = 2;
_Bool compositePrimeNumbers[n];
printf("Prime Numbers from 2 -> %d\n", n);
for (int i = initialPrimeIterator; i < n; i += initialPrimeIterator) {
compositePrimeNumbers[i-1] = true;
}
printf("Done...\n");
printf("Printing prime numbers from 2-> %d\n", n);
for (int i = 2; i < n; i++) {
if (!compositePrimeNumbers[i]){
printf("%d\n", i + 1);
}
}
return 0;
}
edit: haha. Just realized I have an array named 'compositePrime...' Should just be 'compositeNumbers'

Since I understand you are aiming at completing the program when overcoming this hurdle, I will not post a completed program, but only point out issues in your current version:
As it has been noted, the array compositePrimeNumbers is uninitialized. Since it must be initialized with all values false which is represented by 0, the quickest way is this:
memset(compositePrimeNumbers, 0, sizeof(compositePrimeNumbers));
You should not mark the current initialPrimeIterator as a composite number, hence the for-loop should start with the next multiple. Also, n must be included:
for (int i = 2 * initialPrimeIterator; i <= n; i += initialPrimeIterator) {
(actually, this can be optimized by replacing 2 * initialPrimeIterator with initialPrimeIterator * initialPrimeIterator).
With these changes, I believe you are well on the way to complete the program.

In C, a local array is not initialized, probably for performance reasons.
One way to fix this is to loop over it to set each element to false.

Related

Write a program that will create an integer array with 1000 entries

Write a program that will create an integer array with 1000 entries. After creating the array, initialize all of the values in the array to 0. Next, using the rand function, loop through the array and save a random number between 1 and 10 (inclusive) in each entry of the array.
This is for my homework due tomorrow but I need some help with it since I'm barely a beginner at code.
This is the only code I've made so far with single dimensional arrays
#include <stdio.h>
#include <stdlib.h>
int mean(int array[], int size);
int main()
{
int i;
int array[5]={5, 1, 3, 2, 4};
for (i=0; i<5; i++)
{
printf("%d", array[i]);
}
printf("\nThe mean is %d", mean(array,5));
return 0;
}
int mean(int array[], int size)
{
int i, sum = 0;
for (i=0; i<5; i++)
{
sum=sum + array[i];
}
return sum/5;
}
Not sure why you wrote a program to calculate the mean, given that there's nothing in the requirements about that.
However, you just have to think about the steps. Note that the following example do not perfectly match what you need, they're there just to show you the method, not to be cut and pasted into your assignment.
First, you can create an array of size (for example) seven with the statement:
int value[7];
You can then set all elements to a given value with:
for (size_t idx = 0; idx < sizeof(value) / sizeof(*value); idx++)
value[idx] = 42;
(although, at the level of your assignment, it's probably better to use 7 rather than the sizeof expression).
In order to generate random numbers, you first include the requisite header and, as the first thing in main(), set the seed to something "random":
#include <stdlib.h>
#include <time.h>
:
srand (time (0));
Then, at the time when you need to generate a random number from one to fifty inclusive, you can use:
int rnum = rand() % 50 + 1;
(keeping in mind the distribution won't be perfect but it should be more than good enough for the intended purpose here).
Whatever loop you chose above to initialise the array elements to 42 (or zero) can also be used to set them to random values.
That should be enough to get you started.

C program to find the n'th prime number-

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
int prime(long long int);
long long int *arr; //array to hold n prime numbers
int main()
{
int i,count=4;;
long long int n;
scanf("%lli",&n);
arr=malloc(sizeof(long long int)*n);
arr[0]=2;
arr[1]=3;
arr[2]=5;
arr[3]=7;
if (n==1) printf("%lli",arr[0]);
else{ if (n==2) printf("%lli",arr[1]);
else{ if (n==3) printf("%lli",arr[2]);
else{ if (n==4) printf("%lli",arr[3]);
else
{
for(i=2;count<n;i++)
{
if(prime(6*i-1)) { /*As prime nos are always 6k+1 or
arr[count]=6*i-1; 6k-1fork>=2 I checked only for those*/
count++; }
if(prime(6*i+1)&&count<=n) {
arr[count]=6*i+1;
count++; }
}
printf("%lli",arr[count]);
}}}}
//free(arr);
return 0;
}
int prime(long long int x)
{
int j=1,flag=1;
while(arr[j]<=sqrt(x))
{
if (x%arr[j]==0)
{
flag=0;
break;
}
j++;
}
return flag;
}
The code is working only for n=1,2,3,4, i.e i=0,1,2,3 for which the values are explicitly given. For n=5 onwards it is giving 0 as O/P
There is some glitch related to the global dynamic array as free(arr) is giving core dump error.
Q: Is this the right way to declare a global dynamic array? What could be the problem in this code?
Thank You in advance.
If that is your actual code you have 4 bugs:
2 line comment scopes out a line of your code
the second if should check count < n not count <= n as if count == n you cannot write to arr[count]
You cannot print arr[count] only arr[count-1] which is probably what you mean
In the case where n is less than 4 you still set arr[1], arr[2] and arr[3] which may be out of bounds
It is of course also inefficient to call sqrt(x) in every loop iteration, potentially you should call it outside and there may be a potential rounding issue bug due to the way square roots are calculated, so you might prefer:
while( arr[j] * arr[j] < x )
It would be preferable not to make this global and to pass it into your function.
It would also be preferable to move the main loop logic of your program outside of main().
I'm surprised you say you program works for n=1, 2 and 3 as it looks like you are setting out of bounds.
Your counter goes beyond the size of the array. Specifically both conditions (6i-1 and 6i+1) are met for i=2, and therefore counter is incremented twice, resulting in using arr[5] where you only allocated 5 places in the array. This is because you check counter<=n and not counter
Not sure this could be also be the reason for free creating a core dump, but it is possible (because once corrupting the memory, free may access corrupted data).

Convolution in C without Stackoverflow

I'm trying to do a convolution algorithm in C but is stacking on the array of convolution.
#include <stdio.h>
#include <math.h>
#include <stddef.h>
#define convtotal 2590
int main(int argc, char *argv[]) {
int m,n,i,j;
double x[convtotal],h[convtotal];
m=sizeof(x)/sizeof(double);
n=sizeof(h)/sizeof(double);
double aux1[convtotal], aux2[convtotal],conv[convtotal][1];
for (i=0;i<n+m;i++){
if (i<n)
aux1[i]=x[i];
else
aux1[i]=0;
if (i<m)
aux2[i]=h[i];
else
aux2[i]=0;
}
for (i=0;(n+m-1);i++){
conv[i][1]=0;
for (j=0;j<m;j++)
if (i-j+1>0)
conv[i][1]=conv[i][1]+(aux1[j]*aux2[i-j+1]);
}
}
Any suggestions for this problem?
Two problems:
for (i=0;(n+m-1);i++)
You're not limiting i to anything, so the loop doesn't exit when you reach the end of your arrays; it just keeps incrementing i until you hit memory you don't own, at which point you get the segfault. Since conv only goes to m or n, I think you meant to write
for (i = 0; i < n; i++)
Secondly, you declared conv as an Nx1 array, meaning the only legal index in the second dimension may be 0, so the lines
conv[i][1] = 0;
and
conv[i][1]=conv[i][1]+(aux1[j]*aux2[i-j+1]);
should be
conv[i][0] = 0;
and
conv[i][0]=conv[i][0]+(aux1[j]*aux2[i-j+1]);
Not sure why you declared an Nx1 array (seems you could have just declared conv with one dimension), but I may be missing something obvious.
Note that your x and h arrays initially contain random values.
for (i=0;(n+m-1);i++){
conv[i][1]=0;
for (j=0;j<m;j++)
if (i-j+1>0)
conv[i][1]=conv[i][1]+(aux1[j]*aux2[i-j+1]);
}
(n+m-1) infinite loop with constant as a stop condition.
Not actually infinite, runs untill it segfaults.
for (i=0;(n+m-1);i++){
Shouldn't it be i < m+ n - 1?

How can this combination algorithm be modified to run in parallel on a cuda enabled gpu?

I currently have a c program that generates all possible combinations of a character string. Please note combinations, not permutations. This is the program:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//Constants
static const char set[] = "abcd";
static const int setSize = sizeof(set) - 1;
void brute(char* temp, int index, int max){
//Declarations
int i;
for(i = 0; i < setSize; i++){
temp[index] = set[i];
if(index == max - 1){
printf("%s\n", temp);
}
else{
brute(temp, index + 1, max);
}
}
}
void length(int max_len){
//Declarations
char* temp = (char *) malloc(max_len + 1);
int i;
//Execute
for(i = 1; i <= max_len; i++){
memset(temp, 0, max_len + 1);
brute(temp, 0, i);
}
free(temp);
}
int main(void){
//Execute
length(2);
getchar();
return 0;
}
The maximum length of the combinations can be modified; it is currently set to 2 for demonstration purposes. Given how it's currently configured, the program outputs
a, b, c, d, aa, ab, ac, ad, ba, bb, bc, bd, ca, cb, cc...
I've managed to translate this program into cuda:
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//On-Device Memory
__constant__ char set_d[] = "adcd";
__constant__ int setSize_d = 4;
__device__ void brute(char* temp, int index, int max){
//Declarations
int i;
for(i = 0; i < setSize_d; i++){
temp[index] = set_d[i];
if(index == max - 1){
printf("%s\n", temp);
}
else{
brute(temp, index + 1, max);
}
}
}
__global__ void length_d(int max_len){
//Declarations
char* temp = (char *) malloc(max_len + 1);
int i;
//Execute
for(i = 1; i <= max_len; i++){
memset(temp, 0, max_len+1);
brute(temp, 0, i);
}
free(temp);
}
int main()
{
//Execute
cudaSetDevice(0);
//Launch Kernel
length_d<<<1, 1>>>(2);
cudaDeviceSynchronize();
getchar(); //Keep this console open...
return 0;
}
The cuda version of the original program is basically an exact copy of the c program (note that it is being compiled with -arch=sm_20. Therefore, printf and other host functions work in the cuda environment).
My goal is to compute combinations of a-z, A-Z, 0-9, and other characters of maximum lengths up to 10. That being the case, I want this program to run on my gpu. As it is now, it does not take advantage of parallel processing - which obviously defeats the whole purpose of writing the program in cuda. However, I'm not sure how to remove the recursive nature of the program in addition to delegating the threads to a specific index or starting point.
Any constructive input is appreciated.
Also, I get an occasional warning message on successive compiles (meaning it sporadically appears): warning : Stack size for entry function '_Z8length_di' cannot be statically determined.
I haven't pinpointed the problem yet, but I figured I would post it in case anyone identified the cause before I can. It is being compiled in visual studio 2012.
Note: I found this to be fairly interesting. As the cuda program is now, its output to the console is periodic - meaning that it prints a few dozen combinations, pauses, prints a few dozen combinations, pauses, and so forth. I also observe this behavior in its reported gpu usage - it periodically swings from 5% to 100%.
I don't think you need to use recursion for this. (I wouldn't).
Using printf from the kernel is problematic for large amounts of output; it's not really designed for that purpose. And printf from the kernel eliminates any speed benefit the GPU might have. And I assume if you're testing a large vector space like this, your goal is not to print out every combination. Even if that were your goal, printf from the kernel is not the way to go.
Another issue you will run into is storage for the entire vector space you have in mind. If you have some processing you intend to do on each vector and then you can discard it, then storage is not an issue. But storage for a vector space of length n=10 with "digits" (elements) that have k=62 or more possible values (a..z, A..Z, 0..9, etc.) will be huge. It's given by k^n, so in this example that would be 62^10 different vectors. If each digit required a byte to store it, that would be over 7 trillion gigabytes. So this pretty much dictates that storage of the entire vector space is out of the question. Whatever work you're going to do, you're going to have to do it on the fly.
Given the above discussion, this answer should have pretty much everything that you need. The vector digits are handled as unsigned int, you can create whatever mapping you want between unsigned int and your "digits" (i.e. a..z, A..Z, 0..9, etc.) In that example, the function that was performed on each vector was testing if the sum of the digits matched a certain value, so you could replace this line in the kernel:
if (vec_sum(vec, n) == sum) atomicAdd(count, 1UL);
with whatever function and processing you wanted to apply to each vector generated. You could even put a printf here, but for larger spaces the output will be fragmented and incomplete.

storing known sequences in c

I'm working on Project Euler #14 in C and have figured out the basic algorithm; however, it runs insufferably slow for large numbers, e.g. 2,000,000 as wanted; I presume because it has to generate the sequence over and over again, even though there should be a way to store known sequences (e.g., once we get to a 16, we know from previous experience that the next numbers are 8, 4, 2, then 1).
I'm not exactly sure how to do this with C's fixed-length array, but there must be a good way (that's amazingly efficient, I'm sure). Thanks in advance.
Here's what I currently have, if it helps.
#include <stdio.h>
#define UPTO 2000000
int collatzlen(int n);
int main(){
int i, l=-1, li=-1, c=0;
for(i=1; i<=UPTO; i++){
if( (c=collatzlen(i)) > l) l=c, li=i;
}
printf("Greatest length:\t\t%7d\nGreatest starting point:\t%7d\n", l, li);
return 1;
}
/* n != 0 */
int collatzlen(int n){
int len = 0;
while(n>1) n = (n%2==0 ? n/2 : 3*n+1), len+=1;
return len;
}
Your original program needs 3.5 seconds on my machine. Is it insufferably slow for you?
My dirty and ugly version needs 0.3 seconds. It uses a global array to store the values already calculated. And use them in future calculations.
int collatzlen2(unsigned long n);
static unsigned long array[2000000 + 1];//to store those already calculated
int main()
{
int i, l=-1, li=-1, c=0;
int x;
for(x = 0; x < 2000000 + 1; x++) {
array[x] = -1;//use -1 to denote not-calculated yet
}
for(i=1; i<=UPTO; i++){
if( (c=collatzlen2(i)) > l) l=c, li=i;
}
printf("Greatest length:\t\t%7d\nGreatest starting point:\t%7d\n", l, li);
return 1;
}
int collatzlen2(unsigned long n){
unsigned long len = 0;
unsigned long m = n;
while(n > 1){
if(n > 2000000 || array[n] == -1){ // outside range or not-calculated yet
n = (n%2 == 0 ? n/2 : 3*n+1);
len+=1;
}
else{ // if already calculated, use the value
len += array[n];
n = 1; // to get out of the while-loop
}
}
array[m] = len;
return len;
}
Given that this is essentially a throw-away program (i.e. once you've run it and got the answer, you're not going to be supporting it for years :), I would suggest having a global variable to hold the lengths of sequences already calculated:
int lengthfrom[UPTO] = {};
If your maximum size is a few million, then we're talking megabytes of memory, which should easily fit in RAM at once.
The above will initialise the array to zeros at startup. In your program - for each iteration, check whether the array contains zero. If it does - you'll have to keep going with the computation. If not - then you know that carrying on would go on for that many more iterations, so just add that to the number you've done so far and you're done. And then store the new result in the array, of course.
Don't be tempted to use a local variable for an array of this size: that will try to allocate it on the stack, which won't be big enough and will likely crash.
Also - remember that with this sequence the values go up as well as down, so you'll need to cope with that in your program (probably by having the array longer than UPTO values, and using an assert() to guard against indices greater than the size of the array).
If I recall correctly, your problem isn't a slow algorithm: the algorithm you have now is fast enough for what PE asks you to do. The problem is overflow: you sometimes end up multiplying your number by 3 so many times that it will eventually exceed the maximum value that can be stored in a signed int. Use unsigned ints, and if that still doesn't work (but I'm pretty sure it does), use 64 bit ints (long long).
This should run very fast, but if you want to do it even faster, the other answers already addressed that.

Resources