Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon.

Pages: 1-

Lazy Primes in C++

Name: Anonymous 2009-03-31 18:31


#include <cstdlib>
#include <climits>
#include <unistd.h>

class Prime
{
    unsigned long value;
    Prime* next;
    bool locked;

    // modified from
    // www.codecodex.com/wiki/index.php?title=Calculate_an_integer_square_root
    static unsigned long isqrt(unsigned long n)
    {
        register unsigned long op = n, res = 0, one;

        // second-to-top bit set portably.
        one = (~((ULONG_MAX << 1) >> 1)) >> 1;

        while(one > op) one >>= 2;

        while(one) {
            if(op >= res + one) {
                op = op - (res + one);
                res = res + 2 * one;
            }
            res >>= 1;
            one >>= 2;
        }

        return res;
    }

    // used to test primality of larger integers.
    static bool isPrime(unsigned long n)
    {
        unsigned long i, j = isqrt(n);

        // if n is cleanly divisible once from 3 to isqrt(n),
        // then it is not prime.
        for(i = 3; i <= j; i += 2)
            if(n % i == 0)
                return false;

        // if never cleanly divisible, then n is prime.
        return true;
    }

    // used so that only one thread will generate the next prime at a time.
    void lock()
    {
        while(locked)
            usleep(0);
        locked = true;
    }

    // lets other threads get the next prime once it's been generated.
    void unlock()
    {
        locked = false;
    }

    // don't let primes be copied--that's just asking for memory allocation
    // woes.
    Prime(const Prime&);

public:

    Prime(unsigned long v, Prime *n = NULL)
        : value(v), next(n), locked(false)
    {
    }

    ~Prime()
    {
        delete next;
    }

    Prime* Next()
    {
        if(!next)
        {
            unsigned long i;

            lock();

            // search for the next prime;
            for(i = value + 2; !isPrime(i) && i < ULONG_MAX - 1; i += 2);

            // if the search was good, we've generated the next prime.
            if(i != ULONG_MAX - 1)
                next = new Prime(i);

            unlock();
        }

        return next;
    }

    unsigned long Value() const
    {
        return value;
    }
};

class Primes
{
    Prime* first;

public:

    Primes() : first(new Prime(2, new Prime(3)))
    {
    }

    ~Primes()
    {
        delete first;
    }

    Prime* First()
    {
        return first;
    }
};


Primes on demand!

Name: Anonymous 2009-03-31 18:33

EXPERT WEB DEVELOPER CODE

Name: Anonymous 2009-03-31 18:45

>>2
Web developer? What, just because of the code copied from codecodex.com? I needed an integer version of sqrt(), so I just googled it. It's kindof a waste anyway, I've found that just casting the double returned from sqrt() to an integer is just a tad slower than this isqrt() function.

Name: Anonymous 2009-03-31 19:05

>>3
Because you wasted so much time borrowing some code to perform integer square roots, without realising that 99.999% of the computational power in this program is a result of the shitty vanilla for loop isPrime() implementation. You are also wrong about your integer square root function. Square roots on floats/doubles simply have to half the exponent, and are much faster that your implementation.

Name: Anonymous 2009-03-31 19:17

#include "fdlibm.h"

#ifdef __STDC__
static    const double    one    = 1.0, tiny=1.0e-300;
#else
static    double    one    = 1.0, tiny=1.0e-300;
#endif

#ifdef __STDC__
    double __ieee754_sqrt(double x)
#else
    double __ieee754_sqrt(x)
    double x;
#endif
{
    double z;
    int     sign = (int)0x80000000;
    unsigned r,t1,s1,ix1,q1;
    int ix0,s0,q,m,t,i;

    ix0 = __HI(x);            /* high word of x */
    ix1 = __LO(x);        /* low word of x */

    /* take care of Inf and NaN */
    if((ix0&0x7ff00000)==0x7ff00000) {
        return x*x+x;        /* sqrt(NaN)=NaN, sqrt(+inf)=+inf
                       sqrt(-inf)=sNaN */
    }
    /* take care of zero */
    if(ix0<=0) {
        if(((ix0&(~sign))|ix1)==0) return x;/* sqrt(+-0) = +-0 */
        else if(ix0<0)
        return (x-x)/(x-x);        /* sqrt(-ve) = sNaN */
    }
    /* normalize x */
    m = (ix0>>20);
    if(m==0) {                /* subnormal x */
        while(ix0==0) {
        m -= 21;
        ix0 |= (ix1>>11); ix1 <<= 21;
        }
        for(i=0;(ix0&0x00100000)==0;i++) ix0<<=1;
        m -= i-1;
        ix0 |= (ix1>>(32-i));
        ix1 <<= i;
    }
    m -= 1023;    /* unbias exponent */
    ix0 = (ix0&0x000fffff)|0x00100000;
    if(m&1){    /* odd m, double x to make it even */
        ix0 += ix0 + ((ix1&sign)>>31);
        ix1 += ix1;
    }
    m >>= 1;    /* m = [m/2] */

    /* generate sqrt(x) bit by bit */
    ix0 += ix0 + ((ix1&sign)>>31);
    ix1 += ix1;
    q = q1 = s0 = s1 = 0;    /* [q,q1] = sqrt(x) */
    r = 0x00200000;        /* r = moving bit from right to left */

    while(r!=0) {
        t = s0+r;
        if(t<=ix0) {
        s0   = t+r;
        ix0 -= t;
        q   += r;
        }
        ix0 += ix0 + ((ix1&sign)>>31);
        ix1 += ix1;
        r>>=1;
    }

    r = sign;
    while(r!=0) {
        t1 = s1+r;
        t  = s0;
        if((t<ix0)||((t==ix0)&&(t1<=ix1))) {
        s1  = t1+r;
        if(((t1&sign)==sign)&&(s1&sign)==0) s0 += 1;
        ix0 -= t;
        if (ix1 < t1) ix0 -= 1;
        ix1 -= t1;
        q1  += r;
        }
        ix0 += ix0 + ((ix1&sign)>>31);
        ix1 += ix1;
        r>>=1;
    }

    /* use floating add to find out rounding direction */
    if((ix0|ix1)!=0) {
        z = one-tiny; /* trigger inexact flag */
        if (z>=one) {
            z = one+tiny;
            if (q1==(unsigned)0xffffffff) { q1=0; q += 1;}
        else if (z>one) {
            if (q1==(unsigned)0xfffffffe) q+=1;
            q1+=2;
        } else
                q1 += (q1&1);
        }
    }
    ix0 = (q>>1)+0x3fe00000;
    ix1 =  q1>>1;
    if ((q&1)==1) ix1 |= sign;
    ix0 += (m <<20);
    __HI(z) = ix0;
    __LO(z) = ix1;
    return z;
}

Name: Anonymous 2009-03-31 19:24

>>4
I know that isPrime() is simple and expensive. At least it's somewhat "optimized" by only going up to the square root....

Wait, I could possibly make this better by using the existing list of prime numbers to determine whether the next number is prime.

Anyways, like I said, in some short tests, I found isqrt() to be just as fast as (unsigned long)sqrt().

Name: Anonymous 2009-03-31 19:54

>>6
You found incorrectly.
#####:Desktop$ gcc -g -ansi -Wall -lm -D_INT -o testsqrt testsqrt.c
#####:Desktop$ time ./testsqrt

real    0m16.484s
user    0m16.477s
sys    0m0.002s
#####:Desktop$ gcc -g -ansi -Wall -lm -D_DEF -o testsqrt testsqrt.c
testsqrt.c:7: warning: ‘isqrt’ defined but not used
#####:Desktop$ time ./testsqrt

real    0m3.443s
user    0m3.439s
sys    0m0.003s


#include <math.h>
#include <stdlib.h>
#include <limits.h>
#include <unistd.h>
#include <stdio.h>
static unsigned long isqrt(unsigned long n)
{
    register unsigned long op = n, res = 0, one;
    one = (~((ULONG_MAX << 1) >> 1)) >> 1;

    while(one > op) one >>= 2;

    while(one) {
        if(op >= res + one) {
            op = op - (res + one);
            res = res + 2 * one;
        }
        res >>= 1;
        one >>= 2;
    }

    return res;
}
int main(int argc, char** argv) {
    int i=0;
    for(i=0; i<100000000; i++) {
#ifdef _INT
        isqrt(i);
#endif
#ifdef _DEF
        sqrt(i);
#endif
    }
    return 0;
}

Name: Anonymous 2009-03-31 20:07

>>7
To extend on this, I also included the fdlib sqrt implementation in the tests.

cosc794:sqrttest$ gcc -g -ansi -Wall -lm -D_INT -o testsqrt testsqrt.c
user:sqrttest$ time ./testsqrt 10000000

real    0m16.508s
user    0m16.499s
sys    0m0.003s
user:sqrttest$ gcc -g -ansi -Wall -lm -D_DEF -o testsqrt testsqrt.c
testsqrt.c:7: warning: ‘isqrt’ defined but not used
user:sqrttest$ time ./testsqrt 10000000

real    0m3.451s
user    0m3.448s
sys    0m0.000s
user:sqrttest$ gcc -g -ansi -Wall -lm -D_FDL -o testsqrt testsqrt.c
testsqrt.c:7: warning: ‘isqrt’ defined but not used
user:sqrttest$ time ./testsqrt 10000000

real    0m0.340s
user    0m0.337s
sys    0m0.001s

user:sqrttest$ cat ./testsqrt.c
#include <math.h>
#include <stdlib.h>
#include <limits.h>
#include <unistd.h>
#include <stdio.h>
#include "fdlibm.h"
static unsigned long isqrt(unsigned long n)
{
    register unsigned long op = n, res = 0, one;
    one = (~((ULONG_MAX << 1) >> 1)) >> 1;

    while(one > op) one >>= 2;

    while(one) {
        if(op >= res + one) {
            op = op - (res + one);
            res = res + 2 * one;
        }
        res >>= 1;
        one >>= 2;
    }

    return res;
}
int main(int argc, char** argv) {
    int i=0;
    for(i=0; i<atoi(argv[1]); i++) {
#ifdef _INT
        isqrt(i);
#endif
#ifdef _DEF
        sqrt(i);
#endif
#ifdef _FDL
        __ieee754_sqrt(i);
#endif
    }
    return 0;
}

Name: Anonymous 2009-03-31 23:15

>>8
you forgot that you also have to truncate to an int after doing sqrt or __ieee754sqrt.
and unless your compiler or libc is absolute shit, it'll optimize out the whole loop with isqrt and sqrt (and maybe __ieee754_sqrt too).

Name: Anonymous 2009-03-31 23:17

>>9
You don't know much about compilers or the function of libc, do you?

Name: Anonymous 2009-03-31 23:22

>>10
it's pretty obvious that the call to the square root function is the only thing in the body of the loop, the result is discarded, and i isn't used after the loop. unless your libc is completely braindead and doesn't declare atoi and sqrt with the const attribute, even the shittiest compiler in widespread use should be able to eliminate the whole loop.

Name: Anonymous 2009-03-31 23:45

>>11
But not a single one of them will if you compile it like >>8 did.

Name: Anonymous 2009-04-01 0:56

>>12
>>8 intentionally told the compiler to make isqrt slow as fuck when he compiled it, while the other two functions were probably compiled with -O2.

Name: Anonymous 2009-04-01 1:29

>>13
No, I posted the source code; you can check it yourself if you want to be a complete fucknut. Obviously you aren't going to though, because if you were a reasonable and intelligent person you would of already done just that before spewing shit out your ass. TLDR: IHBT

Name: Anonymous 2009-04-01 2:51

>>14
i did check it myself.
when i compiled it, it took the same amount of time with isqrt and sqrt.

Name: Anonymous 2009-04-01 3:04

>>14
www.usingenglish.com

For more information on your specific error, refer to: http://www.wsu.edu/~brians/errors/couldof.html

Name: Anonymous 2009-04-01 3:24

just use goddamn Newton's Method

Name: Anonymous 2009-04-01 3:27

>>17
What does finding the zeros of a function have to do with finding prime numbers?

Name: Anonymous 2009-04-01 3:36

>>18
if' p c a = if p then c else a
loeb = fix (fmap . flip id =<<)
primes = loeb $ const Nothing : const Nothing : const (Just 2) : const (Just 3) : map (flip flip Nothing . ap (flip . (if' .) . ap ((.) . all . ((0 /=) .) . mod) ((. catMaybes) . takeWhile . (. join (*)) . flip (<=))) Just) [3, 5..]

Name: Anonymous 2009-04-01 3:59

>>19
EXPERT @PLER

Name: Anonymous 2009-04-01 4:41

primes=loeb$map const[Nothing,Nothing,Just 2]++map(flip flip(Nothing).ap(flip.((\p c a->if p then c else a).).ap((.).all.((0/=).).mod)((.catMaybes).takeWhile.(.join(*)).(>=)))Just)[3,5..]

Name: Anonymous 2009-04-01 10:50


#include <gmp.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
    mpz_t n;
    int i, res, reps = 100;

    mpz_init(n);

    for(i = 1; i < argc; ++i) {
        mpz_set_str(n, argv[i], 10);
        res = mpz_probab_prime_p(n, reps);

        mpz_out_str(stdout, 10, n);
        if(res == 2)
            printf(" is definitely prime.\n");
        else if(res == 1)
            printf(" is probably prime.\n");
        else if(res == 0)
            printf(" is definitely composite.\n");
    }

    mpz_clear(n);

    return 0;
}

Name: Anonymous 2010-11-15 14:19

Name: Anonymous 2010-12-06 9:08

Back to /b/, ``GNAA Faggot''

Name: Anonymous 2011-02-04 16:25

Name: Anonymous 2013-01-19 23:51

/prog/ will be spammed continuously until further notice. we apologize for any inconvenience this may cause.

Don't change these.
Name: Email:
Entire Thread Thread List