I am a beginner with threads, I have 2 arrays of floats (1024 elements each) one for real part and the other for imaginary part with which I have to do some computations.
So I thought about boosting the performance of my code by using 4 threads,and I divided my array to 4 sub-section each one of size 256 elements. So each thread is working on a part of each sub-section the arrays, for example:
Thread Nr 1 :
working on element index 0 to index 64
working on element index 256 to index 319
working on element index 512 to index 575
working on element index 768 to index 831
Thread Nr 2 :
working on element index 64 to index 127
working on element index 320 to index 383
working on element index 576 to index 639
working on element index 832 to index 895
Thread Nr 3 :
working on element index 128 to index 191
working on element index 384 to index 447
working on element index 640 to index 703
working on element index 896 to index 959
Thread Nr 4 :
working on element index 192 to index 255
working on element index 448 to index 511
working on element index 704 to index 767
working on element index 960 to index 1023
So as a try I wrote this code:
#define SHIFT_FACTOR 8
#define SIMD_SIZE 256
struct thread_data
{
unsigned start;
unsigned stop;
unsigned Twids_idx;
float* re_in;
float* im_in;
float* re_out;
float* im_out;
};
struct thread_data thread_data_array[4];
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *thread_routine(void *thread_info)
{
int n;
unsigned t_start, t_stop, tw_offset;
unsigned ind1, ind2, ind3;
float *Re_in, *Im_in;
float *Re_out, *Im_out;
struct thread_data *mydata;
mydata = (struct thread_data*) thread_info;
t_start = mydata->start;
t_stop = mydata->stop;
Re_in = mydata->re_in;
Im_in = mydata->im_in;
Re_out = mydata->re_out;
Im_out = mydata->im_out;
for (n = t_start; n < t_stop; n += SHIFT_FACTOR)
{
pthread_mutex_lock(&mutex);
ind1 = 256 + n;
ind2 = 512 + n;
ind3 = 768 + n;
__LOAD_PS__((RE_vec_a, &Re_in[n]), SIMD_SIZE);
__LOAD_PS__((RE_vec_b, &Re_in[ind2]), SIMD_SIZE);
__LOAD_PS__((RE_vec_c, &Re_in[ind1]), SIMD_SIZE);
__LOAD_PS__((RE_vec_d, &Re_in[ind3]), SIMD_SIZE);
__LOAD_PS__((IM_vec_a, &Im_in[n]), SIMD_SIZE);
__LOAD_PS__((IM_vec_b, &Im_in[ind2]), SIMD_SIZE);
__LOAD_PS__((IM_vec_c, &Im_in[ind1]), SIMD_SIZE);
__LOAD_PS__((IM_vec_d, &Im_in[ind3]), SIMD_SIZE);
pthread_mutex_unlock(&mutex);
pthread_mutex_lock(&mutex);
__STORE_PS__((&Re_out[n], RE_vec_a), SIMD_SIZE);
__STORE_PS__((&Re_out[ind1], RE_vec_c), SIMD_SIZE);
__STORE_PS__((&Re_out[ind2], RE_vec_b), SIMD_SIZE);
__STORE_PS__((&Re_out[ind3], RE_vec_d), SIMD_SIZE);
__STORE_PS__((&Im_out[n], IM_vec_a), SIMD_SIZE);
__STORE_PS__((&Im_out[ind1], IM_vec_c), SIMD_SIZE);
__STORE_PS__((&Im_out[ind2], IM_vec_b), SIMD_SIZE);
__STORE_PS__((&Im_out[ind3], IM_vec_d), SIMD_SIZE);
pthread_mutex_unlock(&mutex);
}
pthread_exit(NULL);
}
void foo(float* data1, float* data2, float* result1, float* result2)
{
unsigned t, i = 0, tw = 0;
pthread_t threads[4];
for (t = 0; t < 256; t += 64)
{
thread_data_array[i].start = t;
thread_data_array[i].stop = t + QUARTER;
thread_data_array[i].re_in = data1;
thread_data_array[i].im_in = data2;
thread_data_array[i].re_out = result1;
thread_data_array[i].im_out = result2;
pthread_create(&threads[i], NULL, thread_routine, (void *)&thread_data_array[i]);
i++;
}
for (i = 0; i < 4; i++)
pthread_join(threads[i], NULL);
}
And as you can see I am only loading and storing in the same place the elements using some macros macros __LOAD_PS__() __STORE_PS__() which contains Intel intrinsics.
I tried to check the correctness of the execution and it turn out that on 10 tries : 7 gives me correct results and 3 partially wrong results.
Could some one please explain me what is the reason behind it?
Related
This question already has answers here:
How to create a random permutation of an array?
(3 answers)
Closed 6 years ago.
i am doing a homework. i put rand function in a loop.
int counter = 1;
while ( counter <= 10 ){
variable1 = rand() % 5 + 1;
printf("%d", variable);
counter = counter + 1;
In this code, rand function assigns different value to variable called variable1 but sometimes it assigns same value because range of rand function is narrow. how can i perform that rand function assign different number to variable at the time when loop returns every time.
While rand() is not the greatest random function it should do the trick for many jobs and certainly for most homework. It is perfectly valid to have the same number returned twice in a row from a random function -- as the function should not have any memory of what values were previously returned.
The best way to understand this, is with an example of a coin-toss. Every coin toss is random, and the coin has no memory of the previous toss, so it is possible to flip a coin 32 times in a row and they all comes up head -- if every coin toss is a bit in a 32 bit integer you have created the binary value of integer zero.
However human tend to think (intuition) that having the same value returned more than once is "wrong" for a random function -- but our intuition is wrong on this account.
If you for some reason do want to not repeat the number from one loop to the next, then you will need to program that regardless of which random functions you use -- since any random function would be capable of returning the same values twice.
So something like this would do it;
int counter = 1;
int prevValue = -1;
while ( counter <= 10 ){
do {
variable1 = rand();
} while (variable1 == prevValue);
prevValue = variable1;
variable1 = variable1 % 5 + 1;
printf("%d", variable);
counter = counter + 1;
}
Note that this is still capable of printing the same value twice, since 10 and 15 would be different values before the %5 but would be the same after. If you want the %5 to be taken into account, so the printf never print the same value twice in a row, you would need to move the %5 inside the loop.
In your code snippet i can't find which instruction is the last one inside while. If you want to get different numbers every program run you should use srand() function before while.
But as you mentioned before. Your range (1 - 5) is to narrow to get 10 unique values every time.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
int counter = 1;
int variable1 = 0;
srand(time(NULL));
while ( counter <= 10 ) {
variable1 = rand() % 5 + 1;
printf("%d ", variable1);
counter = counter + 1;
}
putchar('\n');
return 0;
}
how can i perform that rand function assign different number to variable at the time when loop returns every time?
I take this to mean OP does not want to generate the same number twice in a row.
On subsequent iterations, use %(n-1)
int main(void) {
int counter;
int variable;
for (counter = 1; counter <= 10; counter++) {
// First time in loop
if (counter <= 1) {
variable = rand() % 5 + 1;
} else {
int previous = variable;
variable = rand() % (5 - 1) + 1;
if (variable >= previous) variable++;
}
printf("%d\n", variable);
}
return 0;
}
In order to generate a unique list of random numbers, you must check each number generated against the list of numbers previously generated to insure there is no duplicate. The easiest way is to store your previously generated numbers in an array to check against. Then you simply iterate over the values in the array, and if your most recent number is already there, create a new one.
For example, you can use a simple flag to check if your are done. e.g.
while (counter < MAXI){
int done = 0;
while (!done) { /* while done remains 0 (not done) */
done = 1;
tmp = rand() % MAXI + 1; /* generate radom number */
for (i = 0; i < counter; i++) /* check again previous */
if (tmp == array[i]) /* if num already exists */
done = 0; /* set as (not done) */
}
array[counter++] = tmp; /* assign random value */
}
Or you can use the old faithful goto to do the same thing:
while (counter < MAXI) {
gennum:
tmp = rand() % MAXI + 1;
for (i = 0; i < counter; i++)
if (tmp == array[i])
goto gennum;
array[counter++] = tmp;
}
Whichever makes more sense to you. Putting together a full example, you could do:
#include <stdio.h>
#include <stdlib.h> /* for rand */
#include <time.h> /* for time */
enum { MAXI = 10 };
int main (void) {
int array[MAXI] = {0}, counter = 0, i, tmp;
srand (time (NULL)); /* initialize the semi-random number generator */
while (counter < MAXI){
int done = 0;
while (!done) { /* while done remains 0 (not done) */
done = 1;
tmp = rand() % MAXI + 1; /* generate radom number */
for (i = 0; i < counter; i++) /* check again previous */
if (tmp == array[i]) /* if num already exists */
done = 0; /* set as (not done) */
}
array[counter++] = tmp; /* assign random value */
}
for (i = 0; i < MAXI; i++)
printf (" array[%2d] = %d\n", i, array[i]);
return 0;
}
(note: the number your mod (%) the generated number by must be equal to or greater than the number of values you intend to collect -- otherwise, you cannot generate a unique list.)
Example Use/Output
$ ./bin/randarray
array[ 0] = 8
array[ 1] = 2
array[ 2] = 7
array[ 3] = 9
array[ 4] = 1
array[ 5] = 4
array[ 6] = 3
array[ 7] = 10
array[ 8] = 6
array[ 9] = 5
A Shuffled Sequence
Given the discussion in the comments, a good point was raised concerning whether your goal was to create unique set of random numbers (above) or a random set from a sequence of numbers (e.g. any sequence, say 1-50 in shuffled order). In the event you are looking for the latter, then an efficient method to create the shuffled-sequence is using a modified Fisher-Yates shuffle knows as The "inside-out" algorithm.
The algorithm allows populating an uninitialized array with a shuffled sequence from any source of numbers (whether the source can be any manner of generating numbers). Essentially, the function will swap the values within an array at the current index with the value held at a randomly generated index. An implementation would look like:
/** fill an uninitialized array using inside-out fill */
void insideout_fill (int *a, int n)
{
int i, val;
for (i = 0; i < n; i++) {
val = i ? randhq (i) : 0;
if (val != i)
a[i] = a[val];
a[val] = i; /* i here can be any source, function, etc.. */
}
}
(where randhq is any function that generates a random value (0 <= val < n))
A short example program that uses the function above to generate a shuffled array of value from 0 - (n-1) is shown below. The example generates a shuffled sequence of values in array using the inside-out algorithm, and then confirms the sequence generation by sorting the array:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void insideout_fill (int *a, int n);
int randhq (int max);
void prnarray (int *a, size_t n, size_t strd, int wdth);
int intcmp (const void *a, const void *b);
int main (int argc, char **argv) {
srand (time (NULL));
int arrsz = argc > 1 ? (int)strtol (argv[1], NULL, 10) : 50;
int array[arrsz];
insideout_fill (array, arrsz);
printf ("\n array initialized with inside-out fill:\n\n");
prnarray (array, arrsz, 10, 4);
qsort (array, arrsz, sizeof *array, intcmp);
printf ("\n value confirmation for inside-out fill:\n\n");
prnarray (array, arrsz, 10, 4);
return 0;
}
/** fill an uninitialized array using inside-out fill */
void insideout_fill (int *a, int n)
{
int i, val;
for (i = 0; i < n; i++) {
val = i ? randhq (i) : 0;
if (val != i)
a[i] = a[val];
a[val] = i; /* i here can be any source, function, etc.. */
}
}
/** high-quality random value in (0 <= val <= max) */
int randhq (int max)
{
unsigned int
/* max <= RAND_MAX < UINT_MAX, so this is okay. */
num_bins = (unsigned int) max + 1,
num_rand = (unsigned int) RAND_MAX + 1,
bin_size = num_rand / num_bins,
defect = num_rand % num_bins;
int x;
/* carefully written not to overflow */
while (num_rand - defect <= (unsigned int)(x = rand()));
/* truncated division is intentional */
return x/bin_size;
}
/** print array of size 'n' with stride 'strd' and field-width 'wdth' */
void prnarray (int *a, size_t n, size_t strd, int wdth)
{
if (!a) return;
register size_t i;
for (i = 0; i < n; i++) {
printf (" %*d", wdth, a[i]);
if (!((i + 1) % strd)) putchar ('\n');
}
}
/** qsort integer compare */
int intcmp (const void *a, const void *b)
{
return *((int *)a) - *((int *)b);
}
Example Use/Output
$ ./bin/array_io_fill
array initialized with inside-out fill:
40 15 35 17 27 28 20 14 32 39
31 25 29 45 4 16 13 9 49 7
11 23 8 33 48 37 41 34 19 38
24 26 47 44 5 0 6 21 43 10
2 1 18 22 46 30 12 42 3 36
value confirmation for inside-out fill:
0 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
30 31 32 33 34 35 36 37 38 39
40 41 42 43 44 45 46 47 48 49
Look it over and let me know if you have any questions.
I want to find prime numbers with multithreading and using Sieve of E. function.I write some piece of codes. If the program will run, the user enter a max number and thread number. The program should create threads that given thread number. The program find all prime numbers until the max number. Each thread must check one prime number.
My program doesn't find prime numbers. I write checkPrime function and crossout functions for finding prime numbers efficiently. But it doesn't work. So, I can't check my threads work correctly or not. How can I implement checkPrime function?
There are 3 functions. crossout is for Sieve E. method. checkPrime is for checking is a number prime or not. worker is for thread's function. Each thread must check one prime number.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#define MAX_N 100000000
#define MAX_THREADS 25
// global values
int threadNumber;
int largestNumber;
int isPrime;
int nthreads, // number of threads (not counting main())
prime[MAX_N + 1],
n, // in the end, prime[i] = 1 if i prime, else 0
nextbase; // next sieve multiplier to be used
// lock for the shared variable nextbase
pthread_mutex_t nextbaselock = PTHREAD_MUTEX_INITIALIZER;
void crossout(int a) {
int i, j, check;
for (i = 2; i < largestNumber; i++)
prime[i] = 1;
for (i = a; i < largestNumber;)
if (prime[i])
for (j = i; i * j < largestNumber; j++)
prime[i * j] = 0;
}
int checkPrime(int a) {
int i;
for (i = 2; i <= a; ++i) {
if (a % i == 0) {
isPrime = 1;
return isPrime;
break;
} else
isPrime = 2;
crossout(a);
return isPrime;
}
}
void* workerThread(void* t) {
int lim, base;
long i, j;
long tid;
tid = (long)t;
printf("Thread %ld starting...\n", tid);
while (1) {
pthread_mutex_lock(&nextbaselock);
base = nextbase;
nextbase++;
// unlock the lock
pthread_mutex_unlock(&nextbaselock);
if (base <= lim) {
if (prime[base]) {
checkPrime(base);
// log work done by this thread
}
}
if (checkPrime(base) == 2)
printf("Thread %ld done. Prime = %d\n", tid, base);
pthread_exit((void*) t);
}
return NULL;
}
//main function with two parameters :argc and argv
int main(int argc, char** argv) {
threadNumber = argv[3];
largestNumber = argv[1];
int i;
pthread_t thread[threadNumber];
int rc;
long t;
void* status;
for (t = 0; t < threadNumber; t++) {
printf("Main: creating thread %ld\n", t);
rc = pthread_create(&thread[t], NULL, workerThread, (void*)t);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
for (t = 0; t < threadNumber; t++) {
rc = pthread_join(thread[t], (void*)&t);
if (rc) {
printf("ERROR; return code from pthread_join() is %d\n", rc);
exit(-1);
}
printf("Main: completed join with thread %ld \n", t);
}
}
You are trying to mix two different methods for finding prime numbers. You don't need to use both the iterative division method and the sieve of Eratosthenes. This shows a way of implementing the sieve. Even numbers are ignored in the sieve but treated as special cases in isprime(). But it won't help you find a multi threaded solution, because you can't just hand over different numbers to different threads - each prime builds on the work of the previous prime, starting with the assumption that 3 is prime.
// Sieve of Eratosthenes
#include <stdio.h>
#include <stdlib.h>
#define LIMIT 200
char sieve[LIMIT] = { 1, 1, }; // 1 for not-prime
int isprime(unsigned n)
{
if(n <= 2) // special cases
return sieve[n] == 0;
if(n % 2 == 0) // even numbers are not prime
return 0;
if(n >= LIMIT) // test range
exit(1);
return sieve[n] == 0;
}
int main(void)
{
unsigned n, p;
for(n=3; n<LIMIT; n+=2) { // odd numbers only
if (sieve[n] == 0) { // if n is prime
for(p=n*n; p<LIMIT; p+=n*2) { // ignore even numbers
sieve[p] = 1; // not primne
}
}
}
printf("Prime numbers are:\n");
for(n=0; n<LIMIT; n++) { // check all numbers
if (isprime(n)) { // if n is prime
printf("%-4d", n);
}
}
printf("\n");
return 0;
}
Program output:
Prime numbers are:
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71
73 79 83 89 97 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173
179 181 191 193 197 199
I'll now show an iterative division method. Once again, even numbers are treated as special cases. I don't often write multi threaded C code, so I can't help you with that. But I hope you can build on this second example to make a multi threaded solution.
// iterative division
#include <stdio.h>
#include <math.h>
#define LIMIT 200
int isprime(unsigned n)
{
unsigned s, i;
if(n <= 1)
return 0;
if(n == 2)
return 1;
if(n % 2 == 0) // no even numbers
return 0;
s = (unsigned)sqrt(n); // limit the loop
for(i=3; i<=s; i+=2) // odd numbers only
if (n % i == 0)
return 0;
return 1;
}
int main(void)
{
unsigned n;
printf("Prime numbers are:\n");
for(n=0; n<LIMIT; n++) { // check all numbers
if (isprime(n)) { // if n is prime
printf("%-4d", n);
}
}
printf("\n");
return 0;
}
Program output:
Prime numbers are:
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71
73 79 83 89 97 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173
179 181 191 193 197 199
There are some pitfalls in both of the above examples when working with larger numbers, but I'll leave them for you to discover.
This is modified version of Sieve of Eratosthenes which is the very simple, interesting and fast. Understand its working as I have tried to explain it using comments. Actually try to understand the run-time allocation of array size to avoid defining a large MAX value and try to code simple by analyzing your algorithm and applying good mathematics along with smart coding knowledge.
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
int main()
{
int *arr;
int count=0,i=3,j,n;
arr=(int*)malloc(count+1*sizeof(int)); //set array size to 1
arr[count++]=2; //stored 2 as array first element
printf("Find all prime numbers upto :: ");
scanf("%d",&n); //n is the number up to which prime numbers are required
here:
{
while(i<=n) //start with i=3
{
j=0;
while(arr[j]<=sqrt(i)) //till array element value is less than or equal to root of number under checking
{
if(i%arr[j]!=0) //if remainder is not zero check divisibility with next array element
j++;
else
{
i++; //if remainder is zero then start checking for another number
goto here;
}
}
printf("%d, ",arr[count-1]); //printing the number which was proved as prime last time
arr=(int *)realloc(arr,(count+1)*sizeof(int)); //increasing array size by 1
arr[count++]=i; //newly proved prime is stored as next array element
i++;
}
printf("%d, ",arr[count-1]); //print last number proved as prime
}
I'm trying to make a calculator for very big numbers (even bigger than long long) and I'm using arrays to make it work.
So far I have done addition, subtraction and multiplication. But I'm really stuck in division part.
EDIT:
new progress. as a friend mentioned i need to compare result array with divisor each time so i can stop the progress any time divisor is larger than dividend. I managed to make a nice function to compare it every time. this function is tested separately and it's working fine. OK. now i'm starting to make REAL progress. i got the quotient. now i will try to put quotient in array so that we can work with LARGER numbers!
#define MAX_SIZE 50
#define SIZE_USE (MAX_SIZE-1)
int div(int inum_first[], int inum_second[], int div_result[], int firstlen, int secondlen)
{
int i;
int check1 = 0, check2 = 0;
int zeroC = 0;
int tmp[MAX_SIZE];
for (i = 0; i <= SIZE_USE; i++)
{
tmp[i] = 0;
}
int inum_firstCP[MAX_SIZE] = { 0 };
for (i = 0; i <= 1; i++)
{
inum_firstCP[i] = inum_first[i]; // create a copy of inum_first
}
for (i = 0; i <= SIZE_USE; i++)
{
if (inum_first[i] != 0)
check1++;
if (inum_second[i] != 0)
check2++;
}
if (secondlen > firstlen)
{
zeroC++;
goto EOI;
}
if (check2 == 0)
{
puts("\nExpected error\n");
return -1;
}
int j = 0, p = 0;
int s = 0;
int o = 1; // o is Quotient!
do
{
for (i = SIZE_USE; i >= 0; i--)
{
if (tmp[i] = inum_firstCP[i] - inum_second[i] >= 0)
{
tmp[i] = inum_firstCP[i] - inum_second[i];
}
else
{
inum_firstCP[i - 1] = inum_firstCP[i - 1] - 1;
tmp[i] = (inum_firstCP[i] + 10) - inum_second[i];
}
inum_firstCP[i] = tmp[i];
}
if (compare(inum_firstCP, inum_second, firstlen, secondlen) < 0) break;
j++;
o++;
} while (j<MAX_SIZE); // anything else will also work
EOI:
return 0;
}
int compare(int inum_firstCP[], int inum_second[], int firstlen, int secondlen)
{
int c = 0, d = 0;
int i;
firstlen = MAX_SIZE, secondlen = MAX_SIZE; // temporary. will provide a better solution ASAP
if (firstlen > secondlen)
{
return 1;
}
else if (secondlen > firstlen)
{
return -1;
}
else
{
for (i = 0; i < firstlen; i++)
{
if (inum_firstCP[i] > inum_second[i]) c++;
else if (inum_second[i] > inum_firstCP[i]) d++;
}
if (c>d) return 1;
else if (d>c) return -1;
}
return 0; // else
}
If you have the subtraction of those big numbers the easiest solution is to take the two numbers and substract one from the other until you are left with something less then zero. It is the basic solution, it works but is a bit slow.
To make it faster you can do the following, take the divisor, multiply it by 2, if it is less then the dividend, keep on multiplying. When you will reach the first number bigger then a dividend set the corresponding bit to 1, subtract the multiplied dividend then do the same for the result.
There is the same thing nicely described on wiki.
In order to make it work you need to implement your own comparing function.
Assuming you will store the size of the malloc allocation in your structure in filed len you can do something like this:
int compare( mynum &a, mynum &b){
if (a.len() > b.len()){
return 1;
} else (if b.len() > a.len()){
return -1;
} else(){
for(int i = b.len(); i > 0; i--){
if (a[i] > b[i]){
return 1;
} else if(b[i] > a[i]){
return -1;
}
}
#if we get there the numbers are the same
return 0;
}
}
I've done this before and was very happy to implement it the same way as you'd do it by hand, with a small modification of multiple subtraction at each step. The algorithm is like that:
Multiply divisor by ten as often as you can without divisor becoming bigger than dividend.
Subtract divisor from dividend as often as you can and remember how many times.
The rest of all the subtractions is the new dividend.
Repeat at step (1) until dividend is smaller than divisor.
The current dividend is the "rest".
All the numbers remembered at step (3) are the "result" when ordered left to right (left calculated first).
Okay, let's try it by example:
E.g. you have 25391 and want to divide it by 71.
(1) 25391 and 71 * 10 = 710
25391 and 710 * 10 = 7100
25391 and 7100 * 10 = 71000 <-- TOO BIG
(2) 25391 - 7100 => X
18291 - 7100 => X
11191 - 7100 => X
4091 - 7100 <--- NOT POSSIBLE
(3) Number of X: 3
(4) 4091 > 71, okay, back to step 1.
(1) 4091 and 71 * 10 = 710
4091 and 710 * 10 = 7100 <--- TOO BIG
(2) 4091 - 710 => X
3381 - 710 => X
2671 - 710 => X
1961 - 710 => X
1251 - 710 => X
541 - 710 <--- NOT POSSIBLE
(3) Number of X: 5
(4) 541 > 71, okay, back to step 1
(1) 541 and 71 * 10 = 710 <--- TOO BIG
(2) 541 - 71 => X
470 - 71 => X
399 - 71 => X
328 - 71 => X
257 - 71 => X
186 - 71 => X
115 - 71 => X
44 - 71 <--- NOT POSSIBLE
(3) Number of X: 7
(4) 44 > 71, WRONG, continue with step 5
(5) Rest is 44
(6) Result is 357
If you had just tested how often you can subtract 71 from 25391, this loop would have had 357 iterations! Of course, my solution uses multiplication, but honestly, multiplying by 10 is no real multiplication, just shift all digits one position to the left and put a zero at the top right one.
The algorithm will need as many iterations as the result has digits and it will need at most 9 iterations (with subtraction) per digit.
#Mecki Try with 54 664 455 645 655 divided by 5 465 126 544, it fails. At step 3 you must add a number of '0' corresponding to the difference of length between the divisor (x n x 10) and the "rest". ie if the rest is 13 190 205 655 (11 digits length) and divisor is 54 651 265 440 000 (14 digits length) then three '0' must be added to the result before performing the next loop.
I am new to multithreaded programming and so I thought I would work on a project to help me learn it. Here are the details of the project:
Write a multithreaded sorting program in c that works as follows: A list of integers is divided into two smaller lists of equal size. Two separate threads (which we will term sorting threads) sort each sublist using a sorting algorithm of your choice. The two sublists are then merged by a third thread - a merging thread - which merges the two sublists into a single sorted list.
//Sort a list of numbers using two separate threads
//by sorting half of each list separately then
//recombining the lists
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define SIZE 10
#define NUMBER_OF_THREADS 3
void *sorter(void *params); /* thread that performs basic sorting algorithm */
void *merger(void *params); /* thread that performs merging of results */
int list[SIZE] = {7,12,19,3,18,4,2,6,15,8};
int result[SIZE];
typedef struct
{
int from_index;
int to_index;
} parameters;
int main (int argc, const char * argv[])
{
int i;
pthread_t workers[NUMBER_OF_THREADS];
/* establish the first sorting thread */
parameters *data = (parameters *) malloc (sizeof(parameters));
data->from_index = 0;
data->to_index = (SIZE/2) - 1;
pthread_create(&workers[0], 0, sorter, data);
/* establish the second sorting thread */
data = (parameters *) malloc (sizeof(parameters));
data->from_index = (SIZE/2);
data->to_index = SIZE - 1;
pthread_create(&workers[1], 0, sorter, data);
/* now wait for the 2 sorting threads to finish */
for (i = 0; i < NUMBER_OF_THREADS - 1; i++)
pthread_join(workers[i], NULL);
/* establish the merge thread */
data = (parameters *) malloc(sizeof(parameters));
data->from_index = 0;
data->to_index = (SIZE/2);
pthread_create(&workers[2], 0, merger, data);
/* wait for the merge thread to finish */
pthread_join(workers[2], NULL);
/* output the sorted array */
return 0;
}
void *sorter(void *params)
{
parameters* p = (parameters *)params;
//SORT
int begin = p->from_index;
int end = p->to_index+1;
int z;
for(z = begin; z < end; z++){
printf("The array recieved is: %d\n", list[z]);
}
printf("\n");
int i,j,t,k;
for(i=begin; i< end; i++)
{
for(j=begin; j< end-i-1; j++)
{
if(list[j] > list[j+1])
{
t = list[j];
list[j] = list[j+1];
list[j+1] = t;
}
}
}
for(k = begin; k< end; k++){
printf("The sorted array: %d\n", list[k]);
}
int x;
for(x=begin; x<end; x++)
{
list[x] = result[x];
}
printf("\n");
pthread_exit(0);
}
void *merger(void *params)
{
parameters* p = (parameters *)params;
//MERGE
int begin = p->from_index;
int end = p->to_index+1;
int i,j,t;
printf("list[1]: %d",list[1]);
printf("result[1]: %d",result[1]);
for(i=begin; i< end; i++)
{
for(j=begin; j< end-i; j++)
{
if(result[j] > result[j+1])
{
t = result[j];
result[j] = result[j+1];
result[j+1] = t;
}
}
}
int d;
for(d=0; d<SIZE; d++)
{
printf("The final resulting array is: %d\n", result[d]);
}
pthread_exit(0);
}
I'm not sure what I'm doing wrong in my algorithms that its not working. It doesn't seem to catch the new sorted array. Any help on this problem would be appreciated VERY much! Thanks again in advance for all your help!
Your approach is incorrect. You should be splitting your partitions, then recursing or threading into them, joining the results, then merging. Its easy to screw this algorithm up, believe me.
Before anything else, make sure your merge algorithm is solid. If your merge has issues in a single-threaded arena, adding threads is only going to make it worse. In your case, you're making it worse because your merge thread appears to be running concurrently with your sorter threads.
That said, step back and consider this. Mergesort is about divide and conquer. To thread up a merge sort you should be doing the following:
Establish a maximum number of threads. Believe me, the last thing you want happening is spinning a thread for each partition. a sequence of 1024 values has 1023 partitions if you crunch the math hard enough. that many threads is not a solution. Establish some boundaries.
Establish a minimum partition size that you're willing to spin a thread for. This is as important as the first item above. Just like you don't want to be spinning 1023 threads to sort a 1024-slot sequence, you also don't want to be spinning a thread just to sort a sequence that has two items. There is zero benefit and much cost.
Have a solid merge algorithm. There are many efficient ways to do it, but do something simple and enhance it later. Right now we're just interested in getting the general threading down right. There is always time to enhance this with a fancy merge algorithm (like in-place, which believe me is harder than it sounds).
Having the above the idea is this:
The merge sort algorithm will have three parameters: a starting pointer, a length, and a thread-depth. For our purposes the thread depth will be N in a situation where we are using at-most 2N-1 threads. (more on that later, but trust me, it makes it easier to do the math this way).
If the thread depth has reached zero OR the sequence length is below a minimum threshold *we set), do not setup and run a new thread. Just recurse into our function again.
Otherwise, split the partition. Setup a structure that holds a partition definition (which for us will be a starting point and a length as well as the thread depth which will be N/2), launch a thread with that parameter block, then do NOT launch another thread. instead use the current thread to recurse into merge_sort_mt() for the "other" half.
Once the current thread returns from its recursion is must wait on the other thread via a join. once that is done both partitions will be done and they can be merged using your trivial merge algorithm.
Whew. Ok. so how does it look in practice:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <pthread.h>
struct Params
{
int *start;
size_t len;
int depth;
};
// only used for synchronizing stdout from overlap.
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
// forward declare our thread proc
void *merge_sort_thread(void *pv);
// a simple merge algorithm. there are *several* more efficient ways
// of doing this, but the purpose of this exercise is to establish
// merge-threading, so we stick with simple for now.
void merge(int *start, int *mid, int *end)
{
int *res = malloc((end - start)*sizeof(*res));
int *lhs = start, *rhs = mid, *dst = res;
while (lhs != mid && rhs != end)
*dst++ = (*lhs < *rhs) ? *lhs++ : *rhs++;
while (lhs != mid)
*dst++ = *lhs++;
// copy results
memcpy(start, res, (rhs - start) * sizeof *res);
free(res);
}
// our multi-threaded entry point.
void merge_sort_mt(int *start, size_t len, int depth)
{
if (len < 2)
return;
if (depth <= 0 || len < 4)
{
merge_sort_mt(start, len/2, 0);
merge_sort_mt(start+len/2, len-len/2, 0);
}
else
{
struct Params params = { start, len/2, depth/2 };
pthread_t thrd;
pthread_mutex_lock(&mtx);
printf("Starting subthread...\n");
pthread_mutex_unlock(&mtx);
// create our thread
pthread_create(&thrd, NULL, merge_sort_thread, ¶ms);
// recurse into our top-end parition
merge_sort_mt(start+len/2, len-len/2, depth/2);
// join on the launched thread
pthread_join(thrd, NULL);
pthread_mutex_lock(&mtx);
printf("Finished subthread.\n");
pthread_mutex_unlock(&mtx);
}
// merge the partitions.
merge(start, start+len/2, start+len);
}
// our thread-proc that invokes merge_sort. this just passes the
// given parameters off to our merge_sort algorithm
void *merge_sort_thread(void *pv)
{
struct Params *params = pv;
merge_sort_mt(params->start, params->len, params->depth);
return pv;
}
// public-facing api
void merge_sort(int *start, size_t len)
{
merge_sort_mt(start, len, 4); // 4 is a nice number, will use 7 threads.
}
int main()
{
static const unsigned int N = 2048;
int *data = malloc(N * sizeof(*data));
unsigned int i;
srand((unsigned)time(0));
for (i=0; i<N; ++i)
{
data[i] = rand() % 1024;
printf("%4d ", data[i]);
if ((i+1)%8 == 0)
printf("\n");
}
printf("\n");
// invoke our multi-threaded merge-sort
merge_sort(data, N);
for (i=0; i<N; ++i)
{
printf("%4d ", data[i]);
if ((i+1)%8 == 0)
printf("\n");
}
printf("\n");
free(data);
return 0;
}
The output for this looks something like this:
825 405 691 290 900 715 125 969
534 809 783 820 933 895 310 687
152 19 659 856 46 765 497 371
339 660 297 509 152 796 230 465
502 948 278 317 144 941 195 208
617 428 118 505 719 161 53 292
....
994 154 745 666 590 356 894 741
881 129 439 237 83 181 33 310
549 484 12 524 753 820 443 275
17 731 825 709 725 663 647 257
Starting subthread...
Starting subthread...
Starting subthread...
Starting subthread...
Starting subthread...
Starting subthread...
Starting subthread...
Finished subthread.
Finished subthread.
Finished subthread.
Finished subthread.
Finished subthread.
Finished subthread.
Finished subthread.
0 0 1 1 1 2 3 3
5 5 5 5 6 6 7 7
7 7 7 8 8 10 10 11
11 11 12 12 12 13 14 14
15 15 15 15 16 17 17 17
17 18 18 19 19 19 20 21
21 21 22 22 23 24 24 24
25 25 25 26 26 28 28 29
29 29 30 30 30 30 30 31
....
994 995 996 998 1000 1001 1001 1003
1003 1003 1003 1004 1004 1005 1007 1007
1010 1010 1010 1010 1011 1012 1012 1012
1012 1013 1013 1013 1015 1015 1016 1016
1016 1017 1018 1019 1019 1019 1020 1020
1020 1021 1021 1021 1021 1022 1023 1023
The most important part of this is the limiters that keep us from going thread-wild (which is easy to accidentally do with recursive threaded algorithms), and the join of the threads before merging their content with the other half of the partition (which we sorted on our thread, and may also have done the same thing).
It's a fun exercise, and I hope you got something out of it. Best of luck.
Update: Integrating qsort()
An interesting task would be performing this functionality using qsort() for sorting the smaller partitions or once the thread pool reaches exhaustion. qsort() is a pretty big hammer to bring to this party, and as such you're going to want to raise the minimum partition size to something respectful (in the example below, we use 256 elements).
So what would it take to integrate qsort() the the sub partitions rather than a hand-rolled merge-sort? Surprisingly, not much. Start with a qsort() compatible comparator:
// comparator for qsort
int cmp_proc(const void *arg1, const void* arg2)
{
const int *lhs = arg1;
const int *rhs = arg2;
return (*lhs < *rhs) ? -1 : (*rhs < *lhs ? 1 : 0);
}
Pretty brain-dead. Now, modify the mt-wrapper to look something like this:
// our multi-threaded entry point.
void merge_sort_mt(int *start, size_t len, int depth)
{
if (len < 2)
return;
// invoke qsort on the partition. no need for merge
if (depth <= 0 || len <= 256)
{
qsort(start, len, sizeof(*start), cmp_proc);
return;
}
struct Params params = { start, len/2, depth/2 };
pthread_t thrd;
pthread_mutex_lock(&mtx);
printf("Starting subthread...\n");
pthread_mutex_unlock(&mtx);
// create our thread
pthread_create(&thrd, NULL, merge_sort_thread, ¶ms);
// recurse into our top-end parition
merge_sort_mt(start+len/2, len-len/2, depth/2);
// join on the launched thread
pthread_join(thrd, NULL);
pthread_mutex_lock(&mtx);
printf("Finished subthread.\n");
pthread_mutex_unlock(&mtx);
// merge the paritions.
merge(start, start+len/2, start+len);
}
That's it. Seriously. That is all it takes. Proving this works is a simple test run with the original program, shown below:
986 774 60 596 832 171 659 753
638 680 973 352 340 221 836 390
930 38 564 277 544 785 795 451
94 602 724 154 752 381 433 990
539 587 194 963 558 797 800 355
420 376 501 429 203 470 670 683
....
216 748 534 482 217 178 541 242
118 421 457 810 14 544 100 388
291 29 562 718 534 243 322 187
502 203 912 717 1018 749 742 430
172 831 341 331 914 866 931 368
Starting subthread...
Starting subthread...
Starting subthread...
Starting subthread...
Starting subthread...
Starting subthread...
Starting subthread...
Finished subthread.
Finished subthread.
Finished subthread.
Finished subthread.
Finished subthread.
Finished subthread.
Finished subthread.
0 0 1 1 1 1 3 3
3 4 5 5 6 6 6 6
7 7 8 9 10 10 10 10
11 12 12 12 13 13 14 14
14 15 15 15 16 17 17 19
19 20 20 21 21 21 22 22
23 23 23 24 24 24 25 26
26 26 26 27 28 28 28 28
....
1000 1000 1000 1001 1001 1002 1003 1003
1004 1004 1004 1005 1005 1005 1006 1007
1008 1010 1010 1010 1010 1010 1011 1011
1011 1012 1012 1012 1012 1013 1013 1013
1015 1015 1015 1016 1016 1017 1017 1017
1018 1018 1018 1019 1019 1021 1021 1022
As you can see, the results are similar.
A couple of issues:
1 - What do you think this code is doing:
int x;
for(x=begin; x<end; x++)
{
list[x] = result[x];
}
2 - Your merger currently looks exactly like your sorter. It should instead be merging the sorted values from the first half of the list and the second half of the list into the result.
Your code is correct i have modified your code and tried to figure out the error,
the loop indexes are not correctly mapped and you are assigning the null result list into actual data in one loop, so the list is taking zeroes.
Find below the modified code and output.
//Sort a list of numbers using two separate threads
//by sorting half of each list separately then
//recombining the lists
void *sort(void *params)
{
parameters* p = (parameters *)params;
//SORT
int begin = p->fromVal;
int end = p->toVal+1;
for(int i = begin; i < end; i++){
printf("The array recieved is: %d\n", list[i]);
}
printf("\n");
int temp=0;
for(int i=begin; i< end; i++)
{
for(int j=begin; j< end-1; j++)
{
if(list[j] > list[j+1])
{
temp = list[j];
list[j] = list[j+1];
list[j+1] = temp;
}
}
}
for(int k = begin; k< end; k++){
printf("The sorted array: %d\n", list[k]);
}
for(int i=begin; i<end; i++)
{
result[i] = list[i];
}
printf("\n");
pthread_exit(NULL);
}
void *merging(void *params)
{
parameters* p = (parameters *)params;
//MERGE
int begin = p->fromVal;
int end = p->toVal+1;
int temp;
for(int i=begin; i< end; i++)
{
for(int j=begin; j< end-1; j++)
{
if(result[j] > result[j+1])
{
temp= result[j];
result[j] = result[j+1];
result[j+1] = temp;
}
}
}
printf("\n\nFINAL RESULT IS:\n");
for(int d=begin+1; d<end; d++)
{
printf("The final resulting array is: %d\n", result[d]);
}
pthread_exit(NULL);
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>
/*globle variables*/
/* structure for passing data to threads */
typedef struct
{
int *start;
int end;
int size;
} parameters;
int t = 1;
int *arr1, *arr2;
//for using quicksort
int comparator (const void * a, const void * b) {
return ( *(int*)a - *(int*)b );
}
void *merge(void *params){
//get data
int *len = params;
//SORT
int start = 0;
int end = *len/2;
int counter = end;
int size = *len;
int index = 0;
while (start < end && counter < size)
{
if (arr1[start] < arr1[counter])
{
arr2[index] = arr1[start];
start ++;
}
else
{
arr2[index] = arr1[counter];
counter ++;
}
index ++;
}
/* Copy the remaining elements , if there
are any */
while ( start < end)
{
arr2[index] = arr1[start];
start ++;
index ++;
}
/* Copy the remaining elements , if there
are any */
while ( counter < size)
{
arr2[index] = arr1[counter];
counter ++;
index ++;
}
}
void *sorting_thread(void *params){
printf("Thread %d ......\n", t);
t++;
//get data
parameters* data = (parameters *)params;
//SORT
int end = data->end;
int size = data->size;
//qsort
qsort(data->start, end, sizeof(*data->start), comparator);
printf("The array after sort : \n");
for(int i = size - end; i < size; i ++){
printf("arr1[%d]:%d, \n", i,arr1[i]);
}
printf("\n");
pthread_exit(0);
}
void *merge_sort_thread(void *params){
int *len = params;
//varaible allocation for two sorting threads.
parameters *data = (parameters *) malloc (sizeof(parameters));
parameters *data1 = (parameters *) malloc (sizeof(parameters));
if(data == NULL&& data1 == NULL){
printf("Memory not allocated. \n");
exit(0);
}
//value for data passing
data->start= arr1;
data->end = *len/2;
data->size = *len/2;
data1->start = arr1 + *len/2;
data1->end = *len-*len/2;
data1->size = *len;
pthread_t left, right;/* the thread identifier */
printf("Entering merge_Sorting..\n");
/* create the sorting thread */
pthread_create(&left, NULL, sorting_thread, data);
pthread_create(&right, NULL, sorting_thread, data1);
/* wait for the thread to exit */
pthread_join(left, NULL);
//free memory
free(data);
pthread_join(right, NULL);
printf("Merging Thread %d ......\n", t);
merge(len);
printf("Process is done.\n");
printf("The final output: \n");
for(int i = 0; i < *len; i ++){
if(i%10==0){
printf("\n");
}
printf("%d, ", arr2[i]);
}
printf("\n");
//free memory
free(data1);
pthread_exit(0);
}
int main( int argc, char *argv[] ) {
long len;
int temp, c, j, k;
char *ptr;
//
//check if the right amount of argument
if( argc == 2 ) {
printf("The input array size is %s\n", argv[1]);
//covert the user input to integer
len = strtol(argv[1], &ptr, 10);
//check if the input is valid.
if(len == 0) {//if not, leave the program.
printf("Please enter a proper number. Leaving the program...\n");
}else{
//dynamically allocate memory
arr1 = (int*)malloc(len * sizeof(int));
arr2 = (int*)malloc(len * sizeof(int));
//check Memory
if(arr1 == NULL && arr2 == NULL){
printf("Memory not allocated. \n");
exit(0);
}
printf("Memory allocated. \n");
//decide the value of data.
//generate random number to 100
srand(time(0));
printf("The array before sorting is: \n");
for(int i = 0; i < len; i ++){
arr1[i] = rand() % 100;
if(i%10==0){
printf("\n");
}
printf("%d, ", arr1[i]);
}
printf(" \n");
//merge sort handle all the threads
pthread_t tid;/* the thread identifier */
/* create the parent sorting thread */
pthread_create(&tid, NULL, merge_sort_thread, &len);
//wait for children thread
pthread_join(tid, NULL);
//printout array after merging threading
printf("\nThe program is finished. \n");
//free memory space
free(arr2);
free(arr1);
}
}
else if( argc > 2 ) {
printf("Too many arguments supplied.\n");
}
else {
printf("One argument expected.\n");
}
return 0;
}
I have to copy the elements of one array of structure to blank elements of a new array of structures (all dynamically allocated). Every element of the array of structures I have, structure 'a', has only two columns, left_column and right_column. Some of the right column entries of each element of structure a (say, i'th structure element) matches the left column entry of the next (viz., i+1 th) structure element of the same structure a. I am attempting to find such matching entries and I am attempting to copy the entire left and right column of the matching elements one-by-one to a smaller, conserved structure, structure b. The problem is the code is compiling, but it is not getting into the all-important matching part, viz., the if part. It is getting into the while loop.
Kept below are the information and sample data. This code has come to this stage due to 'PlerumCodeExperientia', I thank him. Please suggest how to copy these matching elements.
Thanking you, Dan.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* args[])
{
struct a
{
int left_line;
int right_line;
};
struct b
{
int conserved_left;
int conserved_right;
};
FILE *fp100; // Output File
fp100 = fopen("Conserved_Elements.txt", "a");
struct a *ptr1;
int structACapacity = 3; // Only 3 such comparison files are being worked with, there are >1000 comparison files
ptr1 = malloc(structACapacity*sizeof(struct a));
struct b *ptr2;
int structBCapacity = 1000;
ptr2 = malloc(structBCapacity*sizeof(struct b));
int structure_ctr;
int number_of_line_comparison_files = 3; // Only 3 for the time being
int knt;
int left, right;
for (structure_ctr=0; structure_ctr < number_of_line_comparison_files; structure_ctr++) {
knt = 0;
while (((ptr1+knt) < (ptr1+structACapacity-1)) && (knt < 500)) {
fprintf(fp100, "Getting Into While\n");
// finding the matching entries between right column of knt and left column of (knt+1)
if ((ptr1+knt)->right_line == (ptr1+(1+knt))->left_line) {
fprintf(fp100,"\tGetting Into the If\n");
// copying matching values to the struct b
left = (ptr2+knt)->conserved_left = (ptr1+knt)->left_line;
right = (ptr2+knt)->conserved_right = (ptr1+knt)->right_line;
//fprintf(fp100,"C-Left:%d\tC-Right:%d\tLeft%d\tRight%d\n",(ptr2+knt)->conserved_left,(ptr2+knt)->conserved_right,left,right);
// left, right are there for convinience only - easier to see, same values
fprintf(fp100,"C-Left:%d\tC-Right:%d\n", left,right);
}
++knt;
} // end of while
} //end of for
}
The files look:
A fragment of the first structure element looks like:
17 216
26 119
28 16
29 122
59 124
60 116
62 114
63 112
66 61
69 54
70 51
71 62
91 40
99 38
A fragment of the Second element looks like:
321 25
110 45
116 49
216 110
56 117
54 131
32 167
31 178
8 188
12 199
39 239
60 244
121 263
124 275
A fragment of the 3rd element looks like:
75 223
61 248
45 278
31 290
10 291
111 311
117 324
128 338
139 347
148 365
167 376
178 381
191 394
193 397
etc..., there are many such elements. All of them contain such unformatted two columns of integers.
In case if you are interested to see how the content of the original file was loaded into 'structure_a', the next piece is given. It works fine.
for(q=0; q < number_of_line_comparison_files; q++) // going through the total number of files
{
// File Name Etc ..
while (fgets(file_line,99,line_comparison_file)!= NULL)
{
++number_of_lines ; // Integer
for(j=0;j<6;j++)
string_left_line[j]=file_line[j];
for(j=0;j<6;j++)
string_right_line[j]=file_line[6+j];
left_line = atoi(string_left_line);
right_line = atoi(string_right_line);
*(&(ptr1+q)->left_line) = left_line;
*(&(ptr1+q)->right_line) = right_line;
fprintf(fp100,"Left:%d\tRight:%d\n",(ptr1+q)->left_line,(ptr1+q)->right_line);
} // END OF THE 'WHILE'
fprintf(fp100,"\n\n\t================================== ================================\n\n");
} // End of For
Dan
I must say that, there should be a little more information, for the question to be completely clear.
With the given data, this is my answer. At least the part of what I assume is asked.
I hope it helps.
// copy_pointer_struct.c
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char* args[])
{
struct a
{
int left_line;
int right_line;
};
struct b
{
int conserved_left;
int conserved_right;
};
FILE *fp100;
fp100 = fopen("struct_file.txt", "a");
struct a* ptr1;
int structACapacity = 3;
ptr1=(struct a*)malloc(structACapacity*sizeof(struct a));
struct b *ptr2;
int structBCapacity = 1000;
ptr2=(struct b*)malloc(structBCapacity*sizeof(struct b));
// for writing test values to ptr1 array
int i;
for ( i = 0; i < structACapacity; i++ )
{
ptr1[i].left_line = i;
(ptr1+i)->right_line = i+1;
}
int structure_ctr,
number_of_line_comparison_files = 10,
knt;
// This outer for is neccessary only if you are getting structs form another source - a file for example or another structure.
//for(structure_ctr=0; structure_ctr < number_of_line_comparison_files; structure_ctr++)
{
// this inner for would be neccessary if you had an 2 dimensional array of structs or a pointer to a pointer to struct.
//for(knt=0; knt<500; knt++)
{
knt = 0;
// in your while condition there is no changing value, (change being made inside cycle or condition itself),
// which results in an infinite (for condition true) cycle or 0 cycles (for condition false)
// this particular condition works until we have reached 500th element or the end of array,
// whichever has lower value.
// Of course in case of use of outer for ( && knt < 500) wouldn't be used, depending of the goal you have.
while( (ptr1+knt) < (ptr1+structACapacity-1) && knt < 500 )
{
if( (ptr1+knt)->right_line == (ptr1+1+knt)->left_line ) // comment line for file test
{
// copying duplicate values to the struct b
int left = (ptr2+knt)->conserved_left = (ptr1+1+knt)->left_line;
int right = (ptr2+knt)->conserved_right = (ptr1+knt)->right_line;
// here you can write those values to a file as 2 integers, for example
fprintf(fp100,"%d %d\n", left, right);
}
++knt;
} // while
}//
} //for structure_ctr
fclose(fp100);
}
Perhaps this addition helps:
// copy_pointer_struct.c
#include<stdio.h>
#include<stdlib.h>
typedef struct a
{
int left_line;
int right_line;
} structA;
typedef struct b
{
int conserved_left;
int conserved_right;
} structB;
int fillColumnPtr(FILE* source, structA* ptr);
int main(int argc, char* args[])
{
FILE *fp100;
fp100 = fopen("struct_file.txt", "w");
structA* ptr1;
int structACapacity = 1000;
ptr1=(structA*)malloc(structACapacity*sizeof(struct a));
printf("kapacitet ptr1: %d\n", sizeof ptr1);
structB *ptr2;
int structBCapacity = 1000;
ptr2=(struct b*)malloc(structBCapacity*sizeof(struct b));
char *filename = "columns_file4.txt";
FILE *cfile1 = fopen(filename, "r");
printf("Loading values from file: %s . . . \n", filename);
int number_of_lines = fillColumnPtr(cfile1, ptr1);
fclose(cfile1);
printf("Done.\n\n");
printf("Values loaded to ptr1(total lines %d):\n", number_of_lines);
int i;
for ( i = 0; i < number_of_lines; i++ )
{
printf("left: %6d, right: %6d\n", ptr1[i].left_line, ptr1[i].right_line);
}
printf("\nProcessing...\n");
int structure_ctr,
number_of_line_comparison_files = 10,
knt;
knt = 0;
while( (ptr1+knt) < (ptr1+structACapacity-1) && knt < number_of_lines )
{
if( (ptr1+knt)->right_line == (ptr1+1+knt)->left_line ) // comment line for file test
{
// copying duplicate values to the struct b
int left = (ptr2+knt)->conserved_left = (ptr1+1+knt)->left_line;
int right = (ptr2+knt)->conserved_right = (ptr1+knt)->right_line;
// here you can write those values to a file as 2 integers, for example
fprintf(fp100,"%d %d\n", left, right);
printf("%d %d\n", left, right);
}
++knt;
} // while
fclose(fp100);
}
// function: transfers data from a source file to pointer to struct
int fillColumnPtr(FILE* source, structA* ptr)
{
char file_line[20],
*str_left_line = calloc(sizeof(char), 6),
str_right_line[6];
int left_line, right_line, j, line_counter = 0, i = 0;
while ( fgets(file_line, 19, source) != NULL )
{
printf(">> fileline: %s", file_line);
for(j=0;j<6;j++)
{
str_left_line[j]=file_line[j];
str_right_line[j]=file_line[6+j];
}
left_line = atoi(str_left_line);
right_line = atoi(str_right_line);
printf(" left right: %-3d %6d\n", left_line, right_line);
ptr[i].left_line = left_line;
ptr[i].right_line = right_line;
++i;
++line_counter;
}
return line_counter;
}
Note: I examined few of your source values, that are supposed to be in a file - non of them satisfies the condition inside if, resulting in an empty pointer.
The additional posted, I have tested with altered values and it works.
For this method check the spacing in rows.
Contents of the "columns_file4.txt":
321 25
25 45
116 49
216 110
110 117
54 131
32 167
31 178
178 188
12 199
199 239
60 244
121 263
124 275
// End of file
In this file there are equal values for example:
(row 1 col right)25 == (row 2 col left )25, 110 , 178, 199.
If this is not what you are looking for, then alter the if condition.
Good luck.
Hope this help.