hedgewars/uFloat.pas
branch0.9.19
changeset 8924 13ac59499066
parent 8921 e5db2a42e7e8
child 9080 9b42757d7e71
equal deleted inserted replaced
8904:6ea838b8dcd5 8924:13ac59499066
    82 function cstr(const z: hwFloat): shortstring; // Returns a shortstring representations of the hwFloat.
    82 function cstr(const z: hwFloat): shortstring; // Returns a shortstring representations of the hwFloat.
    83 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)
    83 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)
    84 function hwAbs(const t: hwFloat): hwFloat; inline; // Returns the value of t with positive sign.
    84 function hwAbs(const t: hwFloat): hwFloat; inline; // Returns the value of t with positive sign.
    85 function hwSqr(const t: hwFloat): hwFloat; inline; // Returns the square value of parameter t.
    85 function hwSqr(const t: hwFloat): hwFloat; inline; // Returns the square value of parameter t.
    86 function hwPow(const t: hwFloat; p: LongWord): hwFloat; inline; // Returns the power of the value
    86 function hwPow(const t: hwFloat; p: LongWord): hwFloat; inline; // Returns the power of the value
    87 function hwSqrt(const t: hwFloat): hwFloat; inline; // Returns the the positive square root of parameter t.
    87 function hwSqrt1(const t: hwFloat): hwFloat; inline; // Returns the the positive square root of parameter t.
       
    88 function hwSqrt(const x: hwFloat): hwFloat; inline; // Returns the the positive square root of parameter t.
    88 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.
    89 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.
    89 function DistanceI(const dx, dy: LongInt): hwFloat; // Same as above for integer parameters.
    90 function DistanceI(const dx, dy: LongInt): hwFloat; // Same as above for integer parameters.
    90 function AngleSin(const Angle: Longword): hwFloat;
    91 function AngleSin(const Angle: Longword): hwFloat;
    91 function AngleCos(const Angle: Longword): hwFloat;
    92 function AngleCos(const Angle: Longword): hwFloat;
    92 function vector2Angle(const x, y: hwFloat): LongInt;
    93 function vector2Angle(const x, y: hwFloat): LongInt;
   262     z.isNegative:= z1.isNegative;
   263     z.isNegative:= z1.isNegative;
   263     z.QWordValue:= z1.QWordValue + z2.QWordValue
   264     z.QWordValue:= z1.QWordValue + z2.QWordValue
   264     end
   265     end
   265 end;
   266 end;
   266 
   267 
   267 function isZero(const z: hwFloat): boolean; inline; 
   268 function isZero(const z: hwFloat): boolean; inline;
   268 begin
   269 begin
   269 isZero := z.QWordValue = 0;
   270 isZero := z.QWordValue = 0;
   270 end;
   271 end;
   271 
   272 
   272 operator < (const z1, z2: hwFloat) b : boolean; inline;
   273 operator < (const z1, z2: hwFloat) b : boolean; inline;
   275     b:= z1.isNegative
   276     b:= z1.isNegative
   276 else
   277 else
   277     if z1.QWordValue = z2.QWordValue then
   278     if z1.QWordValue = z2.QWordValue then
   278         b:= false
   279         b:= false
   279     else
   280     else
   280         b:= not((z1.QWordValue = z2.QWordValue) or ((z2.QWordValue < z1.QWordValue) <> z1.isNegative))
   281         b:= (z2.QWordValue < z1.QWordValue) = z1.isNegative
   281 end;
   282 end;
   282 
   283 
   283 operator > (const z1, z2: hwFloat) b : boolean; inline;
   284 operator > (const z1, z2: hwFloat) b : boolean; inline;
   284 begin
   285 begin
   285 if z1.isNegative xor z2.isNegative then
   286 if z1.isNegative xor z2.isNegative then
   310 z.isNegative:= z1.isNegative xor (z2 < 0);
   311 z.isNegative:= z1.isNegative xor (z2 < 0);
   311 z.QWordValue:= z1.QWordValue * abs(z2)
   312 z.QWordValue:= z1.QWordValue * abs(z2)
   312 end;
   313 end;
   313 
   314 
   314 operator / (const z1: hwFloat; z2: hwFloat) z : hwFloat; inline;
   315 operator / (const z1: hwFloat; z2: hwFloat) z : hwFloat; inline;
   315 var t: hwFloat;
   316 var t: QWord;
   316 begin
   317 begin
   317 z.isNegative:= z1.isNegative xor z2.isNegative;
   318 z.isNegative:= z1.isNegative xor z2.isNegative;
   318 z.Round:= z1.QWordValue div z2.QWordValue;
   319 z.Round:= z1.QWordValue div z2.QWordValue;
   319 t:= z1 - z2 * z.Round;
   320 t:= z1.QWordValue - z2.QWordValue * z.Round;
   320 if t.QWordValue = 0 then
   321 z.Frac:= 0;
   321     z.Frac:= 0
   322 
   322 else
   323 if t <> 0 then
   323     begin
   324     begin
   324     while ((t.QWordValue and $8000000000000000) = 0) and ((z2.QWordValue and $8000000000000000) = 0) do
   325     while ((t and $FF00000000000000) = 0) and ((z2.QWordValue and $FF00000000000000) = 0) do
   325         begin
   326         begin
   326         t.QWordValue:= t.QWordValue shl 1;
   327         t:= t shl 8;
   327         z2.QWordValue:= z2.QWordValue shl 1
   328         z2.QWordValue:= z2.QWordValue shl 8
   328         end;
   329         end;
       
   330 
   329     if z2.Round > 0 then
   331     if z2.Round > 0 then
   330         z.Frac:= (t.QWordValue) div (z2.Round)
   332         inc(z.QWordValue, t div z2.Round);
   331     else
       
   332         z.Frac:= 0
       
   333     end
   333     end
   334 end;
   334 end;
   335 
   335 
   336 operator / (const z1: hwFloat; const z2: LongInt) z : hwFloat; inline;
   336 operator / (const z1: hwFloat; const z2: LongInt) z : hwFloat; inline;
   337 begin
   337 begin
   383     hwPow.QWordValue:= QWord(hwPow.Round) * t.Frac + QWord(hwPow.Frac) * t.Round + ((QWord(hwPow.Frac) * t.Frac) shr 32);
   383     hwPow.QWordValue:= QWord(hwPow.Round) * t.Frac + QWord(hwPow.Frac) * t.Round + ((QWord(hwPow.Frac) * t.Frac) shr 32);
   384     dec(p)
   384     dec(p)
   385     end
   385     end
   386 end;
   386 end;
   387 
   387 
   388 function hwSqrt(const t: hwFloat): hwFloat;
   388 function hwSqrt1(const t: hwFloat): hwFloat;
   389 const pwr = 8; // even value, feel free to adjust
   389 const pwr = 8; // even value, feel free to adjust
   390       rThreshold = 1 shl (pwr + 32);
   390       rThreshold = 1 shl (pwr + 32);
   391       lThreshold = 1 shl (pwr div 2 + 32);
   391       lThreshold = 1 shl (pwr div 2 + 32);
   392 var l, r: QWord;
   392 var l, r: QWord;
   393     c: hwFloat;
   393     c: hwFloat;
   394 begin
   394 begin
   395 hwSqrt.isNegative:= false;
   395 hwSqrt1.isNegative:= false;
   396 
   396 
   397 if t.Round = 0 then
   397 if t.Round = 0 then
   398     begin
   398     begin
   399     l:= t.QWordValue;
   399     l:= t.QWordValue;
   400     r:= $100000000
   400     r:= $100000000
   423         r:= c.QWordValue
   423         r:= c.QWordValue
   424     else
   424     else
   425         l:= c.QWordValue
   425         l:= c.QWordValue
   426 until r - l <= 1;
   426 until r - l <= 1;
   427 
   427 
   428 hwSqrt.QWordValue:= l
   428 hwSqrt1.QWordValue:= l
   429 end;
   429 end;
       
   430 
       
   431 function hwSqrt(const x: hwFloat): hwFloat;
       
   432 var r, t, s, q: QWord;
       
   433     i: integer;
       
   434 begin
       
   435 hwSqrt.isNegative:= false;
       
   436 
       
   437 t:= $4000000000000000;
       
   438 r:= 0;
       
   439 q:= x.QWordValue;
       
   440 
       
   441 for i:= 0 to 31 do
       
   442     begin
       
   443     s:= r + t;
       
   444     r:= r shr 1;
       
   445     if s <= q then
       
   446         begin
       
   447         dec(q, s);
       
   448         inc(r, t);
       
   449         end;
       
   450     t:= t shr 2;
       
   451     end;
       
   452 
       
   453 hwSqrt.QWordValue:= r shl 16
       
   454 end;
       
   455 
       
   456 
   430 
   457 
   431 function Distance(const dx, dy: hwFloat): hwFloat;
   458 function Distance(const dx, dy: hwFloat): hwFloat;
   432 begin
   459 var r: QWord;
   433 Distance:= hwSqrt(hwSqr(dx) + hwSqr(dy))
   460 begin
       
   461 r:= dx.QWordValue or dy.QWordValue;
       
   462 
       
   463 if r < $10000 then
       
   464     begin
       
   465     Distance.QWordValue:= r;
       
   466     Distance.isNegative:= false
       
   467     end else
       
   468     Distance:= hwSqrt(hwSqr(dx) + hwSqr(dy))
   434 end;
   469 end;
   435 
   470 
   436 function DistanceI(const dx, dy: LongInt): hwFloat;
   471 function DistanceI(const dx, dy: LongInt): hwFloat;
   437 begin
   472 begin
   438 DistanceI:= hwSqrt(int2hwFloat(sqr(dx) + sqr(dy)))
   473 DistanceI:= hwSqrt(int2hwFloat(sqr(dx) + sqr(dy)))