diff -r c3ccec3834e8 -r 29bc9c36ad5f hedgewars/uFloat.pas --- /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 + * + * 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.