hedgewars/uFloat.pas
branchwebgl
changeset 9127 e350500c4edb
parent 8847 ff7fbab7cd56
parent 9080 9b42757d7e71
child 9968 7fb2f35bdd5b
--- a/hedgewars/uFloat.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uFloat.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -86,7 +86,8 @@
 function hwAbs(const t: hwFloat): hwFloat; inline; // Returns the value of t with positive sign.
 function hwSqr(const t: hwFloat): hwFloat; inline; // Returns the square value of parameter t.
 function hwPow(const t: hwFloat; p: LongWord): hwFloat; inline; // Returns the power of the value
-function hwSqrt(const t: hwFloat): hwFloat; inline; // Returns the the positive square root of parameter t.
+function hwSqrt1(const t: hwFloat): hwFloat; inline; // Returns the the positive square root of parameter t.
+function hwSqrt(const x: hwFloat): hwFloat; inline; // Returns the the positive square root of parameter t.
 function Distance(const dx, dy: hwFloat): hwFloat; // Returns the distance between two points in 2-dimensional space, of which the parameters are the horizontal and vertical distance.
 function DistanceI(const dx, dy: LongInt): hwFloat; // Same as above for integer parameters.
 function AngleSin(const Angle: Longword): hwFloat;
@@ -274,7 +275,7 @@
     end
 end;
 
-function isZero(const z: hwFloat): boolean; inline; 
+function isZero(const z: hwFloat): boolean; inline;
 begin
 isZero := z.QWordValue = 0;
 end;
@@ -287,7 +288,7 @@
     if z1.QWordValue = z2.QWordValue then
         b:= false
     else
-        b:= not((z1.QWordValue = z2.QWordValue) or ((z2.QWordValue < z1.QWordValue) <> z1.isNegative))
+        b:= (z2.QWordValue < z1.QWordValue) = z1.isNegative
 end;
 
 operator > (const z1, z2: hwFloat) b : boolean; inline;
@@ -418,24 +419,23 @@
 end;
 
 operator / (const z1: hwFloat; z2: hwFloat) z : hwFloat; inline;
-var t: hwFloat;
+var t: QWord;
 begin
 z.isNegative:= z1.isNegative xor z2.isNegative;
 z.Round:= z1.QWordValue div z2.QWordValue;
-t:= z1 - z2 * z.Round;
-if t.QWordValue = 0 then
-    z.Frac:= 0
-else
+t:= z1.QWordValue - z2.QWordValue * z.Round;
+z.Frac:= 0;
+
+if t <> 0 then
     begin
-    while ((t.QWordValue and $8000000000000000) = 0) and ((z2.QWordValue and $8000000000000000) = 0) do
+    while ((t and $FF00000000000000) = 0) and ((z2.QWordValue and $FF00000000000000) = 0) do
         begin
-        t.QWordValue:= t.QWordValue shl 1;
-        z2.QWordValue:= z2.QWordValue shl 1
+        t:= t shl 8;
+        z2.QWordValue:= z2.QWordValue shl 8
         end;
+
     if z2.Round > 0 then
-        z.Frac:= (t.QWordValue) div (z2.Round)
-    else
-        z.Frac:= 0
+        inc(z.QWordValue, t div z2.Round);
     end
 end;
 
@@ -491,14 +491,14 @@
     end
 end;
 
-function hwSqrt(const t: hwFloat): hwFloat;
+function hwSqrt1(const t: hwFloat): hwFloat;
 const pwr = 8; // even value, feel free to adjust
       rThreshold = 1 shl (pwr + 32);
       lThreshold = 1 shl (pwr div 2 + 32);
 var l, r: QWord;
     c: hwFloat;
 begin
-hwSqrt.isNegative:= false;
+hwSqrt1.isNegative:= false;
 
 if t.Round = 0 then
     begin
@@ -531,12 +531,47 @@
         l:= c.QWordValue
 until r - l <= 1;
 
-hwSqrt.QWordValue:= l
+hwSqrt1.QWordValue:= l
 end;
 
-function Distance(const dx, dy: hwFloat): hwFloat;
+function hwSqrt(const x: hwFloat): hwFloat;
+var r, t, s, q: QWord;
+    i: integer;
 begin
-Distance:= hwSqrt(hwSqr(dx) + hwSqr(dy))
+hwSqrt.isNegative:= false;
+
+t:= $4000000000000000;
+r:= 0;
+q:= x.QWordValue;
+
+for i:= 0 to 31 do
+    begin
+    s:= r + t;
+    r:= r shr 1;
+    if s <= q then
+        begin
+        dec(q, s);
+        inc(r, t);
+        end;
+    t:= t shr 2;
+    end;
+
+hwSqrt.QWordValue:= r shl 16
+end;
+
+
+
+function Distance(const dx, dy: hwFloat): hwFloat;
+var r: QWord;
+begin
+r:= dx.QWordValue or dy.QWordValue;
+
+if r < $10000 then
+    begin
+    Distance.QWordValue:= r;
+    Distance.isNegative:= false
+    end else
+    Distance:= hwSqrt(hwSqr(dx) + hwSqr(dy))
 end;
 
 function DistanceI(const dx, dy: LongInt): hwFloat;