hedgewars/uFloat.pas
changeset 351 29bc9c36ad5f
child 355 40c68869899e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hedgewars/uFloat.pas	Sun Jan 21 19:51:02 2007 +0000
@@ -0,0 +1,276 @@
+(*
+ * Hedgewars, a Worms style game
+ * Copyright (c) 2007 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
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *)
+
+unit uFloat;
+interface
+
+{$IFDEF FPC}
+{$ifdef FPC_LITTLE_ENDIAN}
+type hwFloat = record
+               isNegative: boolean;
+               case byte of
+               0: (Frac, Round: Longword);
+               1: (QWordValue : QWord);
+               end;
+{$else FPC_LITTLE_ENDIAN}
+type hwFloat = record
+               isNegative: boolean;
+               case byte of
+               0: (Round, Frac: Longword);
+               1: (QWordValue : QWord);
+               end;
+{$endif FPC_LITTLE_ENDIAN}
+
+operator := (i: LongInt) z : hwFloat;
+
+operator + (z1, z2: hwFloat) z : hwFloat;
+operator - (z1, z2: hwFloat) z : hwFloat;
+operator - (z1: hwFloat) z : hwFloat;
+
+operator * (z1, z2: hwFloat) z : hwFloat;
+operator * (z1: hwFloat; z2: LongInt) z : hwFloat;
+operator / (z1, z2: hwFloat) z : hwFloat;
+
+operator < (z1, z2: hwFloat) b : boolean;
+operator > (z1, z2: hwFloat) b : boolean;
+
+function cstr(z: hwFloat): string;
+function hwRound(t: hwFloat): integer;
+function hwAbs(t: hwFloat): hwFloat;
+function hwSqr(t: hwFloat): hwFloat;
+function Distance(dx, dy: hwFloat): hwFloat;
+function AngleSin(angle: Longword): hwFloat;
+function AngleCos(angle: Longword): hwFloat;
+
+const  _1div1024: hwFloat = (isNegative: false; QWordValue:     4194304);
+      _1div10000: hwFloat = (isNegative: false; QWordValue:      429496);
+      _1div50000: hwFloat = (isNegative: false; QWordValue:       85899);
+     _1div100000: hwFloat = (isNegative: false; QWordValue:       42950);
+          _1div3: hwFloat = (isNegative: false; QWordValue:  1431655766);
+            hwPi: hwFloat = (isNegative: false; QWordValue: 13493037704);
+       _0_000004: hwFloat = (isNegative: false; QWordValue:       17179);
+         _0_0002: hwFloat = (isNegative: false; QWordValue:      858993);
+          _0_001: hwFloat = (isNegative: false; QWordValue:     4294967);
+          _0_003: hwFloat = (isNegative: false; QWordValue:    12884902);
+          _0_004: hwFloat = (isNegative: false; QWordValue:    17179869);
+          _0_005: hwFloat = (isNegative: false; QWordValue:    21474836);
+           _0_01: hwFloat = (isNegative: false; QWordValue:    42949673);
+           _0_02: hwFloat = (isNegative: false; QWordValue:    85899345);
+           _0_03: hwFloat = (isNegative: false; QWordValue:   128849018);
+           _0_08: hwFloat = (isNegative: false; QWordValue:   343597383);
+            _0_1: hwFloat = (isNegative: false; QWordValue:   429496729);
+           _0_15: hwFloat = (isNegative: false; QWordValue:   644245094);
+            _0_2: hwFloat = (isNegative: false; QWordValue:   858993459);
+           _0_25: hwFloat = (isNegative: false; QWordValue:  1073741824);
+            _0_3: hwFloat = (isNegative: false; QWordValue:  1288490189);
+           _0_35: hwFloat = (isNegative: false; QWordValue:  1503238553);
+            _0_4: hwFloat = (isNegative: false; QWordValue:  1717986918);
+           _0_45: hwFloat = (isNegative: false; QWordValue:  1932735283);
+            _0_5: hwFloat = (isNegative: false; QWordValue:  2147483648);
+           _0_55: hwFloat = (isNegative: false; QWordValue:  2362232012);
+            _0_6: hwFloat = (isNegative: false; QWordValue:  2576980377);
+            _0_8: hwFloat = (isNegative: false; QWordValue:  3435973837);
+           _0_84: hwFloat = (isNegative: false; QWordValue:  3607772528);
+           _0_87: hwFloat = (isNegative: false; QWordValue:  3736621547);
+            _0_9: hwFloat = (isNegative: false; QWordValue:  3865470566);
+           _0_93: hwFloat = (isNegative: false; QWordValue:  3994319585);
+           _0_96: hwFloat = (isNegative: false; QWordValue:  4123168604);
+          _0_995: hwFloat = (isNegative: false; QWordValue:  4273492459);
+          _0_999: hwFloat = (isNegative: false; QWordValue:  4290672328);
+            _1_9: hwFloat = (isNegative: false; QWordValue:  8160437862);
+
+         cLittle: hwFloat = (isNegative: false; QWordValue:           1);
+         cHHKick: hwFloat = (isNegative: false; QWordValue:   128849018);
+{$ENDIF}
+
+{$IFNDEF FPC}
+type hwFloat = Extended;
+{$ENDIF}
+
+implementation
+uses uConsts;
+
+{$IFDEF FPC}
+
+operator := (i: LongInt) z : hwFloat;
+begin
+z.isNegative:= i < 0;
+z.Round:= abs(i);
+z.Frac:= 0
+end;
+
+operator + (z1, z2: hwFloat) z : hwFloat;
+begin
+if z1.isNegative = z2.isNegative then
+   begin
+   z.isNegative:= z1.isNegative;
+   z.QWordValue:= z1.QWordValue + z2.QWordValue
+   end
+else
+   if z1.QWordValue > z2.QWordValue then
+      begin
+      z.isNegative:= z1.isNegative;
+      z.QWordValue:= z1.QWordValue - z2.QWordValue
+      end else
+      begin
+      z.isNegative:= z2.isNegative;
+      z.QWordValue:= z2.QWordValue - z1.QWordValue
+      end
+end;
+
+operator - (z1, z2: hwFloat) z : hwFloat;
+begin
+if z1.isNegative = z2.isNegative then
+   if z1.QWordValue > z2.QWordValue then
+      begin
+      z.isNegative:= z1.isNegative;
+      z.QWordValue:= z1.QWordValue - z2.QWordValue
+      end else
+      begin
+      z.isNegative:= not z2.isNegative;
+      z.QWordValue:= z2.QWordValue - z1.QWordValue
+      end
+else begin
+     z.isNegative:= z1.isNegative;
+     z.QWordValue:= z1.QWordValue + z2.QWordValue
+     end
+end;
+
+operator - (z1: hwFloat) z : hwFloat;
+begin
+z:= z1;
+z.isNegative:= not z.isNegative
+end;
+
+
+operator * (z1, z2: hwFloat) z : hwFloat;
+begin
+z.isNegative:= z1.isNegative xor z2.isNegative;
+z.QWordValue:= QWord(z1.Round) * z2.Frac +
+               QWord(z1.Frac) * z2.Round +
+               ((QWord(z1.Frac) * z2.Frac) shr 32);
+z.Round:= z.Round + QWord(z1.Round) * z2.Round;
+end;
+
+operator * (z1: hwFloat; z2: LongInt) z : hwFloat;
+begin
+z.isNegative:= z1.isNegative xor (z2 < 0);
+z2:= abs(z2);
+z.QWordValue:= z.QWordValue * z2
+end;
+
+operator / (z1, z2: hwFloat) z : hwFloat;
+var t: hwFloat;
+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
+   begin
+   while ((t.QWordValue and $8000000000000000) = 0) and
+         ((z2.QWordValue and $8000000000000000) = 0) do
+         begin
+         t.QWordValue:= t.QWordValue shl 1;
+         z2.QWordValue:= z2.QWordValue shl 1
+         end;
+   z.Frac:= (t.QWordValue) div (z2.Round)
+   end
+end;
+
+operator < (z1, z2: hwFloat) b : boolean;
+begin
+if z1.isNegative <> z2.isNegative then
+   b:= z1.isNegative
+else
+   if z1.QWordValue = z2.QWordValue then
+      b:= false
+   else
+      b:= (z1.QWordValue < z2.QWordValue) xor z1.isNegative
+end;
+
+operator > (z1, z2: hwFloat) b : boolean;
+begin
+if z1.isNegative <> z2.isNegative then
+   b:= z2.isNegative
+else
+   if z1.QWordValue = z2.QWordValue then
+      b:= false
+   else
+      b:= (z1.QWordValue > z2.QWordValue) xor z2.isNegative
+end;
+
+function cstr(z: hwFloat): string;
+var tmpstr: string;
+begin
+str(z.Round, cstr);
+if z.Frac <> 0 then
+   begin
+   str(z.Frac / $100000000:1:15, tmpstr);
+   delete(tmpstr, 1, 2);
+   cstr:= cstr + '.' + tmpstr
+   end;
+if z.isNegative then cstr:= '-' + cstr
+end;
+
+function hwRound(t: hwFloat): integer;
+begin
+if t.isNegative then hwRound:= -t.Round
+                else hwRound:= t.Round
+end;
+
+function hwAbs(t: hwFloat): hwFloat;
+begin
+hwAbs:= t;
+hwAbs.isNegative:= false
+end;
+
+function hwSqr(t: hwFloat): hwFloat;
+begin
+hwSqr:= t * t
+end;
+
+function Distance(dx, dy: hwFloat): hwFloat;
+var x, y: hwFloat;
+    Result: hwFloat;
+begin
+x:= dx * dx;
+y:= dy * dy;
+Result:= x + y;
+Result.QWordValue:= Round(sqrt(1.0 / 4294967296 * (Result.QWordValue)) * 4294967296);
+Distance:= Result
+end;
+
+function AngleSin(angle: Longword): hwFloat;
+begin
+AngleSin.isNegative:= false;
+AngleSin:= Round(Sin(Angle * pi / cMaxAngle) * 4294967296)
+end;
+
+function AngleCos(angle: Longword): hwFloat;
+var CosVal: Extended;
+begin
+CosVal:= Cos(Angle * pi / cMaxAngle);
+AngleCos.isNegative:= CosVal < 0;
+AngleCos:= Round(Cosval * 4294967296)
+end;
+
+{$ENDIF}
+
+end.