Ulam Spiral : Sieve of Eratosthenes
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.
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);
}
}
}
}
}
