hedgewars/uFloat.pas
changeset 351 29bc9c36ad5f
child 355 40c68869899e
equal deleted inserted replaced
350:c3ccec3834e8 351:29bc9c36ad5f
       
     1 (*
       
     2  * Hedgewars, a Worms style game
       
     3  * Copyright (c) 2007 Andrey Korotaev <unC0Rr@gmail.com>
       
     4  *
       
     5  * This program is free software; you can redistribute it and/or modify
       
     6  * it under the terms of the GNU General Public License as published by
       
     7  * the Free Software Foundation; version 2 of the License
       
     8  *
       
     9  * This program is distributed in the hope that it will be useful,
       
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    12  * GNU General Public License for more details.
       
    13  *
       
    14  * You should have received a copy of the GNU General Public License
       
    15  * along with this program; if not, write to the Free Software
       
    16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
       
    17  *)
       
    18 
       
    19 unit uFloat;
       
    20 interface
       
    21 
       
    22 {$IFDEF FPC}
       
    23 {$ifdef FPC_LITTLE_ENDIAN}
       
    24 type hwFloat = record
       
    25                isNegative: boolean;
       
    26                case byte of
       
    27                0: (Frac, Round: Longword);
       
    28                1: (QWordValue : QWord);
       
    29                end;
       
    30 {$else FPC_LITTLE_ENDIAN}
       
    31 type hwFloat = record
       
    32                isNegative: boolean;
       
    33                case byte of
       
    34                0: (Round, Frac: Longword);
       
    35                1: (QWordValue : QWord);
       
    36                end;
       
    37 {$endif FPC_LITTLE_ENDIAN}
       
    38 
       
    39 operator := (i: LongInt) z : hwFloat;
       
    40 
       
    41 operator + (z1, z2: hwFloat) z : hwFloat;
       
    42 operator - (z1, z2: hwFloat) z : hwFloat;
       
    43 operator - (z1: hwFloat) z : hwFloat;
       
    44 
       
    45 operator * (z1, z2: hwFloat) z : hwFloat;
       
    46 operator * (z1: hwFloat; z2: LongInt) z : hwFloat;
       
    47 operator / (z1, z2: hwFloat) z : hwFloat;
       
    48 
       
    49 operator < (z1, z2: hwFloat) b : boolean;
       
    50 operator > (z1, z2: hwFloat) b : boolean;
       
    51 
       
    52 function cstr(z: hwFloat): string;
       
    53 function hwRound(t: hwFloat): integer;
       
    54 function hwAbs(t: hwFloat): hwFloat;
       
    55 function hwSqr(t: hwFloat): hwFloat;
       
    56 function Distance(dx, dy: hwFloat): hwFloat;
       
    57 function AngleSin(angle: Longword): hwFloat;
       
    58 function AngleCos(angle: Longword): hwFloat;
       
    59 
       
    60 const  _1div1024: hwFloat = (isNegative: false; QWordValue:     4194304);
       
    61       _1div10000: hwFloat = (isNegative: false; QWordValue:      429496);
       
    62       _1div50000: hwFloat = (isNegative: false; QWordValue:       85899);
       
    63      _1div100000: hwFloat = (isNegative: false; QWordValue:       42950);
       
    64           _1div3: hwFloat = (isNegative: false; QWordValue:  1431655766);
       
    65             hwPi: hwFloat = (isNegative: false; QWordValue: 13493037704);
       
    66        _0_000004: hwFloat = (isNegative: false; QWordValue:       17179);
       
    67          _0_0002: hwFloat = (isNegative: false; QWordValue:      858993);
       
    68           _0_001: hwFloat = (isNegative: false; QWordValue:     4294967);
       
    69           _0_003: hwFloat = (isNegative: false; QWordValue:    12884902);
       
    70           _0_004: hwFloat = (isNegative: false; QWordValue:    17179869);
       
    71           _0_005: hwFloat = (isNegative: false; QWordValue:    21474836);
       
    72            _0_01: hwFloat = (isNegative: false; QWordValue:    42949673);
       
    73            _0_02: hwFloat = (isNegative: false; QWordValue:    85899345);
       
    74            _0_03: hwFloat = (isNegative: false; QWordValue:   128849018);
       
    75            _0_08: hwFloat = (isNegative: false; QWordValue:   343597383);
       
    76             _0_1: hwFloat = (isNegative: false; QWordValue:   429496729);
       
    77            _0_15: hwFloat = (isNegative: false; QWordValue:   644245094);
       
    78             _0_2: hwFloat = (isNegative: false; QWordValue:   858993459);
       
    79            _0_25: hwFloat = (isNegative: false; QWordValue:  1073741824);
       
    80             _0_3: hwFloat = (isNegative: false; QWordValue:  1288490189);
       
    81            _0_35: hwFloat = (isNegative: false; QWordValue:  1503238553);
       
    82             _0_4: hwFloat = (isNegative: false; QWordValue:  1717986918);
       
    83            _0_45: hwFloat = (isNegative: false; QWordValue:  1932735283);
       
    84             _0_5: hwFloat = (isNegative: false; QWordValue:  2147483648);
       
    85            _0_55: hwFloat = (isNegative: false; QWordValue:  2362232012);
       
    86             _0_6: hwFloat = (isNegative: false; QWordValue:  2576980377);
       
    87             _0_8: hwFloat = (isNegative: false; QWordValue:  3435973837);
       
    88            _0_84: hwFloat = (isNegative: false; QWordValue:  3607772528);
       
    89            _0_87: hwFloat = (isNegative: false; QWordValue:  3736621547);
       
    90             _0_9: hwFloat = (isNegative: false; QWordValue:  3865470566);
       
    91            _0_93: hwFloat = (isNegative: false; QWordValue:  3994319585);
       
    92            _0_96: hwFloat = (isNegative: false; QWordValue:  4123168604);
       
    93           _0_995: hwFloat = (isNegative: false; QWordValue:  4273492459);
       
    94           _0_999: hwFloat = (isNegative: false; QWordValue:  4290672328);
       
    95             _1_9: hwFloat = (isNegative: false; QWordValue:  8160437862);
       
    96 
       
    97          cLittle: hwFloat = (isNegative: false; QWordValue:           1);
       
    98          cHHKick: hwFloat = (isNegative: false; QWordValue:   128849018);
       
    99 {$ENDIF}
       
   100 
       
   101 {$IFNDEF FPC}
       
   102 type hwFloat = Extended;
       
   103 {$ENDIF}
       
   104 
       
   105 implementation
       
   106 uses uConsts;
       
   107 
       
   108 {$IFDEF FPC}
       
   109 
       
   110 operator := (i: LongInt) z : hwFloat;
       
   111 begin
       
   112 z.isNegative:= i < 0;
       
   113 z.Round:= abs(i);
       
   114 z.Frac:= 0
       
   115 end;
       
   116 
       
   117 operator + (z1, z2: hwFloat) z : hwFloat;
       
   118 begin
       
   119 if z1.isNegative = z2.isNegative then
       
   120    begin
       
   121    z.isNegative:= z1.isNegative;
       
   122    z.QWordValue:= z1.QWordValue + z2.QWordValue
       
   123    end
       
   124 else
       
   125    if z1.QWordValue > z2.QWordValue then
       
   126       begin
       
   127       z.isNegative:= z1.isNegative;
       
   128       z.QWordValue:= z1.QWordValue - z2.QWordValue
       
   129       end else
       
   130       begin
       
   131       z.isNegative:= z2.isNegative;
       
   132       z.QWordValue:= z2.QWordValue - z1.QWordValue
       
   133       end
       
   134 end;
       
   135 
       
   136 operator - (z1, z2: hwFloat) z : hwFloat;
       
   137 begin
       
   138 if z1.isNegative = z2.isNegative then
       
   139    if z1.QWordValue > z2.QWordValue then
       
   140       begin
       
   141       z.isNegative:= z1.isNegative;
       
   142       z.QWordValue:= z1.QWordValue - z2.QWordValue
       
   143       end else
       
   144       begin
       
   145       z.isNegative:= not z2.isNegative;
       
   146       z.QWordValue:= z2.QWordValue - z1.QWordValue
       
   147       end
       
   148 else begin
       
   149      z.isNegative:= z1.isNegative;
       
   150      z.QWordValue:= z1.QWordValue + z2.QWordValue
       
   151      end
       
   152 end;
       
   153 
       
   154 operator - (z1: hwFloat) z : hwFloat;
       
   155 begin
       
   156 z:= z1;
       
   157 z.isNegative:= not z.isNegative
       
   158 end;
       
   159 
       
   160 
       
   161 operator * (z1, z2: hwFloat) z : hwFloat;
       
   162 begin
       
   163 z.isNegative:= z1.isNegative xor z2.isNegative;
       
   164 z.QWordValue:= QWord(z1.Round) * z2.Frac +
       
   165                QWord(z1.Frac) * z2.Round +
       
   166                ((QWord(z1.Frac) * z2.Frac) shr 32);
       
   167 z.Round:= z.Round + QWord(z1.Round) * z2.Round;
       
   168 end;
       
   169 
       
   170 operator * (z1: hwFloat; z2: LongInt) z : hwFloat;
       
   171 begin
       
   172 z.isNegative:= z1.isNegative xor (z2 < 0);
       
   173 z2:= abs(z2);
       
   174 z.QWordValue:= z.QWordValue * z2
       
   175 end;
       
   176 
       
   177 operator / (z1, z2: hwFloat) z : hwFloat;
       
   178 var t: hwFloat;
       
   179 begin
       
   180 z.isNegative:= z1.isNegative xor z2.isNegative;
       
   181 z.Round:= z1.QWordValue div z2.QWordValue;
       
   182 t:= z1 - z2 * z.Round;
       
   183 if t.QWordValue = 0 then
       
   184    z.Frac:= 0
       
   185 else
       
   186    begin
       
   187    while ((t.QWordValue and $8000000000000000) = 0) and
       
   188          ((z2.QWordValue and $8000000000000000) = 0) do
       
   189          begin
       
   190          t.QWordValue:= t.QWordValue shl 1;
       
   191          z2.QWordValue:= z2.QWordValue shl 1
       
   192          end;
       
   193    z.Frac:= (t.QWordValue) div (z2.Round)
       
   194    end
       
   195 end;
       
   196 
       
   197 operator < (z1, z2: hwFloat) b : boolean;
       
   198 begin
       
   199 if z1.isNegative <> z2.isNegative then
       
   200    b:= z1.isNegative
       
   201 else
       
   202    if z1.QWordValue = z2.QWordValue then
       
   203       b:= false
       
   204    else
       
   205       b:= (z1.QWordValue < z2.QWordValue) xor z1.isNegative
       
   206 end;
       
   207 
       
   208 operator > (z1, z2: hwFloat) b : boolean;
       
   209 begin
       
   210 if z1.isNegative <> z2.isNegative then
       
   211    b:= z2.isNegative
       
   212 else
       
   213    if z1.QWordValue = z2.QWordValue then
       
   214       b:= false
       
   215    else
       
   216       b:= (z1.QWordValue > z2.QWordValue) xor z2.isNegative
       
   217 end;
       
   218 
       
   219 function cstr(z: hwFloat): string;
       
   220 var tmpstr: string;
       
   221 begin
       
   222 str(z.Round, cstr);
       
   223 if z.Frac <> 0 then
       
   224    begin
       
   225    str(z.Frac / $100000000:1:15, tmpstr);
       
   226    delete(tmpstr, 1, 2);
       
   227    cstr:= cstr + '.' + tmpstr
       
   228    end;
       
   229 if z.isNegative then cstr:= '-' + cstr
       
   230 end;
       
   231 
       
   232 function hwRound(t: hwFloat): integer;
       
   233 begin
       
   234 if t.isNegative then hwRound:= -t.Round
       
   235                 else hwRound:= t.Round
       
   236 end;
       
   237 
       
   238 function hwAbs(t: hwFloat): hwFloat;
       
   239 begin
       
   240 hwAbs:= t;
       
   241 hwAbs.isNegative:= false
       
   242 end;
       
   243 
       
   244 function hwSqr(t: hwFloat): hwFloat;
       
   245 begin
       
   246 hwSqr:= t * t
       
   247 end;
       
   248 
       
   249 function Distance(dx, dy: hwFloat): hwFloat;
       
   250 var x, y: hwFloat;
       
   251     Result: hwFloat;
       
   252 begin
       
   253 x:= dx * dx;
       
   254 y:= dy * dy;
       
   255 Result:= x + y;
       
   256 Result.QWordValue:= Round(sqrt(1.0 / 4294967296 * (Result.QWordValue)) * 4294967296);
       
   257 Distance:= Result
       
   258 end;
       
   259 
       
   260 function AngleSin(angle: Longword): hwFloat;
       
   261 begin
       
   262 AngleSin.isNegative:= false;
       
   263 AngleSin:= Round(Sin(Angle * pi / cMaxAngle) * 4294967296)
       
   264 end;
       
   265 
       
   266 function AngleCos(angle: Longword): hwFloat;
       
   267 var CosVal: Extended;
       
   268 begin
       
   269 CosVal:= Cos(Angle * pi / cMaxAngle);
       
   270 AngleCos.isNegative:= CosVal < 0;
       
   271 AngleCos:= Round(Cosval * 4294967296)
       
   272 end;
       
   273 
       
   274 {$ENDIF}
       
   275 
       
   276 end.