B4J Tutorial Newton Fractals - all in B4J

Johan Schoeman

Expert
Licensed User
Longtime User
Attached the test program, it is yours but with the new new display routine and Logs for the time measurements.
Could not resist - started up and downloaded your sample project. It is very much faster! Thanks for the mod Klaus

Change this line in class NewtonFractal to be as follows:

B4X:
    Dim DEFAULT_ZOOM As Double = 83

It will center the image a bit better.

 

William Lancee

Well-Known Member
Licensed User
Longtime User
#21 is mesmerizing. I know it is a static image, but with my eyes the center is NOT stable, it seems to be continually growing (which is not possible).

I did look at other aspects of the code. The classes are very small and compact.
RootPoint could be a Type, but I doubt that would speed up the calculations.

Arithmetic with Complex Double Numbers take up a lot of CPU cycles.
As @klaus suggested, is it possible to do with none-complex Float or even Int?

In any case, with @klaus changes, the rendering ceases to be a performance factor.
 

Daestrum

Expert
Licensed User
Longtime User
I did play around with your original code, removed the list and just used an int array(x,y) just for the colour and no x,y (done in a loop).
The drawing was faster ( I used pixelwriter on the canvas as that just takes x,y,32bColor ) but the calculation stage is the killer.
 

Daestrum

Expert
Licensed User
Longtime User
Got it down to 58 seconds in release, but doesn't seem as long as it updates the display while waiting.

Some of the changes to the original code

Got rid of the list entirely (not needed and not replaced with anything)
Moved a lot of local variables to global ones (some saved 15 seconds on a run)
Gave compiler hints on the maths - added parenthesis to a lot of the calcs
 

Attachments

  • NewtonFractalViewerDaestrum.zip
    7.5 KB · Views: 123
Last edited:

Johan Schoeman

Expert
Licensed User
Longtime User
Here is another one - it is based on this web posting and this Github project. Have compiled the Github project to the attached Jar - copy the Jar to your additional B4J libs folder (jFractalLibrary.jar).

Have done some minor mods to the inline Java code to bring back an array of Ints and then use it with BitmapCreator to display the image.

This lib only caters for z^n -1 where n > 1

Note the code in the B4J project to alter the Exponent of "z" and to select between color or Grayscale:

Set z^n and Color/Grayscale:
    'set the exponent for z in f(x) = z^exp - 1
    Dim exp As Int = 7                 
    nativeMe.RunMethod("setExp", Array(exp))
  
    'set to True for a color image, set to False for a Grayscale image
    Dim isColor As Boolean = True









z^15 -1 in color


z^15 -1 in Grayscale
 

Attachments

  • jFractalLibrary.jar
    8.6 KB · Views: 108
  • b4jFractalLibrary.zip
    3 KB · Views: 96
Last edited:

klaus

Expert
Licensed User
Longtime User
I have also spent some time on the program.
I replaced the myList by an Array of Ints to store only the colors without the x and y coordinates.
The time to draw the image is now below 30 milliseconds.

I have also looked at the calculation routines but no real improvements.

Attached the last version.
 

Attachments

  • b4aNewtonFractalViewerKlaus2.zip
    7.3 KB · Views: 128

William Lancee

Well-Known Member
Licensed User
Longtime User
@Johan Schoeman Comment the ' #JavaCompilerPath: 22, C:\jdk-22\bin\ in Main

@klaus modifications have reduced the times to the following on my system:

run 1: 5788 msec
run 2: 4880 msec
run 3: 4794 msec
run 4: 4743 msec

Observations:
1. About a second difference between first and subsequent runs
2. I changed Double to Float. No difference in image, but also no difference in times on my 64 bit machine.
3. Overall, great performance
 

William Lancee

Well-Known Member
Licensed User
Longtime User
If you comment out the 2 lines in NewtonFractal and if you add @klaus rendering
B4X:
            Main.drawToIV(x,y,cc)
            If x = width-1 Then Sleep(0)
The times are comparable.

These two lines draw the image one line at a time.
 

klaus

Expert
Licensed User
Longtime User
Daestrom uses also BitmapCreator in his program.
The difference is that in the doInBackground routine he is setting the pixel color directly and updates the image in the ImageView which slows down the drawing.
Which means that the image is updated 560000 times.
I fill an Array of Ints in the doInBackground routine and when the calculation is finished I display the entire image.
 
Last edited:

Johan Schoeman

Expert
Licensed User
Longtime User
#21 is mesmerizing. I know it is a static image, but with my eyes the center is NOT stable, it seems to be continually growing (which is not possible).
I have also noticed it. Interesting indeed how our eyes can play silly buggers with us ?
 

Johan Schoeman

Expert
Licensed User
Longtime User
Can you post the project with your mod?
 

William Lancee

Well-Known Member
Licensed User
Longtime User
I left a stray line in
' Dim temp(width) As Int

Note times vary with parameters.
 
Last edited:

Daestrum

Expert
Licensed User
Longtime User
Now down to 8.9 seconds for the image to complete.
(Thanks @klaus for pointing out the redrawing too often)

Now it a draws a line at a time.
B4X:
#Region Backgroundtask

public Sub doInBackground
	Dim c As JavaObject
	c.Initializestatic("java.awt.Color")
	Log("start")
	Dim st As Long = DateTime.Now
#Region Heavy Task	
	For y = 0 To height - 1
		For x = 0 To  width - 1
			applyNewtonMethod(x,y)
			pnt3.RunMethod("setLocation",Array(x,y))
			c = getColorFromRoot(roots.Get(pnt3))
			Dim cc As Int = c.RunMethod("getRGB",Null)
			Main.bmc.SetColor(x, y, cc)
		Next
		Sleep(0)
		Main.bmc.SetBitmapToImageView(Main.bmc.Bitmap, Main.ImageView1)
	Next
	Main.bmc.SetBitmapToImageView(Main.bmc.Bitmap, Main.ImageView1)
#End Region	
	Log("end : (" & (DateTime.Now - st) & ")ms")
End Sub

#End Region
 

Daestrum

Expert
Licensed User
Longtime User
Changing the line after the Sleep(0) line above to
B4X:
		If y Mod 20 = 0 Then Main.bmc.SetBitmapToImageView(Main.bmc.Bitmap, Main.ImageView1)

Brings the time down to 4.8 seconds. The 20 seems the ideal on my system, a lager number is slower also a smaller number is too.
 

William Lancee

Well-Known Member
Licensed User
Longtime User
@Daestrum
Yes, I tried different block values 1, 2, 3, 4, 5, 10, 20, 40, 50.
I was surprised that it didn't matter very much. You would think that doing rendering every other line would nearly half the time.
Not so. I guess the limit is not the rendering per se but leaving enough non-interruptible time for the computation of the line to complete.

Putting the sleep(0) after the rendering is slightly faster than putting it before.
Presumably, the rendering is going on in a different thread while the computations continue almost immediately.
 

William Lancee

Well-Known Member
Licensed User
Longtime User
My presumption, as usual, was wrong. It is just that the rendering time is very small 538 MICROSeconds per line (on average).
So the total time is mostly due computation: 22 milliseconds average for first two lines and 7 milliseconds average for subsequent lines.

So Java optimization takes place during initial 2 lines of the loop, then settles down.

All in all a pleasure to watch, and thanks to @Johan Schoeman for bringing his art to B4X.

________________________________
All release times on my system
Processor 11th Gen Intel(R) Core(TM) i9-11900K @ 3.50GHz
Installed RAM 32.0 GB (31.9 GB usable)
System type 64-bit operating system, x64-based processor
 

Daestrum

Expert
Licensed User
Longtime User
It's a good exercise to see how miniscule changes to code have a direct bearing on execution speed.
When I first ran the program it took around 150 seconds to fully display the image, now (for me) it takes around 4.8 seconds.
(I have changed a few more places and shaved single digit millis off it further - the 2 * pi is calculated once and plugged in - that alone saved ~60ms overall)

I agree, thank you @Johan Schoeman for posting this - it has been fun.
 
Cookies are required to use this site. You must accept them to continue using the site. Learn more…