Ulam Spiral : Sieve of Eratosthenes

by PESakaTFM forked from forked from: Ulam Spiral(ウーラムスパイラル) (diff: 162)
Ulam Spiral
Using Sieve of Eratosthenes is WAY faster then Trial Devision (how I found primes before).  Using this I found all primes less then 6,553,600 in less then 2 seconds.  It took only 3 seconds total to generate the 2560x2560 PNG I'm now using as a desktop background.
♥0 | Line 103 | Modified 2013-03-02 00:18:33 | MIT License
play

ActionScript3 source code

/**
 * Copyright PESakaTFM ( http://wonderfl.net/user/PESakaTFM )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/pJws
 */

// forked from PESakaTFM's forked from: Ulam Spiral(ウーラムスパイラル)
// forked from mex_takagi's Ulam Spiral(ウーラムスパイラル)
/**
 * Ulam Spiral
 * 素数だけに色を付ける。
 * EDIT: PESakaTFM - Using Sieve of Eratosthenes is WAY faster
 */
package
{
    import flash.display.Sprite;
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.utils.ByteArray;
    
    public class PrimeReality extends Sprite
    {
        private const LIMIT:int = 216225;//465 x 465 <- takes no time at all  //6553600;// 2560 x 2560 = 6553600 <- takes about 3 seconds
        
        // Holds Boolean values where true means composite and false means prime
        private var marked:ByteArray;
        private var primeSet:BitmapData;
        
        // Use this if you want to have this as a utility class instead of the main application class.
        public function get bitmapData():BitmapData { return primeSet; }
        
        public function PrimeReality()
        {
            init();
            sieve();
            drawUlamSpiral();
            
            // Add our bitmap to the stage.
            // At this point I used com.adobe.images.PNGEncoder instead to create a PNG file when doing this locally
            var bmp:Bitmap = new Bitmap(primeSet);
            addChild(bmp);
        }
        
        // Create our ByteArray and fill it with zeros
        private function init():void
        {
            marked = new ByteArray();
            marked.length = LIMIT * 0.5 - 1;
            marked.position = 0;
        }
        
        private function sieve():void
        {
            var i:int = 0, 
                cur:int = 0,
                add:int = 0;
            
            // We are only doing odd numbers so we need to double i
            // eg: if i = 1 then ( i<<1 ) + 1 = 3
            //     if i = 2 then ( i<<1 ) + 1 = 5 etc...
            // Also we don't need to sieve numbers once their square is greater then our limit
            // because all multiples less then our square are also multiples of numbers
            // less then our number.
            while(((i<<1)+1)*((i<<1)+1) < LIMIT)
            {
                marked.position = i;
                // If the next number isn't marked yet then we need to mark all it's multiples
                if(!marked.readBoolean())
                {
                    cur = marked.position;
                    add = (cur<<1);
                    // Start at our current number squared
                    marked.position += add*cur + cur - 1;
                    while(marked.bytesAvailable)
                    {
                        marked.writeBoolean(true);
                        marked.position += add;
                    }
                }
                i++;
            }
        }
        
        private function drawUlamSpiral():void
        {
            primeSet = new BitmapData(465, 465, false, 0x000000);
            var tick:int = 1,
                inv:Boolean = true,
                isY:Boolean = true,
                isOdd:Boolean = true,
                i:int = 232,
                j:int = 232,
                count:int = 1;
            
            // Set 1
            primeSet.setPixel(i, j, 0x000000);
            i++;
            // Set 2 as prime.
            primeSet.setPixel(i, j, 0xFF0000);
            
            // marked results start at 3
            marked.position = 0;
            while(true)
            {
                for(count = 1; count<=tick; count++)
                {
                    if(isY)
                        j += inv? -1 : 1;
                    else
                        i += inv? -1 : 1;
                        
                    if(isOdd)
                    {
                        if(!marked.readBoolean())
                            primeSet.setPixel(i, j, 0xFF0000);
                    }
                    isOdd = !isOdd;
                    // As long as we have results keep going.
                    if(!marked.bytesAvailable)
                        return;
                }
                
                //The spiral pattern goes 
                // x += 1 y += -1 | x += -2  y += 2 
                // x += 3 y += -3 | x += 4 y += -4 
                // and so on... So we up the tick every other and 
                // invert on the opposite every other (swapping between X and Y every time)
                if(isY)
                {
                    tick++;
                }
                else
                {
                    inv = !inv;
                }
                isY = !isY;
            }
        }
        
        private function readPrimes():void
        {
            marked.position = 0;
            while(marked.bytesAvailable)
            {
                if(!marked.readBoolean())
                {
                    trace((marked.position<<1)+1);
                }
            }
        }
    }
}