![]() |
|
|
#23 |
|
Jun 2003
2·3·7·112 Posts |
Code:
if (arr[i >> 6] & (0x80000000 >> ((i >> 1) & 0x1F)))
{
arr[i >> 6] ^= (0x80000000 >> ((i >> 1) & 0x1F));
}
Code:
arr[i >> 6] &= ~(0x80000000 >> ((i >> 1) & 0x1F)) |
|
|
|
|
|
#24 |
|
Jun 2003
508210 Posts |
Also, while clearing of multiples of num, instead of starting from num * 3, you can start from num * num (Ask yourself why this would work!).
Also, the whole inner loop can be optimised by directly working with j = i/2 rather than with i. Some thing like: Code:
for ( i = num * num, j=i>>1; (j >> 5) < b_num; j += num)
{
arr[j >> 5] &= ~(0x80000000 >> (j & 0x1F))
}
|
|
|
|
|
|
#25 | |
|
Jun 2003
2×3×7×112 Posts |
Quote:
It is that, earlier, you were doing trial division -- i.e you were trying to divide every number with primes < sqrt(number), whereas SoE knows exactly which numbers are multiples of a given prime and checks off those only. So, for example, your first version will try to check every single number to see if it is divisible by 3, whereas SoE will only check off the actual multiples of 3. In fact, it'd be a very interesting exercise to count the inner loops of both versions -- see how many time SoE executes the "clear" operation, vs how many times the first version executed the "(num % div) == 0" operation. Be warned, you'll probably need to use 64 bit ints to fit the count |
|
|
|
|
|
|
#26 | |||
|
Dec 2005
10111002 Posts |
Quote:
Code:
arr[i >> 6] ^= ~(0x80000000 >> ((i >> 1) & 0x1F)) Quote:
Code:
if (arr[i >> 6] & (0x80000000 >> ((i >> 1) & 0x1F)))
{
arr[i >> 6] ^= (0x80000000 >> ((i >> 1) & 0x1F));
}
So the inner loop becomes: Code:
for ( i = num * num, j = num << 1; (i >> 6) < b_num ; i += j )
{
arr[i >> 6] ^= (0x80000000 >> ((i >> 1) & 0x1F));
}
Quote:
By the way, here is the latest version of my code: Code:
/* prime.c */
/* Oct 17, 2007. */
/* <my name was here> */
/* Program to find prime numbers */
#include <stdlib.h>
int main (void)
{
unsigned int len, num, bitVal, *arr = NULL;
printf ("\nFind prime numbers smaller than \n");
scanf("%i", &len);
if (len < 1)
{
return 0;
}
arr = (unsigned int*)calloc (blocks(len), sizeof(unsigned int));
bin_arr_prime_fill(arr, len);
if (len >= 2)
{
printf("Number 2 is a prime number\n");
}
/* Loop through Prime Array and Output Primes */
for ( num = 1; num <= len ; ++arr )
{
for ( bitVal = 0x80000000; bitVal > 0 && num <= len; bitVal >>= 1,
num += 2 )
{
if ((*arr & bitVal) == bitVal)
{
printf("Number %i is a prime number\n", num);
}
}
}
free(arr - blocks(len));
main();
return 0;
}
unsigned int blocks (const unsigned int len)
{
return ( len % (sizeof(unsigned int) << 4) == 0 ) ?
(len / (sizeof(unsigned int) << 4)) :
(len / (sizeof(unsigned int) << 4) + 1);
}
int bin_arr_prime_fill (unsigned int * const arr, const unsigned int len)
{
unsigned int num, i, j, b_num = blocks(len);
arr[0] = 0x7FFFFFFF;
for ( num = 1 ; num < b_num ; ++num )
{
arr[num] = 0xFFFFFFFF;
}
/* num is the number being checked for primiality */
for ( num = 3; num * num <= len ; num += 2 )
{
for ( i = num * num, j = num << 1; (i >> 6) < b_num ; i += j )
{
arr[i >> 6] ^= (0x80000000 >> ((i >> 1) & 0x1F));
}
}
return 0;
}
Last fiddled with by ShiningArcanine on 2007-10-18 at 11:11 |
|||
|
|
|
|
|
#27 |
|
Dec 2005
1348 Posts |
It seems that the inner loop's test condition can be changed from (i >> 6) < b_num to i < len, which eliminates the need for a bitshift every iteration of that loop.
|
|
|
|
|
|
#28 |
|
Dec 2005
22×23 Posts |
I had to bring back:
Code:
if (arr[i >> 6] & (0x80000000 >> ((i >> 1) % 32)))
{
arr[i >> 6] ^= (0x80000000 >> ((i >> 1) & 0x1F));
}
Edit: With this, the inner loop becomes: Code:
for ( i = num * num, j = num << 1 ; i < len ; i += j )
{
if (arr[i >> 6] & (0x80000000 >> ((i >> 1) & 0x1F)))
{
arr[i >> 6] ^= (0x80000000 >> ((i >> 1) & 0x1F));
}
}
Code:
/* prime.c */
/* Oct 17, 2007. */
/* <my name was here> */
/* Program to find prime numbers */
#include <stdlib.h>
int main (void)
{
unsigned int len, num, bitVal, *arr = NULL;
printf ("\nFind prime numbers smaller than \n");
scanf("%i", &len);
if (len < 1)
{
return 0;
}
arr = (unsigned int*)calloc (blocks(len), sizeof(unsigned int));
bin_arr_prime_fill(arr, len);
if (len >= 2)
{
printf("Number 2 is a prime number\n");
}
/* Loop through Prime Array and Output Primes */
for ( num = 1; num <= len ; ++arr )
{
for ( bitVal = 0x80000000; bitVal > 0 && num <= len; bitVal >>= 1,
num += 2 )
{
if ((*arr & bitVal) == bitVal)
{
printf("Number %i is a prime number\n", num);
}
}
}
free(arr - blocks(len));
main();
return 0;
}
unsigned int blocks (const unsigned int len)
{
return ( len % (sizeof(unsigned int) << 4) == 0 ) ?
(len / (sizeof(unsigned int) << 4)) :
(len / (sizeof(unsigned int) << 4) + 1);
}
int bin_arr_prime_fill (unsigned int * const arr, const unsigned int len)
{
unsigned int num, i, j, k, b_num = blocks(len);
arr[0] = 0x7FFFFFFF;
for ( num = 1 ; num < b_num ; ++num )
{
arr[num] = 0xFFFFFFFF;
}
/* num is the number being checked for primiality */
for ( num = 3; num * num <= len ; num += 2 )
{
if ((arr[num >> 6] & (0x80000000 >> ((num >> 1) & 0x1F))) == 0)
{
continue;
}
for ( i = num * num, j = num << 1; i < len ; i += j )
{
if (arr[i >> 6] & (0x80000000 >> ((i >> 1) & 0x1F)))
{
arr[i >> 6] ^= (0x80000000 >> ((i >> 1) & 0x1F));
}
}
}
return 0;
}
Last fiddled with by ShiningArcanine on 2007-10-18 at 12:29 |
|
|
|
|
|
#29 | |
|
Jun 2003
2×3×7×112 Posts |
Quote:
Already taken care in that code. That's why we start with j = i/2 and increment j by num (j += num) rather than (i += num << 1). |
|
|
|
|
|
|
#30 | |
|
Dec 2005
10111002 Posts |
Quote:
If you use XAND, then (~x) XAND 0100 = 0001, but if you were to do it again, you would get what we had originally, as ~x will be 1110, and ~x XAND 0100 = 0101. (NOT x) XAND y is both a way of setting bits and a way unsetting bits, with the bits you want to either set or unset in x set to 1 in y. That prevents it from being able to replace the conditional expression, as when the sieve goes to 64, the bit position representing 63 will be unset and reset, making the program will report that 63 is prime. However, (NOT x) XAND y == x XOR y, which is x ^ y in C. I posted the source code. Make your change, compile it in Visual Studio, execute the program, run it for 64 as an upper bound, and watch it report that 63 is prime. As for your other suggestion, my program only considers odd integers. On the first iteration, j is even because of j = i/2. On the second iteration, j is odd because of (j += num). On the third iteration, j is even because of (j += num). j will oscillate from even to odd over the course of the first inner loop even loop, making the program report false primes and miss primes. Of course, that is ignoring the fact that after the first iteration, the program will sieve for some even numbers, so some loops will consider only even integers and apply their values to bits that represent odd integers. Edit: I seem to have uncovered a small bug in my program. The inner loop's condition should be i <= len and not i < len. This caused the program to generate incorrect output whenever the upper bound is an odd composite integer. Despite this bug, my 64 upper bound example above still holds. Apparently, I am somewhat biased towards picking either even or prime bounds, so I missed the bug until I accidentally typed 63 instead of 64. Last fiddled with by ShiningArcanine on 2007-10-18 at 16:01 |
|
|
|
|
|
|
#31 | |
|
"Ben"
Feb 2007
DBC16 Posts |
Quote:
Code:
b &= ~(0100) Last fiddled with by bsquared on 2007-10-18 at 17:41 |
|
|
|
|
|
|
#32 | |||
|
Jun 2003
2×3×7×112 Posts |
Quote:
If you want to unset 0100 of the pattern 0101, then you do 0101 & ~(0100) i.e. 0101 & 1011 = 0001. I am not sure why you are getting wrong results. Neither XAND nor a test for checking if the bit is set is needed here. EDIT:- Perhaps, you were checking 63rd bit which corresponds to the prime 127? Quote:
![]() Quote:
Last fiddled with by axn on 2007-10-18 at 18:10 |
|||
|
|
|
|
|
#33 | |
|
1976 Toyota Corona years forever!
"Wayne"
Nov 2006
Saskatchewan, Canada
22·3·17·23 Posts |
Quote:
|
|
|
|
|
![]() |
| Thread Tools | |
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Finding VERY large primes | c10ck3r | Information & Answers | 34 | 2012-08-29 16:47 |
| Why arent there many softwares for finding Huge Primes | blistervol | Math | 2 | 2012-08-20 17:26 |
| Best Work for Finding Primes | Unregistered | Information & Answers | 9 | 2012-06-24 13:50 |
| Finding primes using modular stacking | goatboy | Math | 1 | 2007-12-07 12:30 |
| Finding primes with a PowerPC | rogue | Lounge | 4 | 2005-07-12 12:31 |