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; |
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))) |