Posts: 3,982
Threads: 178
Joined: Apr 2022
Reputation:
220
nagging... that reminds me I got to go
b = b + ...
Posts: 3,982
Threads: 178
Joined: Apr 2022
Reputation:
220
08-30-2024, 12:58 AM
(This post was last modified: 08-30-2024, 01:03 AM by bplus.)
(08-29-2024, 11:35 PM)Pete Wrote: Very cool you found something on par with it. Now all you have to do is lobby for it as an alternative! Didn't we work together with Bill and Steve on some ellipse fill gold standard years ago?
Pete
- The Three Musketeers and the Theoretical Musketeer
yes we did, that's when we drove Bill nutz and he posted his slanted ellipse version without consulting, fortunately it was good!
BTW FC3 is working well in QB64 v2.1 once I tested without the browser on both with Checking On and OFF
b = b + ...
Posts: 2,183
Threads: 222
Joined: Apr 2022
Reputation:
104
Code: (Select All)
Sub fcirc (CX As Integer, CY As Integer, R As Integer, C As _Unsigned Long)
Dim Radius As Integer, RadiusError As Integer
Dim X As Integer, Y As Integer
Radius = Abs(R): RadiusError = -Radius: X = Radius: Y = 0
If Radius = 0 Then PSet (CX, CY), C: Exit Sub
Line (CX - X, CY)-(CX + X, CY), C, BF
While X > Y
RadiusError = RadiusError + Y * 2 + 1
If RadiusError >= 0 Then
If X <> Y + 1 Then
Line (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
Line (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
End If
X = X - 1
RadiusError = RadiusError - X * 2
End If
Y = Y + 1
Line (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
Line (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
Wend
End Sub
Probably just for style points, or do you think changing the conditional statement slows it down or speeds it up?
Code: (Select All)
Sub fcirc (CX As Integer, CY As Integer, R As Integer, C As _Unsigned Long)
Dim Radius As Integer, RadiusError As Integer
Dim X As Integer, Y As Integer
Radius = Abs(R): RadiusError = -Radius: X = Radius: Y = 0
If Radius Then
Line (CX - X, CY)-(CX + X, CY), C, BF
While X > Y
RadiusError = RadiusError + Y * 2 + 1
If RadiusError >= 0 Then
If X <> Y + 1 Then
Line (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
Line (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
End If
X = X - 1
RadiusError = RadiusError - X * 2
End If
Y = Y + 1
Line (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
Line (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
Wend
Else
PSet (CX, CY), C
End If
End Sub
or...
Code: (Select All)
Sub fcirc (CX As Integer, CY As Integer, R As Integer, C As _Unsigned Long)
Dim RadiusError, X, Y As Integer
If Abs(R) Then
X = Abs(R): Y = 0: RadiusError = -X
Line (CX - X, CY)-(CX + X, CY), C, BF
While X > Y
RadiusError = RadiusError + Y * 2 + 1
If RadiusError >= 0 Then
If X <> Y + 1 Then
Line (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
Line (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
End If
X = X - 1
RadiusError = RadiusError - X * 2
End If
Y = Y + 1
Line (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
Line (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
Wend
Else
PSet (CX, CY), C
End If
End Sub
Pete
Shoot first and shoot people who ask questions, later.
Posts: 2,697
Threads: 328
Joined: Apr 2022
Reputation:
217
Play around with a pre-calculated set of coordinates:
Code: (Select All)
Screen _NewImage(1200, 700, 32)
_Define A-Z As LONG
Dim Shared CircleXPos(500, 500)
PreCalcX
Print
Print " fcirc fc fc3 fc4 precalc"
Print
For i = 1 To 10
'time the fcirc sub
t## = Timer(0.001)
For c = 1 To 15000
fcirc 400, 400, 100, _RGB(128, 128, 128)
Next
t1## = Timer(0.001) - t##
'time the fc sub
t## = Timer(0.001)
For c = 1 To 15000
fc 400, 400, 100, _RGB(255, 128, 128)
Next
t2## = Timer(0.001) - t##
'time the fc3 sub
t## = Timer(0.001)
For c = 1 To 15000
FC3 400, 400, 100, _RGB(128, 255, 128)
Next
t3## = Timer(0.001) - t##
'time the fc4 sub
t## = Timer(0.001)
For c = 1 To 15000
fc4 400, 400, 100, _RGB(128, 128, 255)
Next
t4## = Timer(0.001) - t##
'time the Steve sub
t## = Timer(0.001)
For c = 1 To 15000
StevePreCalcCircle 400, 400, 100, _RGB(255, 0, 0)
Next
t5## = Timer(0.001) - t##
Print t1##, t2##, t3##, t4##, t5##
Next
Sub fc (cx, cy, r, clr&)
For y = -r To r
x = Int(Sqr(r * r - y * y))
Line (cx - x, cy + y)-(cx + x, cy + y), clr&, BF
Next
End Sub
Sub fc4 (cx, cy, r, clr&)
r2 = r * r
For y = 0 To r
y2 = y * y
'If y2 <= r2 Then
x = Int(Sqr(r2 - y2))
Line (cx - x, cy - y)-(cx + x, cy - y), clr&, BF
Line (cx - x, cy + y)-(cx + x, cy + y), clr&, BF
'End If
Next
End Sub
Sub FC3 (cx, cy, r, clr&)
Line (cx - r, cy)-(cx + r, cy), clr&, BF
y = 1
r2 = r * r ' Dav mod
While y <= r
y2 = y * y
If y2 < r2 Then
x = Int(Sqr(r2 - y2))
Line (cx - x, cy + y)-(cx + x, cy + y), clr&, BF
Line (cx - x, cy - y)-(cx + x, cy - y), clr&, BF
End If
y = y + 1
Wend
End Sub
Sub fcirc (CX As Integer, CY As Integer, R As Integer, C As _Unsigned Long)
Dim Radius As Integer, RadiusError As Integer
Dim X As Integer, Y As Integer
Radius = Abs(R): RadiusError = -Radius: X = Radius: Y = 0
If Radius = 0 Then PSet (CX, CY), C: Exit Sub
Line (CX - X, CY)-(CX + X, CY), C, BF
While X > Y
RadiusError = RadiusError + Y * 2 + 1
If RadiusError >= 0 Then
If X <> Y + 1 Then
Line (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
Line (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
End If
X = X - 1
RadiusError = RadiusError - X * 2
End If
Y = Y + 1
Line (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
Line (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
Wend
End Sub
Sub StevePreCalcCircle (cx, cy, r, clr&)
$Checking:Off
For y = 0 To r
x = CircleXPos(r, y)
Line (cx - x, cy - y)-(cx + x, cy - y), clr&, BF
Line (cx - x, cy + y)-(cx + x, cy + y), clr&, BF
Next
$Checking:On
End Sub
Sub PreCalcX
For r = 0 To 500 'circles with a radius from 0 to 500
r2 = r * r
For y = 0 To r
y2 = y * y
x = Int(Sqr(r2 - y2))
CircleXPos(r, y) = x
Next
Next
End Sub
Note that I just translated the easiest to modify routine (f4) to make use of just doing a lookup, rather than the math on the spot.
Performance here varies widely for me here, based on optimization flags, variable types (change that _DEFINE type a few times), and other such things...
Which leads me to the conclusion that you can only optimize down so much, and then you're defeating the purpose and over analyzing it. Speeds are going to always vary based on OS/memory/system/background processes/blah/blah/blah...
Just because one method works fastest on my machine, doesn't mean it's going to be the fastest on yours. If you TRULY have time-critical tasks, the best you can do is head to the PC/Laptop/Machine that needs to run that task, and then test and benchmark all those thousands of different variables and configurations that can come into play, and then you micro-optimize for that *one particular machine*.
It's like professional, Olympic level shooting and the care they take to perfectly bore and set up each rifle and sight, and then how they weigh out each grain of gunpowder that they manually load their ammo with, after the choose the perfect... blah blah and blah.... Compared to Joe Smoe who has a 20-year old rifle that was cleaned and oiled sometime in the last ten years, with ammo that's been on a shelf for the last five to forty years, and a scope that was kinda... maybe... sighted in probably about six years ago.
Sometimes you just have to say, "Meh, close enough," and then let it go as long as it'll still drop that deer at 100 yards and put food on your table.
Posts: 2,183
Threads: 222
Joined: Apr 2022
Reputation:
104
Yes, I recall how Bill didn't think using SQR could possibly work, until I did exactly that. Mostly thanks to _INTEGER64, it worked.
That reminds me....
Code: (Select All)
Sub FC3 (cx, cy, r, clr&)
Line (cx - r, cy)-(cx + r, cy), clr&, BF
y = 1
r2 = r * r ' Dav mod
While y <= r
y2 = y * y
If y2 < r2 Then
x = Int(Sqr(r2 - y2))
Line (cx - x, cy + y)-(cx + x, cy + y), clr&, BF
Line (cx - x, cy - y)-(cx + x, cy - y), clr&, BF
End If
y = y + 1
Wend
End Sub
Could be modified to...
Code: (Select All)
Sub FC3 (cx, cy, r, clr&)
Dim x as Integer
Line (cx - r, cy)-(cx + r, cy), clr&, BF
r2 = r * r ' Dav mod
Do Until y > r
y = y + 1
y2 = y * y
If y2 < r2 Then
x = Sqr(r2 - y2)
Line (cx - x, cy + y)-(cx + x, cy + y), clr&, BF
Line (cx - x, cy - y)-(cx + x, cy - y), clr&, BF
End If
Loop
End Sub
Pete
Shoot first and shoot people who ask questions, later.
Posts: 2,697
Threads: 328
Joined: Apr 2022
Reputation:
217
(08-30-2024, 04:21 AM)Pete Wrote: Yes, I recall how Bill didn't think using SQR could possibly work, until I did exactly that. Mostly thanks to _INTEGER64, it worked.
That reminds me....
Code: (Select All)
Sub FC3 (cx, cy, r, clr&)
Line (cx - r, cy)-(cx + r, cy), clr&, BF
y = 1
r2 = r * r ' Dav mod
While y <= r
y2 = y * y
If y2 < r2 Then
x = Int(Sqr(r2 - y2))
Line (cx - x, cy + y)-(cx + x, cy + y), clr&, BF
Line (cx - x, cy - y)-(cx + x, cy - y), clr&, BF
End If
y = y + 1
Wend
End Sub
Could be modified to...
Code: (Select All)
Sub FC3 (cx, cy, r, clr&)
Dim x as Integer
Line (cx - r, cy)-(cx + r, cy), clr&, BF
r2 = r * r ' Dav mod
Do Until y > r
y = y + 1
y2 = y * y
If y2 < r2 Then
x = Sqr(r2 - y2)
Line (cx - x, cy + y)-(cx + x, cy + y), clr&, BF
Line (cx - x, cy - y)-(cx + x, cy - y), clr&, BF
End If
Loop
End Sub
Pete
My thinking was to make use of something like this:
Code: (Select All) Sub PreCalcX
For r = 0 To 500 'circles with a radius from 0 to 500
r2 = r * r
For y = 0 To r
y2 = y * y
x = Int(Sqr(r2 - y2))
CircleXPos(r, y) = x
Next
Next
End Sub
Precalculate all that math, and get rid of it completely. Just one quick lookup for that value rather than multiplying and all that.
It would seem to me that *this* should be much faster than everything else is:
Code: (Select All) Sub StevePreCalcCircle (cx, cy, r, clr&)
$Checking:Off
For y = 0 To r
x = CircleXPos(r, y)
Line (cx - x, cy - y)-(cx + x, cy - y), clr&, BF
Line (cx - x, cy + y)-(cx + x, cy + y), clr&, BF
Next
$Checking:On
End Sub
Just look up that one value from a precalculated list. And yet... almost impossibly... it's often not the fastest method we have available, when resting those speeds all side by side!
Are our arrays that slow?
Is the timer routine screwing up somewhere?
WTF is going on to give us the figures that we're getting??
I have no clue. I just found the results upper astonishing.
Posts: 2,697
Threads: 328
Joined: Apr 2022
Reputation:
217
A few changes to make comparing the speeds and overall results a little easier to understand the overall differences:
Code: (Select All)
Screen _NewImage(1200, 700, 32)
_Define A-Z As LONG
Dim Shared CircleXPos(500, 500)
PreCalcX
Print
Print " fcirc fc fc3 fc4 precalc"
Print
For i = 1 To 10
'time the fcirc sub
t## = Timer(0.001)
For c = 1 To 15000
fcirc 400, 400, 200, _RGB(128, 128, 128)
Next
t1## = Timer(0.001)
'time the fc sub
For c = 1 To 15000
fc 400, 400, 200, _RGB(255, 128, 128)
Next
t2## = Timer(0.001)
'time the fc3 sub
For c = 1 To 15000
FC3 400, 400, 200, _RGB(128, 255, 128)
Next
t3## = Timer(0.001)
'time the fc4 sub
For c = 1 To 15000
fc4 400, 400, 200, _RGB(128, 128, 255)
Next
t4## = Timer(0.001)
'time the Steve sub
For c = 1 To 15000
StevePreCalcCircle 400, 400, 200, _RGB(255, 0, 0)
Next
t5## = Timer(0.001)
Print t1## - t##, t2## - t1##, t3## - t2##, t4## - t3##, t5## - t4##
f1## = f1## + t1## - t##
f2## = f2## + t2## - t1##
f3## = f3## + t3## - t2##
f4## = f4## + t4## - t3##
f5## = f5## + t5## - t4##
Next
Print
Print f1##, f2##, f3##, f4##, f5##
Sub fc (cx, cy, r, clr&)
For y = -r To r
x = Int(Sqr(r * r - y * y))
Line (cx - x, cy + y)-(cx + x, cy + y), clr&, BF
Next
End Sub
Sub fc4 (cx, cy, r, clr&)
r2 = r * r
For y = 0 To r
y2 = y * y
'If y2 <= r2 Then
x = Int(Sqr(r2 - y2))
Line (cx - x, cy - y)-(cx + x, cy - y), clr&, BF
Line (cx - x, cy + y)-(cx + x, cy + y), clr&, BF
'End If
Next
End Sub
Sub FC3 (cx, cy, r, clr&)
Line (cx - r, cy)-(cx + r, cy), clr&, BF
y = 1
r2 = r * r ' Dav mod
While y <= r
y2 = y * y
If y2 < r2 Then
x = Int(Sqr(r2 - y2))
Line (cx - x, cy + y)-(cx + x, cy + y), clr&, BF
Line (cx - x, cy - y)-(cx + x, cy - y), clr&, BF
End If
y = y + 1
Wend
End Sub
Sub fcirc (CX As Integer, CY As Integer, R As Integer, C As _Unsigned Long)
Dim Radius As Integer, RadiusError As Integer
Dim X As Integer, Y As Integer
Radius = Abs(R): RadiusError = -Radius: X = Radius: Y = 0
If Radius = 0 Then PSet (CX, CY), C: Exit Sub
Line (CX - X, CY)-(CX + X, CY), C, BF
While X > Y
RadiusError = RadiusError + Y * 2 + 1
If RadiusError >= 0 Then
If X <> Y + 1 Then
Line (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
Line (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
End If
X = X - 1
RadiusError = RadiusError - X * 2
End If
Y = Y + 1
Line (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
Line (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
Wend
End Sub
Sub StevePreCalcCircle (cx, cy, r, clr&)
$Checking:Off
For y = 0 To r
x = CircleXPos(r, y)
Line (cx - x, cy - y)-(cx + x, cy - y), clr&, BF
Line (cx - x, cy + y)-(cx + x, cy + y), clr&, BF
Next
$Checking:On
End Sub
Sub PreCalcX
For r = 0 To 500 'circles with a radius from 0 to 500
r2 = r * r
For y = 0 To r
y2 = y * y
x = Int(Sqr(r2 - y2))
CircleXPos(r, y) = x
Next
Next
End Sub
From this, on my machine, the precalculated coordinate look-up is the quickest, with fcirc right behind and everything else being a little slower. This is with the latest QB64PE version and with the optimization flag set in compiler options. I don't know if others will see the same style results or not, depending on however it compiles and optimizes on their systems.
Posts: 3,982
Threads: 178
Joined: Apr 2022
Reputation:
220
Steve yours has same flaw as Dav's FC4 from which you made youirs
Code: (Select All) Screen _NewImage(1200, 700, 32)
_Define A-Z As LONG
Dim Shared CircleXPos(500, 500)
PreCalcX
StevePreCalcCircle 600, 350, 300, _RGB32(0, 0, 255, 100)
Sub StevePreCalcCircle (cx, cy, r, clr&)
$Checking:Off
For y = 0 To r
x = CircleXPos(r, y)
Line (cx - x, cy - y)-(cx + x, cy - y), clr&, BF
Line (cx - x, cy + y)-(cx + x, cy + y), clr&, BF
Next
$Checking:On
End Sub
Sub PreCalcX
For r = 0 To 500 'circles with a radius from 0 to 500
r2 = r * r
For y = 0 To r
y2 = y * y
x = Int(Sqr(r2 - y2))
CircleXPos(r, y) = x
Next
Next
End Sub
Does not work for transparent colors.
Both Steve and Pete are also using Dav's messed up FC3 code.
I've already pointed out these 2 things with Dav's code.
b = b + ...
Posts: 2,697
Threads: 328
Joined: Apr 2022
Reputation:
217
(08-30-2024, 02:17 PM)bplus Wrote: Steve yours has same flaw as Dav's FC4 from which you made youirs
Code: (Select All) Screen _NewImage(1200, 700, 32)
_Define A-Z As LONG
Dim Shared CircleXPos(500, 500)
PreCalcX
StevePreCalcCircle 600, 350, 300, _RGB32(0, 0, 255, 100)
Sub StevePreCalcCircle (cx, cy, r, clr&)
$Checking:Off
For y = 0 To r
x = CircleXPos(r, y)
Line (cx - x, cy - y)-(cx + x, cy - y), clr&, BF
Line (cx - x, cy + y)-(cx + x, cy + y), clr&, BF
Next
$Checking:On
End Sub
Sub PreCalcX
For r = 0 To 500 'circles with a radius from 0 to 500
r2 = r * r
For y = 0 To r
y2 = y * y
x = Int(Sqr(r2 - y2))
CircleXPos(r, y) = x
Next
Next
End Sub
Does not work for transparent colors.
Both Steve and Pete are also using Dav's messed up FC3 code.
I've already pointed out these 2 things with Dav's code.
Aye. I wasn't trying to make an image perfect circle. I was simply testing the concept of how much a precalculated-point system would speed up a circle.
What we have is already quick enough and optimized enough for my needs. The time difference in these routines is really fairly negligible under most use cases. It shouldn't be too difficult to adjust that to accommodate for the overlap.
Code: (Select All) Sub StevePreCalcCircle (cx, cy, r, clr&)
$Checking:Off
For y = 0 To r
x = CircleXPos(r, y)
Line (cx - x, cy - y)-(cx + x, cy - y), clr&, BF
IF y > 0 THEN Line (cx - x, cy + y)-(cx + x, cy + y), clr&, BF
Next
$Checking:On
End Sub
Something as simple as the above should fix it, I'd think -- though it's untested. The concept, at least, seems sound to me: If your +y and -y are 0, then you only need to draw the line once, not twice.
Posts: 250
Threads: 44
Joined: May 2022
Reputation:
28
Bplus, color has data type unsigned long. You use the long data type in FC (variable clr&). Maybe that's why it doesn't work for you with transparent colors.
|