hedgewars/uFloat.pas
branchwebgl
changeset 9127 e350500c4edb
parent 8847 ff7fbab7cd56
parent 9080 9b42757d7e71
child 9968 7fb2f35bdd5b
equal deleted inserted replaced
8860:bde641cf53c8 9127:e350500c4edb
     1 (*
     1 (*
     2  * Hedgewars, a free turn based strategy game
     2  * Hedgewars, a free turn based strategy game
     3  * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
     3  * Copyright (c) 2004-2013 Andrey Korotaev <unC0Rr@gmail.com>
     4  *
     4  *
     5  * This program is free software; you can redistribute it and/or modify
     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
     6  * it under the terms of the GNU General Public License as published by
     7  * the Free Software Foundation; version 2 of the License
     7  * the Free Software Foundation; version 2 of the License
     8  *
     8  *
    84 function cstr(const z: hwFloat): shortstring; // Returns a shortstring representations of the hwFloat.
    84 function cstr(const z: hwFloat): shortstring; // Returns a shortstring representations of the hwFloat.
    85 function hwRound(const t: hwFloat): LongInt; inline; // Does NOT really round but returns the integer representation of the hwFloat without fractional digits. (-_0_9 -> -0, _1_5 -> _1)
    85 function hwRound(const t: hwFloat): LongInt; inline; // Does NOT really round but returns the integer representation of the hwFloat without fractional digits. (-_0_9 -> -0, _1_5 -> _1)
    86 function hwAbs(const t: hwFloat): hwFloat; inline; // Returns the value of t with positive sign.
    86 function hwAbs(const t: hwFloat): hwFloat; inline; // Returns the value of t with positive sign.
    87 function hwSqr(const t: hwFloat): hwFloat; inline; // Returns the square value of parameter t.
    87 function hwSqr(const t: hwFloat): hwFloat; inline; // Returns the square value of parameter t.
    88 function hwPow(const t: hwFloat; p: LongWord): hwFloat; inline; // Returns the power of the value
    88 function hwPow(const t: hwFloat; p: LongWord): hwFloat; inline; // Returns the power of the value
    89 function hwSqrt(const t: hwFloat): hwFloat; inline; // Returns the the positive square root of parameter t.
    89 function hwSqrt1(const t: hwFloat): hwFloat; inline; // Returns the the positive square root of parameter t.
       
    90 function hwSqrt(const x: hwFloat): hwFloat; inline; // Returns the the positive square root of parameter t.
    90 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.
    91 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.
    91 function DistanceI(const dx, dy: LongInt): hwFloat; // Same as above for integer parameters.
    92 function DistanceI(const dx, dy: LongInt): hwFloat; // Same as above for integer parameters.
    92 function AngleSin(const Angle: Longword): hwFloat;
    93 function AngleSin(const Angle: Longword): hwFloat;
    93 function AngleCos(const Angle: Longword): hwFloat;
    94 function AngleCos(const Angle: Longword): hwFloat;
    94 function vector2Angle(const x, y: hwFloat): LongInt;
    95 function vector2Angle(const x, y: hwFloat): LongInt;
   272     z.isNegative:= z1.isNegative;
   273     z.isNegative:= z1.isNegative;
   273     z.QWordValue:= z1.QWordValue + z2.QWordValue
   274     z.QWordValue:= z1.QWordValue + z2.QWordValue
   274     end
   275     end
   275 end;
   276 end;
   276 
   277 
   277 function isZero(const z: hwFloat): boolean; inline; 
   278 function isZero(const z: hwFloat): boolean; inline;
   278 begin
   279 begin
   279 isZero := z.QWordValue = 0;
   280 isZero := z.QWordValue = 0;
   280 end;
   281 end;
   281 
   282 
   282 operator < (const z1, z2: hwFloat) b : boolean; inline;
   283 operator < (const z1, z2: hwFloat) b : boolean; inline;
   285     b:= z1.isNegative
   286     b:= z1.isNegative
   286 else
   287 else
   287     if z1.QWordValue = z2.QWordValue then
   288     if z1.QWordValue = z2.QWordValue then
   288         b:= false
   289         b:= false
   289     else
   290     else
   290         b:= not((z1.QWordValue = z2.QWordValue) or ((z2.QWordValue < z1.QWordValue) <> z1.isNegative))
   291         b:= (z2.QWordValue < z1.QWordValue) = z1.isNegative
   291 end;
   292 end;
   292 
   293 
   293 operator > (const z1, z2: hwFloat) b : boolean; inline;
   294 operator > (const z1, z2: hwFloat) b : boolean; inline;
   294 begin
   295 begin
   295 if z1.isNegative xor z2.isNegative then
   296 if z1.isNegative xor z2.isNegative then
   416 z.isNegative:= z1.isNegative xor (z2 < 0);
   417 z.isNegative:= z1.isNegative xor (z2 < 0);
   417 z.QWordValue:= z1.QWordValue * abs(z2)
   418 z.QWordValue:= z1.QWordValue * abs(z2)
   418 end;
   419 end;
   419 
   420 
   420 operator / (const z1: hwFloat; z2: hwFloat) z : hwFloat; inline;
   421 operator / (const z1: hwFloat; z2: hwFloat) z : hwFloat; inline;
   421 var t: hwFloat;
   422 var t: QWord;
   422 begin
   423 begin
   423 z.isNegative:= z1.isNegative xor z2.isNegative;
   424 z.isNegative:= z1.isNegative xor z2.isNegative;
   424 z.Round:= z1.QWordValue div z2.QWordValue;
   425 z.Round:= z1.QWordValue div z2.QWordValue;
   425 t:= z1 - z2 * z.Round;
   426 t:= z1.QWordValue - z2.QWordValue * z.Round;
   426 if t.QWordValue = 0 then
   427 z.Frac:= 0;
   427     z.Frac:= 0
   428 
   428 else
   429 if t <> 0 then
   429     begin
   430     begin
   430     while ((t.QWordValue and $8000000000000000) = 0) and ((z2.QWordValue and $8000000000000000) = 0) do
   431     while ((t and $FF00000000000000) = 0) and ((z2.QWordValue and $FF00000000000000) = 0) do
   431         begin
   432         begin
   432         t.QWordValue:= t.QWordValue shl 1;
   433         t:= t shl 8;
   433         z2.QWordValue:= z2.QWordValue shl 1
   434         z2.QWordValue:= z2.QWordValue shl 8
   434         end;
   435         end;
       
   436 
   435     if z2.Round > 0 then
   437     if z2.Round > 0 then
   436         z.Frac:= (t.QWordValue) div (z2.Round)
   438         inc(z.QWordValue, t div z2.Round);
   437     else
       
   438         z.Frac:= 0
       
   439     end
   439     end
   440 end;
   440 end;
   441 
   441 
   442 operator / (const z1: hwFloat; const z2: LongInt) z : hwFloat; inline;
   442 operator / (const z1: hwFloat; const z2: LongInt) z : hwFloat; inline;
   443 begin
   443 begin
   489     hwPow.QWordValue:= QWord(hwPow.Round) * t.Frac + QWord(hwPow.Frac) * t.Round + ((QWord(hwPow.Frac) * t.Frac) shr 32);
   489     hwPow.QWordValue:= QWord(hwPow.Round) * t.Frac + QWord(hwPow.Frac) * t.Round + ((QWord(hwPow.Frac) * t.Frac) shr 32);
   490     dec(p)
   490     dec(p)
   491     end
   491     end
   492 end;
   492 end;
   493 
   493 
   494 function hwSqrt(const t: hwFloat): hwFloat;
   494 function hwSqrt1(const t: hwFloat): hwFloat;
   495 const pwr = 8; // even value, feel free to adjust
   495 const pwr = 8; // even value, feel free to adjust
   496       rThreshold = 1 shl (pwr + 32);
   496       rThreshold = 1 shl (pwr + 32);
   497       lThreshold = 1 shl (pwr div 2 + 32);
   497       lThreshold = 1 shl (pwr div 2 + 32);
   498 var l, r: QWord;
   498 var l, r: QWord;
   499     c: hwFloat;
   499     c: hwFloat;
   500 begin
   500 begin
   501 hwSqrt.isNegative:= false;
   501 hwSqrt1.isNegative:= false;
   502 
   502 
   503 if t.Round = 0 then
   503 if t.Round = 0 then
   504     begin
   504     begin
   505     l:= t.QWordValue;
   505     l:= t.QWordValue;
   506     r:= $100000000
   506     r:= $100000000
   529         r:= c.QWordValue
   529         r:= c.QWordValue
   530     else
   530     else
   531         l:= c.QWordValue
   531         l:= c.QWordValue
   532 until r - l <= 1;
   532 until r - l <= 1;
   533 
   533 
   534 hwSqrt.QWordValue:= l
   534 hwSqrt1.QWordValue:= l
   535 end;
   535 end;
       
   536 
       
   537 function hwSqrt(const x: hwFloat): hwFloat;
       
   538 var r, t, s, q: QWord;
       
   539     i: integer;
       
   540 begin
       
   541 hwSqrt.isNegative:= false;
       
   542 
       
   543 t:= $4000000000000000;
       
   544 r:= 0;
       
   545 q:= x.QWordValue;
       
   546 
       
   547 for i:= 0 to 31 do
       
   548     begin
       
   549     s:= r + t;
       
   550     r:= r shr 1;
       
   551     if s <= q then
       
   552         begin
       
   553         dec(q, s);
       
   554         inc(r, t);
       
   555         end;
       
   556     t:= t shr 2;
       
   557     end;
       
   558 
       
   559 hwSqrt.QWordValue:= r shl 16
       
   560 end;
       
   561 
       
   562 
   536 
   563 
   537 function Distance(const dx, dy: hwFloat): hwFloat;
   564 function Distance(const dx, dy: hwFloat): hwFloat;
   538 begin
   565 var r: QWord;
   539 Distance:= hwSqrt(hwSqr(dx) + hwSqr(dy))
   566 begin
       
   567 r:= dx.QWordValue or dy.QWordValue;
       
   568 
       
   569 if r < $10000 then
       
   570     begin
       
   571     Distance.QWordValue:= r;
       
   572     Distance.isNegative:= false
       
   573     end else
       
   574     Distance:= hwSqrt(hwSqr(dx) + hwSqr(dy))
   540 end;
   575 end;
   541 
   576 
   542 function DistanceI(const dx, dy: LongInt): hwFloat;
   577 function DistanceI(const dx, dy: LongInt): hwFloat;
   543 begin
   578 begin
   544 DistanceI:= hwSqrt(int2hwFloat(sqr(dx) + sqr(dy)))
   579 DistanceI:= hwSqrt(int2hwFloat(sqr(dx) + sqr(dy)))