## Circles

General FreeBASIC programming questions.
albert
Posts: 5916
Joined: Sep 28, 2006 2:41
Location: California, USA
Richard your loopy version matains a single circle up to 1 trillion mag after that it at ten trillion i had to add the sqr() function and increase the loops to 53 at 100 trillion i had to add a second sqr() and increase the loops to 55 didn't do much above 53 only small difference.

But without the sqr() it was over and under the circle. were getting processor noise in the mul and div circuits (AMD athlon 64 2GHZ that i'm running on.) i divide 387 by 100 and get 3.9 instead of 3.87 (hmmm?????)

Anyway its accurate to 14 decimal places, degree wise.
getting 1's and 7's in the 15 decimal place instead of 0's and 9's.

it seems to hold a tighter pattern if you set c =1 instead of c=k???

Can you do a full CORDIC implementation for us?
Richard
Posts: 3030
Joined: Jan 15, 2007 20:44
Location: Australia
You should not be applying normalization to the loopy version because it converts radial noise into angular noise. It is better to have balanced noise. C = k corrects the scale exactly without the need for normalization, that is why k is calculated with the table, so it corrects for the table scale exactly.

CORDIC is not applicable to your calculator because you could not generate the lookup table to sufficient digits quickly.

CORDIC in FB is slower than the CPU/FPU instructions, there is no advantage to be gained by using CORDIC in FB. It is only when in an approximation short form, such as n = 8 thru 17 that it is worth considering, but it is quicker even in that case to use a truncated power series because the CPU/FPU has a parallel multiplier.
albert
Posts: 5916
Joined: Sep 28, 2006 2:41
Location: California, USA
Richard maybe you can doo something with this formula to get it closer.

I think it needs to be .99995 at 1 and .9003 at 50 and .36..... at 100

I can't seem to get the multiplier correct.

If you can help that would be great!

Code: Select all

'================================================================
' Albert's .000943 in green
'  approximations measured relative to the reference circle ... blue
Const As Double mag = 100  ' magnification of errors
'================================================================
Dim As Double t, tt, grad, q, s, c, dx, dy, x, y, r = 1.1
Dim As Double sqr_root

Screen 19
Dim As Integer w, h, depth
Screeninfo w, h, depth
Window (-r * w / h, -r) - (r * w / h, r)  ' maintain pixel aspect

'----------------------------------------------------------------
Line(-c, 0)-(c, 0), 1   ' x axis
Line(0, -c)-(0, c), 1   ' y axis
Const As Double Pion2 = 2 * Atn(1)
For t = 0 To 4 * Pion2 Step Pion2 / 1000
x = Cos(t)
y = Sin(t)
Pset(x, y), 1       ' reference circle
Pset(x*.1, y*.1), 1 ' one tenth of circle at centre
Next t

'================================================================
'Albert's .000943 formula for a 200 degree pi
dim as double deg = atn(1)/100
mul = .00179
For grad = 0 To 100 Step 5

sarc = deg * inc
carc = deg * (200-inc)

s = sarc * ((1- (sgrad2 * mul )) * .01)
c = carc * ((1- (cgrad2 * mul )) * .01)

sqr_root=sqr(c*c+s*s)
s=s/sqr_root
c=c/sqr_root
'----------------------------------------
r = 1 + mag * (Sqr(c*c + s*s) - 1)   ' magnify radius error
x = c * r
y = s * r
Pset (+x, -y), 10
Pset (+x, +y), 10
Pset (-x, -y), 10
Pset (-x, +y), 10
'line(0,0)-(+x,-y),10
'line(0,0)-(+x, y),10
'line(0,0)-(-x,-y),10
'line(0,0)-(-x, y),10
print atan2(s,c)*100/(deg*200)
t = grad * Pion2 / 100
dx = c - Cos(t)
dy = s - Sin(t)
Circle(mag * dx, mag * dy), 0.01, 10   ' plot the scatter

'================================================================
Sleep
'================================================================

Have a nice ThanksGiving everybody!!
Richard
Posts: 3030
Joined: Jan 15, 2007 20:44
Location: Australia
@Albert.
Normalisation reduces radius noise by increasing phase noise. It also uses a slow square root. Radius normalisation hides the real radius problems with your approximation. Fast square root approximations have greater errors than the sine and cosine approximations. Therefore normalisation using fast square root approximations will increase phase and often peak amplitude noise. Normalisation using square root is an inherently slow process.

By using normalisation you convolute the radius error into a more complex phase error. Phase error is much harder to remove than radius error, so once you introduce normalisation you cannot advance and your attempt is finished.

Any approximation that employs a square root will be much too slow. You can get the same degree of curvature from any second order function such as squaring which is very much quicker, just look at the graph of a square root from the side and you will see it is a square. Think of square roots as going backward when you need to go forward. They are a function of last resort.

The theory of numerical approximation is a well developed art. The application of that theory generates approximations that optimise the balance of accuracy against time and complexity. You cannot expect to randomly stumble onto a perfect result, Chebychev optimisation will outrun you every time.

Your latest approximation is only second order so it cannot get anywhere near my fourth/fifth order constant parameter version, yet your version takes longer already. I would improve your latest in speed and accuracy by replacing it with my constant parameter version.

You need to question why you are pursuing approximations in a situation where you have claimed that precision is required. Your equations can never be more than approximations and can therefore never be of any use for your arbitrary precision calculator that requires precision certainty beyond 1000 digits.
albert
Posts: 5916
Joined: Sep 28, 2006 2:41
Location: California, USA
Your loopy version uses the atn() function which i believe returns the radians of a tangent. and is only accurate to 14 decimal places.
I'd might as well just use sin() and cos() in the calculator.

What i'm trying to do is peg the degree marks and hopefully it makes a circle or i can use your normalization to make it a circle. but pegging the degree marks is important.

Here is my attempt to correct the last formula.
It keeps the scatter plot within the circle at various step sizes. at 100 mag.

At 1000 mag its over the circle.

Code: Select all

'================================================================
' Albert's .0018 in green
'  approximations measured relative to the reference circle ... blue
Const As Double mag = 100  ' magnification of errors
'================================================================
Dim As Double t, tt, grad, q, s, c, dx, dy, x, y, r = 1.1
Dim As Double sqr_root

Screen 19
Dim As Integer w, h, depth
Screeninfo w, h, depth
Window (-r * w / h, -r) - (r * w / h, r)  ' maintain pixel aspect

'----------------------------------------------------------------
Line(-c, 0)-(c, 0), 1   ' x axis
Line(0, -c)-(0, c), 1   ' y axis
Const As Double Pion2 = 2 * Atn(1)
For t = 0 To 4 * Pion2 Step Pion2 / 1000
x = Cos(t)
y = Sin(t)
Pset(x, y), 1       ' reference circle
Pset(x*.1, y*.1), 1 ' one tenth of circle at centre
Next t

'================================================================
'Albert's .0018 formula for a 200 degree pi
dim as double steps= 5
dim as double deg = atn(1)/100
mul = .00181483069342619
for grad = 0 To 100 Step steps

sarc = deg * inc
carc = deg * (200-inc)

s = sarc * ((1- (sgrad2 * mul )) * .01)
c = carc * ((1- (cgrad2 * mul )) * .01)

if grad >=0  and grad <=50  then mul = mul - (1/(800000*(1/steps)))
if grad > 50 and grad <=100 then mul = mul + (1/(700000*(1/steps)))

sqr_root=sqr(c*c+s*s)
s=s/sqr_root
c=c/sqr_root
'----------------------------------------
r = 1 + mag * (Sqr(c*c + s*s) - 1)   ' magnify radius error
x = c * r
y = s * r
Pset (+x, -y), 10
Pset (+x, +y), 10
Pset (-x, -y), 10
Pset (-x, +y), 10
'line(0,0)-(+x,-y),10
'line(0,0)-(+x, y),10
'line(0,0)-(-x,-y),10
'line(0,0)-(-x, y),10
print atan2(s,c)*100/(deg*200)
t = grad * Pion2 / 100
dx = c - Cos(t)
dy = s - Sin(t)
Circle(mag * dx, mag * dy), 0.01, 10   ' plot the scatter

'================================================================
Sleep
'================================================================

bfuller
Posts: 338
Joined: Jun 02, 2007 12:35
Location: Sydney, Australia
@Albert

Don't forget that you are using the inbuilt Freebasic Cos and Sin functions which themselves have a finite accuracy to calculate your dx and dy values for the scatterplot. Magnification does not make it more accurate.
albert
Posts: 5916
Joined: Sep 28, 2006 2:41
Location: California, USA
@ bfuller

Can you come up with a formula to closely approximate the sine and cosine functions.
It doesn't really matter if it makes a good circle, we can use the dividing s and c by the sqr(c*c+s*s) to force a circle, we just need the degrees to be correct.

I tried playing around with Richards loopy version and plugged in radians of aa instead of atn(aa) and got bad results. I'll try again, i'm sure theres a method to figure the radians of a tangent besides the atn().
Richard
Posts: 3030
Joined: Jan 15, 2007 20:44
Location: Australia
@Albert. If by “pegging the degree marks” you mean eliminating the phase error, then it can not be done with an approximation. You must use a power series.

The loopy version is CORDIC and will NOT work with your variable-precision calculator because you could not calculate the table to sufficient precision. How many times do you have to be told?

I wrote...
You need to question why you are pursuing crude approximations in a situation where you have claimed that precision is required.
bfuller
Posts: 338
Joined: Jun 02, 2007 12:35
Location: Sydney, Australia
Albert, you are tying yourself in knots. You want to:
closely approximate the sine and cosine functions

but state:
It doesn't really matter if it makes a good circle

Of course it matters-------------if it doesn't make a "good" circle, its not a "close" approximation of sine and cosine.

And as for
i'm sure theres a method to figure the radians of a tangent besides the atn()

yes there is, its another infinite series just like cos and sin.
albert
Posts: 5916
Joined: Sep 28, 2006 2:41
Location: California, USA
It took Richard 15 pages of posts to come up with his loopy version.
It took richard 15 pages of posts to come up with the normalization s,c=s,c / sqr(c*c+s*s) to correct radius.

What i'm trying to accomplish, i already did several yrs ago whae i wrot the first Pro-Draw for QBasic I just can't remember how I allowed for a user to rotate a line on the screen to a particular degree with soines and cosines, It can be done, I remember that i counted the pixels per inch H and V and somehow manipulated x and y to come up with the new coords for X and Y with a pi/180 step between increments.

I asked Richard how to determine X,Y when you have X2,Y2 and a chord? He came up with the sine,cosine formula. There is a way to rework the chord formula to get X1,Y1 from the X2,Y2 and chord and angle.But I can't remember how I did it.
At the time i didn't know anything about sines or cosines the only thing i knew is what my father told me that a sqr + b sqr = c sqr and tangent times dist = height. armed with those few thoings i accomplished the task but can't remember how i did it.

You guys have no business posting here if all you got is sarcasm and negative ideas about the matter. It can be done I did it once and will do it again I hope soon!
Richard
Posts: 3030
Joined: Jan 15, 2007 20:44
Location: Australia
@ Albert. Like a kitten with two balls of wool, you are tangling yourself in both while tangling the two together.

Are you trying to write sine, cosine and tangent code for your arbitrary precision calculator, or are you trying to draw circles on the screen quickly. The two are diametrically opposed. They have very different solutions.

If you keep moving the goal posts then you only generate tangled confusion.

So which is it, precision? or approximation?
albert
Posts: 5916
Joined: Sep 28, 2006 2:41
Location: California, USA
using the s,c = s,c /sqr(c*c+s*s) we can force the sine and cosine onto the circle. We got that much solved. we can make a circle out of a square.

Just try deg*.01 and (100-deg)*.01 as the sine and cosine and apply the sqr() and you get a perfect radius circle. but the degree marks are off.

Now its the degrees we need to solve.

As long as the degrees are correct the formula can make any shape it makes and we can force it to be a circle.

If anyone can come up with the correct degree ratios we can make a perfect circle.

I've farted around with my latest formula and am getting pretty close.
If you rem out the s,c=s,c / sqr_root you can see it does not make a circle but the degrees are close. I think i might have to use the atan2 function to create a look-up table.

its about as close as Richards first constant parameter version.
but not perfect yet.

Code: Select all

'================================================================
' Albert's .0018 in green
'  approximations measured relative to the reference circle ... blue
Const As Double mag = 100  ' magnification of errors
'================================================================
Dim As Double t, tt, grad, q, s, c, dx, dy, x, y, r = 1.1
Dim As Double sqr_root

Screen 19
Dim As Integer w, h, depth
Screeninfo w, h, depth
Window (-r * w / h, -r) - (r * w / h, r)  ' maintain pixel aspect

'----------------------------------------------------------------
Line(-c, 0)-(c, 0), 1   ' x axis
Line(0, -c)-(0, c), 1   ' y axis
Const As Double Pion2 = 2 * Atn(1)
For t = 0 To 4 * Pion2 Step Pion2 / 1000
x = Cos(t)
y = Sin(t)
Pset(x, y), 1       ' reference circle
Pset(x*.1, y*.1), 1 ' one tenth of circle at centre
Next t

'================================================================
'Albert's .0018 formula for a 200 degree pi
dim as double steps= 1
dim as double deg = atn(1)/100
mul = .00181
for grad = 0 To 100 Step steps

sarc = deg * inc
carc = deg * (200-inc)

s = sarc * ((1- (sgrad2 * mul )) * .01)
c = carc * ((1- (cgrad2 * mul )) * .01)

if grad <=50 then mul = mul - (( 1 / (900000*(1/steps)) ) )
if grad > 50 then mul = mul + (( 1 / (900000*(1/steps)) ) )

sqr_root=sqr(c*c+s*s)
s=s/sqr_root
c=c/sqr_root
'----------------------------------------
r = 1 + mag * (Sqr(c*c + s*s) - 1)   ' magnify radius error
x = c * r
y = s * r
Pset (+x, -y), 10
Pset (+x, +y), 10
Pset (-x, -y), 10
Pset (-x, +y), 10
'line(0,0)-(+x,-y),10
'line(0,0)-(+x, y),10
'line(0,0)-(-x,-y),10
'line(0,0)-(-x, y),10
'print atan2(s,c)*100/(deg*200)
t = grad * Pion2 / 100
dx = c - Cos(t)
dy = s - Sin(t)
Circle(mag * dx, mag * dy), 0.01, 10   ' plot the scatter

'================================================================
Sleep
'================================================================

albert
Posts: 5916
Joined: Sep 28, 2006 2:41
Location: California, USA
Richard wrote:@ Albert. Like a kitten with two balls of wool, you are tangling yourself in both while tangling the two together.

Are you trying to write sine, cosine and tangent code for your arbitrary precision calculator, or are you trying to draw circles on the screen quickly. The two are diametrically opposed. They have very different solutions.

If you keep moving the goal posts then you only generate tangled confusion.

So which is it, precision? or approximation?

Richard we need precise degrees. with the normalization we can force a circle but we need correct degrees.

In my above (last posted) formula I noticed that when i played around with the mul variable and dialed in 1 degree i also got 99 degrees correct so it needs 50 numbers to get 100 correct, The numbers are opposites.
when i played around and dialed in 2 degrees i got 98 also.
There is a thing about varied step sizes that prohibits a table if the table only holds 50 numbers and you want 1.1 degree the whole thing falls apart.
In my analysis of sines i found that the increments seem to follow a pattern,where the decrease in size i think can be tied to a specific percentage of the last increment. I think its around .99994% of the previous increment size.

I hope you can come up with a formula to get correct degree values as I'm having little success on my own. everything i've done so far in this topic has been somewhat of a flop.

Thanks for all your input on this topic. You've been a great help so far.
first with the sine plotter and then the scatter plotter and your formulas.
albert
Posts: 5916
Joined: Sep 28, 2006 2:41
Location: California, USA
The sine and cosine functions are only accurate to 15 decimal places.
at 1 quadrillion magnification, the sin(),cos() errors can be seen.

1,000,000,000,000,000 magnification thats 16 decimal places.

I'm beginning to think that your right about the power series being the only way. I tried to do the .99994 times the previous increment and wound up at 50.02 degrees and there was only 22 plots above 50 degrees. I was thinking that if you draw lines from the degrees straight accross to the vertical,that each increment was 99.994 percent of the previous increment but it seems that the percentages are all different from each other which does not make sense, it should be a steady cascade from .0157 to 1 with each increment being a precise percentage of the previous.

Code: Select all

'================================================================
'  approximations measured relative to the reference circle ... blue
Const As Double mag = 1000000000000000  '1 quadrillion ' magnification of errors
'================================================================
Dim As Double t, tt, grad, q, s, c, dx, dy, x, y, r = 1.1

Screen 19
Dim As Integer w, h, depth
Screeninfo w, h, depth
Window (-r * w / h, -r) - (r * w / h, r)  ' maintain pixel aspect

'----------------------------------------------------------------
Line(-c, 0)-(c, 0), 1   ' x axis
Line(0, -c)-(0, c), 1   ' y axis
Const As Double Pion2 = 2 * Atn(1)
For t = 0 To 4 * Pion2 Step Pion2 / 1000
x = Cos(t)
y = Sin(t)
Pset(x, y), 1       ' reference circle
Pset(x*.1, y*.1), 1 ' one tenth of circle at centre
Next t

'================================================================
'sine and cosine functions 200 grad pi
dim as double steps = .1
dim as double deg = atn(1)*4/200
for grad = 0 To 100 Step steps

'----------------------------------------
r = 1 + mag * (Sqr(c*c + s*s) - 1)   ' magnify radius error
x = c * r
y = s * r
Pset (+x, -y), 10
Pset (+x, +y), 10
Pset (-x, -y), 10
Pset (-x, +y), 10
'line(0,0)-(+x,-y),10
'line(0,0)-(+x, y),10
'line(0,0)-(-x,-y),10
'line(0,0)-(-x, y),10
'print atan2(s,c)*100/(deg*100)
t = grad * Pion2 / 100
dx = c - Cos(t)
dy = s - Sin(t)
Circle(mag * dx, mag * dy), 0.01, 10   ' plot the scatter

'================================================================
Sleep
'================================================================

albert
Posts: 5916
Joined: Sep 28, 2006 2:41
Location: California, USA
Here is my attempt at incrementing sine by percentages it only goes to 50 grads.

at 100 mag its well outside the circle but makes a nice looking circle.
but like with love ,looks don't count

Code: Select all

'================================================================
'test to see if sine increments have a set percentage of increase.
'  approximations measured relative to the reference circle ... blue
Const As Double mag = 100  ' magnification of errors
'================================================================
Dim As Double t, tt, grad, q, s, c, dx, dy, x, y, r = 1.1
Dim As Double sqr_root

Screen 19
Dim As Integer w, h, depth
Screeninfo w, h, depth
Window (-r * w / h, -r) - (r * w / h, r)  ' maintain pixel aspect

'----------------------------------------------------------------
Line(-c, 0)-(c, 0), 1   ' x axis
Line(0, -c)-(0, c), 1   ' y axis
Const As Double Pion2 = 2 * Atn(1)
For t = 0 To 4 * Pion2 Step Pion2 / 1000
x = Cos(t)
y = Sin(t)
Pset(x, y), 1       ' reference circle
Pset(x*.1, y*.1), 1 ' one tenth of circle at centre
Next t

'================================================================
'Albert's .0018 formula for a 200 degree pi
dim as double mul,arc
dim as double steps = 1
dim as double deg = atn(1)*4/200
mul = .99994
arc = deg*1*mul
c=1
s=0
for  grad = 0 To 50 Step steps

s=s+arc
arc = arc * mul
mul = mul -.000299
end if
c=sqr(1-s*s)

'----------------------------------------
r = 1 + mag * (Sqr(c*c + s*s) - 1)   ' magnify radius error
x = c * r
y = s * r
Pset (+x, -y), 10
Pset (+x, +y), 10
Pset (-x, -y), 10
Pset (-x, +y), 10
line(0,0)-(+x,-y),10
line(0,0)-(+x, y),10
line(0,0)-(-y,-x),10
line(0,0)-(-y, x),10

line(0,0)-(-x,-y),10
line(0,0)-(-x, y),10
line(0,0)-( y,-x),10
line(0,0)-( y, x),10

'print atan2(s,c)*100/(deg*200)
t = grad * Pion2 / 100
dx = c - Cos(t)
dy = s - Sin(t)
Circle(mag * dx, mag * dy), 0.01, 14   ' plot the scatter