[Mandelbrot] Code Samples/Comparisons
viktoras d.
viktoras at ekoinf.net
Mon Dec 7 07:28:17 EST 2009
Well written! It was a pleasure to read, you need to put at least part
of this text somewhere on the http://www.runrev.com/ website :-)
All the best!
Viktoras
Bill Marriott wrote:
----
> Thanks so much for taking the time to do this! But I think it's a *great*
> example, and I am going to show you why.
>
> Let's start out with a few observations:
>
> - How "practical" is this? I took a closer look at the site.
>
> http://shootout.alioth.debian.org/u64/benchmark.php?test=mandelbrot&lang=all&box=1
>
>
> The goal of the routine is to generate a mandelbrot image in the .PBM
> format. Now, this has some relevance I suppose in testing CPU
> performance,
> but not exactly in the real world. How many programs read PBM, for
> one? None
> on my Mac, but Photoshop and Paint Shop Pro could read it on my
> Windows PC.
> How fun is it to run this program, then load the result up in a graphics
> editor? About as much fun as punch-card, batch programming.
>
> - The original Pascal program (or at least your transliteration of it)
> *has
> a bug!* Give the output file an extension of .pbm and load it into a
> program
> that can read that format. You'll find that the image is skewed more and
> more as the dimensions increase.
>
> http://revuser.com/mandel/orig-600.png
>
> In either Pascal or revTalk, as coded, it's going to be a challenge to
> find
> out where that bug lies.
>
> - It doesn't seem like it was that hard to "transliterate" the original
> Pascal code. I was impressed by the similarities, actually. Even then,
> there
> are portions of your revTalk version that are a little more readable.
> Since
> the vast majority of this is mathematics, and we're not out to reinvent
> algebraic notation, you're right that it's not the best showcase. Math is
> going to be math in any programming language. It's certainly not *less*
> readable. What makes it hard is the Mandelbrot formulas and especially
> the
> encoding into .pbm format (which is what requires all those bit
> operations.
> (Maybe all of the examples from that site are like this?)
>
> - Pascal is considered a pretty "easy" language. Did you check out
> what the
> "solution" looks like in Java?
>
> http://shootout.alioth.debian.org/u64/benchmark.php?test=mandelbrot&lang=javaxint&id=3
>
>
> In C++?
>
> http://shootout.alioth.debian.org/u64/benchmark.php?test=mandelbrot&lang=gpp&id=5
>
>
> Woah! :)
>
> - Well our performance is a is a bit disappointing relative to the
> "command
> line" Pascal version, we *do* beat out variants of PHP, Python, Ruby, and
> Perl, depending on what your processor was versus the one used for the
> benchmarks.
>
> - You were able to add a nice GUI file selector dialog trivially. Now,
> imagine that your goal isn't to produce a .pbm image, but rather to show
> something on-0screen the user could interact with in some way. Things
> get more interesting. This is where Rev starts to shine. The
> further away you get from "pure" math and have to get into user
> interface,
> interaction with local and remote file systems, manipulating data
> sets, and
> business logic issues, the better we look. Our language abstracts the
> operating system, so developers don't need to be concerned with the
> proper
> API to call for common tasks.
>
> - Most (but not all) of us are not using Rev to generate Mandelbrot data.
> We're creating usable applications for business tasks, entertainment and
> educational software, database front-ends, etc. It might well be that
> this
> site/link is all about these kinds of math-intensive routines. I
> didn't look
> too closely at them, admittedly. What I did like about Viktoras'
> suggestion
> was that he found a site with some sample code in a variety of
> languages. I
> think it's healthy for us to look for such examples and discover the
> strengths and weaknesses that emerge when we try to express them in
> revTalk.
>
> My take on the "productivity" equation is that it's not merely the
> number of
> lines of code produced, and it's ultimately not even how fast the code
> executes. In most situations, it's how long it takes to express the
> algorithm, and debug it later on. To encapsulate algorithms in
> flexible user
> interfaces. To take things to an extreme: a routine
> built with machine code or assembly will always execute faster than one
> built in a high-level language. But how many of us could sit down and
> write
> a database front-end in assembly? How long would it take? How usable and
> adaptable would it be?
>
> Another way to look at things is from the artist's viewpoint. There are
> people who will never touch digital photography because they are
> expert at
> the analog process. There are illustrators who will never give up their
> charcoals. There are Lego builders who spurn the non-rectangular
> bricks! And
> thank heaven for them, because I respect the desire for control and
> attention to nuance. In a similar vein, other languages can indeed reward
> sweating details like what kind of number you're trying to store,
> manually
> allocating and releasing memory, etc.
>
> We're not promising to be the tool that lets you rewrite OpenGL or even
> build a competitor to Excel. Instead, we're a tool that complements these
> other technologies, and opens up the idea that -- for example --
> instead of
> spending hours "steering" Excel you might automate your workflow such
> that
> data acquisition, processing, and presentation might all be handled
> with a
> single click.
>
> Enough pontificating eh? Let's get to coding. I'm going to deliver on my
> promise to show you why this actually shows off why Rev is so fantastic.
>
> I was intrigued by this example, because Mandelbrots are beautiful
> things. I
> knew they had something to do with imaginary numbers, that they are
> infinitely variable -- you can zoom in on them forever and not find a
> repeated pattern. But I didn't understand the math, so of course I
> couldn't
> really analyze the original Pascal code effectively.
>
> I had to become a "mini" content expert. So I read up on Mandelbrots. I
> found some useful pages:
>
> http://www.wikihow.com/Plot-the-Mandelbrot-Set-By-Hand
>
> http://www.olympus.net/personal/dewey/mandelbrot.html
>
> and especially
>
> http://steve.hollasch.net/cgindex/misc/mandelbrot.html
>
> Now I was getting somewhere. I learned that a Mandelbrot is a graph where
> the x axis represents a "real" number, and the y axis represents an
> imaginary number (a number involving the element "i" -- which is the
> square
> root of -1). The unique thing about a Mandelbrot set is that you don't
> know
> for sure whether a given coordinate is within the set until you test it
> iteratively. Some coordinates reveal themselves to be part of the set
> quickly, and some not so quickly. The "depth" you have to go in this
> iterative calculation varies for each coordinate. It also involves a
> kind of
> "digital sampling" phenomenon, where things look different depending
> on the
> "resolution" at which you're charting. That hardly covers the whole
> topic,
> but it was enough to give me a handle on what the routines were trying to
> do.
>
> I found George Taylor's page to be much more useful than the Pascal
> code as
> a launch point for understanding how to chart a Mandelbrot in revTalk.
> For
> one thing, he didn't break it up into multiple nested functions, which
> made
> it easier for me to understand. Second, I'm much more familiar with BASIC
> from my early days with the Sinclair ZX81 than I am with Pascal. I
> took his
> code example:
>
> INPUT "Initial Real value of C",CRL
> INPUT "Final Real value of C",CRH
> INPUT "Initial Imaginary value of C",CIL
> INPUT "Final Imaginary value of C",CIH
> INPUT "Iteration limit",MAXITER
> WIDTH=320
> HEIGHT=200
> XSIZE=(CRH-CRL)/(WIDTH-1)
> YSIZE=(CIH-CIL)/(HEIGHT-1)
> FOR Y=0 TO 199
> CI=CIH-Y*YSIZE
> FOR X=0 TO 319
> CR=X*XSIZE+CRL
> REM Now CR, CI are scaled
> REM Do Z<-Z^2+C iteration
> MEMBER=TRUE
> ZR=0
> ZI=0
> FOR I=1 TO MAXITER
> NEWZR=ZR*ZR-ZI*ZI+CR
> NEWZI=2*ZR*ZI+CI
> ZR=NEWZR
> ZI=NEWZI
> Z=SQR(ZR*ZR+ZI*ZI)
> IF Z>2 THEN
> MEMBER=FALSE
> EXIT (exits the FOR loop)
> ENDIF
> NEXT I
> IF MEMBER=TRUE THEN
> PLOT X,Y
> ELSEIF ((MAXITER-I) AND 1)=0 THEN
> PLOT X,Y
> ENDIF
> NEXT X
> NEXT Y
> END
>
> And I did my own revTalk translation, this time making generous use of
> long
> variable names that made more sense to me:
>
> on mouseUp
> put fld "cRstart" into cRstart
> put fld "cRend" into cRend
> put fld "cIstart" into cIstart
> put fld "cIend" into cIend
> put fld "maxIterations" into maxIterations
> put fld "myWidth" into myWidth
> put fld "myHeight" into myHeight
>
> put (cRend-cRstart)/(myWidth-1) into plotWidth
> put (cIend-cIstart)/(myHeight-1) into plotHeight
>
> -- for each y-axis value (scaled)
> repeat with y=0 to myHeight-1
> put cIend-y*plotHeight into cImaginary
>
> -- for each x-axis value (scaled)
> repeat with x=0 to myWidth-1
> put x*plotWidth+cRstart into cReal
>
> -- test the coordinate iteratively
> put true into itBelongs
> put 0 into zReal; put 0 into zImaginary
>
> repeat with i = 1 to maxIterations
>
> put zReal * zReal - zImaginary * zImaginary + cReal into newZreal
> put 2*zReal*zImaginary+cImaginary into newZimaginary
>
> put newZreal into zReal; put newZimaginary into zImaginary
> put sqrt(zReal*zReal+zImaginary*zImaginary) into z
>
> if z>2 then
> put false into itBelongs
> exit repeat
> end if
>
> if z> 2 then exit repeat
>
> end repeat
>
> if itBelongs then
> put i into myPlot[x][y]
> else
> if maxIterations-i > 0 then
> put i into myPlot[x][y]
> end if
> end if
>
> end repeat
> end repeat
> end mouseUp
>
> Now you'll notice that even now I'm able to do something a little
> different
> from Taylor's original algorithm. Where he says, "plot x,y" -- which
> marks
> the pixel at x,y black -- I store i within a multi-dimensional array.
> This
> stores the number of generations it took to determine whether x,y was
> part
> of
> the Mandelbrot set. It will enable me to produce a prettier graph, and
> also
> separates the output code (whether I'm going to create a .pbm file or
> display
> on-screen or do something else from it) from the code used to generate
> the
> Mandelbrot itself.
>
> Showing the image on-screen in Rev was a piece of cake, relative to
> creating
> a .pbm file.
>
> repeat with y=0 to myHeight-1
> repeat with x=0 to myWidth-1
> -- more iterations yields a lighter color
> put numToChar(trunc(myPlot[x][y]/maxIterations*256)) into c
> -- create a shade of grey
> put numToChar(0) & c & c & c after bitmapData
> end repeat
> end repeat
> set the width of image "mandelPlot" to myWidth
> set the height of image "mandelPlot" to myHeight
> set the imageData of image "mandelPlot" to bitmapData
>
> That's because the imageData is simply four whole bytes representing 0
> and
> the R, G, B values of the pixel. Inefficient perhaps, but really
> simple. No
> bitwise
> operations unless I really need to (and I won't need to, since Rev can
> export
> snapshots to a variety of common formats).
>
> It didn't take me much work to display a beautiful, greyscale image of a
> real Mandelbrot on-screen. Plus I had a nice UI that would let me set all
> the parameters of the equation visually. I had one final thing I
> wanted to
> do, and that was to make it so I could "zoom in" on the Mandelbrot to
> explore its infinitely variable nature.
>
> All I did was overlay a graphic on top of the "mandelPlot" image I
> created,
> then attach a script which would make note of where I clicked on it, set
> that as the new origin, and set a new scale around that point.
>
> My "finished" stack is at:
>
> http://revuser.com/mandel/MyMandelbrot.zip
>
> I would say that I got much further along exploring and understanding the
> magic of fractals. In the end, I'm looking at a 300x300 or maybe a
> 900x900
> screen image; I'm not generating 16,000x16,000 bitmaps. So it doesn't
> really
> matter if it takes 3 or 30 seconds to generate. I have a solution that
> has a
> nice user interface so I can tweak various settings and interactively see
> their effect on the graph. I already added niceties like a progress
> bar, and
> zooming.
>
> I could add more customizations like the ability to set the colors I
> want to
> use. The code I have written to generate the Mandelbrot is about as
> clear as
> it could be. (And I'd like to see what the Pascal or C++ code would be to
> replicate my little stack's UI/functionality!)
>
> By analogy, when constructing business applications, the "hard part"
> -- the
> part you have to get right -- should be understanding your business. It
> shouldn't be expressing that business logic/mechanics within code. Rev
> enabled me to focus on the science of Mandelbrots, not the mechanics of
> creating a bitmap. It allowed me to create a program that I could use to
> explore what Mandelbrots are in a beautiful, fun, engaging way. And if I
> ultimately decided that I needed blistering performance in rendering the
> graphs, I could always crack open my Pascal or C++ compiler and make an
> external that did the "heavy lifting" down the road.
>
> Look at it this way -- would an organization prefer a piece of code that
> runs in 3 seconds but does only one thing, and can't be modified except
> by the original coder? To change the parameters of the graph in Pascal,
> one must load up the compiler, edit the right bits of the code, do a
> "build"
> and all that stuff. Or, would you like an application like my stack,
> which
> might
> take 10 times longer to execute, but gives the end user a lot of control
> and flexibility to understand what's going on?
>
> Productivity isn't about processor cycles, and it's not always about
> lines
> of code. It's about how much one can accomplish with the knowledge
> they have.
>
>
>
> _______________________________________________
> use-revolution mailing list
> use-revolution at lists.runrev.com
> Please visit this url to subscribe, unsubscribe and manage your
> subscription preferences:
> http://lists.runrev.com/mailman/listinfo/use-revolution
>
More information about the use-livecode
mailing list