Fix64Bug

ThomasW69
 
Avatar
 
Subject:

Fix64Bug

 · 
Posted: 30.06.2010 - 08:09  ·  #1
Ich teste gerade mal die Fix64 Funktionen durch und bekomme bei der Wurzelfunktion einen Fehler.

Da ich leider nicht die Pro-Version habe muss ich mir einige Funktionen selber schreiben. Beim natürlichen Logarithmus, hergeleitet aus Quadratwurzeln bekomme ich dann einen Compilerfehler.
Code
function Fix64Ln(const a: fix64):fix64;
var
  p,q: fix64;
  i: Integer;
begin
 p:=1.0;
 q:=a;
 for i:=1 to 10 do
 q:=sqrt(q);
 p:=p*2/(q+1/q);
 endfor;
 Return(p*(a-1.0/a)/2.0);
end;


In der Zeile mit dem q:=sqrt(q); kommt der
internal assembler error 2502.
Nehme ich die Zeile raus, so lässt sich das Programm compilieren.
Laut Compilerhandbuch Seite 121 sollte aber die Sqrt-Funktion auch für Fix64 geeignet sein.
Kann man nicht die uFix64.pas public machen? Ich kann zwar keine Units verwenden, aber da dann das was ich bräuchte herauskopieren.
rh
Administrator
Avatar
Gender:
Location: Germany
Age: 24
Homepage: e-lab.de
Posts: 5558
Registered: 03 / 2002
Subject:

Re: Fix64Bug

 · 
Posted: 30.06.2010 - 11:18  ·  #2
Hallo Thomas,

bug fixed. Bis zum WE kommt ein update. Falls Sie nicht so lange warten wollen, hier ein work-around. Fügen Sie irgendwo diesen code ein:
Code
 var  i64  : int64;
  ...
  if i64 > i64 then  endif;

Unit Sourcen, vor allen Dingen die uFix64, werden nicht veröffentlicht. Die böse Konkurrenz würde sich die Finger danach schlecken. Weiterhin möchten wir auch gerne die Profi Version verkaufen...
:'( O-)

rolf
ThomasW69
 
Avatar
 
Subject:

Re: Fix64Bug

 · 
Posted: 30.06.2010 - 12:56  ·  #3
Ja der Workaround funktioniert. Danke

Ich hatte mir zwischenzeitlich eine eigene Wurzelfunktion geschrieben
Dabei habe ich festgestellt, daß Sqrt doch recht ungenau ist.
Mein Code:
Code

function Fix64Sqrt(const a:fix64):fix64;
var delta,w,x:fix64;
begin
  w:=a/2.0;
  repeat
    delta:=(a-(w*w))/(2.0*w);
    w:=w+delta;
    x:=abs(delta);
  until x<0.0000001;
  return(w);
end;


So ist zum Beispiel die Wurzel aus 1250
= 35,35533905932
und
= 35.355339059 mit meiner Funktion
= 35.355331421 mit sqrt

Ich brauch das Fix64 ja für astronomische Berechnungen und die müssen sehr exakt sein. Da bin ich mit meiner selbstgeschriebenen Wurzelfunktion schon mal besser, aber dafür braucht die 13ms ( bei 16MHz ProcClock) anstatt 600µs für sqrt() :'(
Insbesondere beim Ln, den ich mittels iterierenden Quadratwurzeln bilde ist das problematisch weil es dann halt durchaus mal 300-400ms dauert.

Ich weiß ja nicht wie schnell der Sinus bei uFix64 berechnet wird und wie genau der ist. Ich habe mir diese Funktion geschrieben.
Code
function Fix64Sin(const radians: fix64):fix64;
var  x1,y,y2,y3,y5,y7,sum,sg:Fix64;
begin
  sg := 1.0;
  x1 := radians;
  if (x1<0) then
      x1 := -x1;
      sg := -1.0;
   endif;
  while (x1 > HalfFix64Pi) Do
      x1 := x1 - Fix64PI;
      sg := -1.0*sg;
  endwhile;
  y := x1*2/Fix64PI;
  y2 := y*y;
  y3 := y*y2;
  y5 := y3*y2;
  y7 := y5*y2;
  sum := 1.570796327*y - 0.645962*y3 +
         0.079692*y5 - 0.004681712*y7;
  Return(sg*sum);
end;

Die liefert mir den Sinus von 1.5rad in 3,2ms als
= 0.997392543
= 0,9974949866 mit Taschenrechner.
Wie man sieht geht es zwar schnell, aber da werde ich schon in der 4. Nachkommastelle ungenau.

Die Alternative mittels Taylorreihe
Code

function Fix64Sin(const radians: fix64):fix64;
var i,fx,s,tf:Fix64;
begin
 i:= 0.0;
 fx:=0.0;
 s:=radians;
 TF:=-radians*radians;
 repeat
   fx := fx+S;
   S := S*TF/((2.0*i)*(2.0*i+1.0));
   i := i+1.000000000;
 until (S = 0.0);
 
 //eventuele ungenauigkeiten beseitigen
 if fx>1.0 then fx:=1.0; endif;
 if fx<-1.0 then fx:=-1.0; endif;
 return (fx);
end;

liefert den Sinus von 1.5rad in 15ms
= 0.997494986 im Vergleich zu
= 0.9974949866 mit Taschenrechner.
und ist eine Punktlandung.

So wie es ausschaut kann man entweder nur genau oder schnell sein.
Hat jemand mal Vergleichswerte mit den Funktionen aus der uFix64 Unit?
rh
Administrator
Avatar
Gender:
Location: Germany
Age: 24
Homepage: e-lab.de
Posts: 5558
Registered: 03 / 2002
Subject:

Re: Fix64Bug

 · 
Posted: 30.06.2010 - 14:41  ·  #4
Hallo Thomas,

Fix64Sin(1.5) -> 0.997494987
Dauer = 8.24msec

Man sieht dass der AVRco doch einen recht dichten Code erzeugt 15msec | 8msec

btw
Wegen der Genauigkeit kann User AVRA mehr dazu sagen...

rolf
Merlin
Administrator
Avatar
Gender:
Age: 24
Posts: 1408
Registered: 03 / 2005
Subject:

Re: Fix64Bug

 · 
Posted: 30.06.2010 - 17:13  ·  #5
Hi Thomas.

For the the square root function the following is likely to be quicker:

Code
function Fix64Sqrt(const a:fix64):fix64; 
var delta,w, w1:fix64; 
begin 
  if a= 0.0 then
    return( 0.0 );
  endif;
  w:=a/2.0; 
  repeat 
    w1 = a/w; 
    w:=(w+w1)/2.0;  
  until abs(w-w1)<0.0000001; 
  return(w); 
end; 


Also, if you don't use the optimiser, using it should also speed things up a little.

I have not done timing tests but there are fewer calculations per iteration and the same number of iterations (the two methods, although they look very different, are equivalent).

Regards

Merlin.
rh
Administrator
Avatar
Gender:
Location: Germany
Age: 24
Homepage: e-lab.de
Posts: 5558
Registered: 03 / 2002
Subject:

Re: Fix64Bug

 · 
Posted: 02.07.2010 - 14:29  ·  #6
@all,

now I have a Sqrt(Fix64) function which provides the absolute accuracy:

SqrtF64(1250.0) -> 35.355339059 which is more precise than my Casio calculator !! And it takes only 5msec !!!
Delphi Double Sqrt(125456.789) --> 354.1987987
AVRco Fix64 SqrtF64(125456.789) -> 354.198798699

So in the near future there will be the
function Sqrt(nnn : type) : xxxx; which eats most of the types
and additional the precise
function SqrtF64(nnn : Fix64) : Fix64; which is only applicable for Fix64 types.

For the Unit uFix64 then there will be an application switch {$DEFINE useSqrtF64} which forces this unit to internal use SqrtF64(Fix64) instead of Sqrt(xx).

rolf
Selected quotes for multi-quoting:   0

Registered users in this topic

Currently no registered users in this section

The statistic shows who was online during the last 5 minutes. Updated every 90 seconds.
MySQL Queries: 15 · Cache Hits: 14   108   122 · Page-Gen-Time: 0.028701s · Memory Usage: 2 MB · GZIP: on · Viewport: SMXL-HiDPI