hedgewars/uFloat.pas
changeset 515 270f10276d2e
parent 513 69e06d710d46
child 538 74219eadab5e
equal deleted inserted replaced
514:fb8ba88a83c3 515:270f10276d2e
    34                0: (Round, Frac: Longword);
    34                0: (Round, Frac: Longword);
    35                1: (QWordValue : QWord);
    35                1: (QWordValue : QWord);
    36                end;
    36                end;
    37 {$endif FPC_LITTLE_ENDIAN}
    37 {$endif FPC_LITTLE_ENDIAN}
    38 
    38 
    39 function int2hwFloat (i: LongInt) : hwFloat;
    39 function int2hwFloat (const i: LongInt) : hwFloat;
    40 
    40 
    41 operator + (z1, z2: hwFloat) z : hwFloat;
    41 operator + (const z1, z2: hwFloat) z : hwFloat;
    42 operator - (z1, z2: hwFloat) z : hwFloat;
    42 operator - (const z1, z2: hwFloat) z : hwFloat;
    43 operator - (z1: hwFloat) z : hwFloat;
    43 operator - (const z1: hwFloat) z : hwFloat;
    44 
    44 
    45 operator * (z1, z2: hwFloat) z : hwFloat;
    45 operator * (const z1, z2: hwFloat) z : hwFloat;
    46 operator * (z1: hwFloat; z2: LongInt) z : hwFloat;
    46 operator * (const z1: hwFloat; const z2: LongInt) z : hwFloat;
    47 operator / (z1, z2: hwFloat) z : hwFloat;
    47 operator / (const z1: hwFloat; z2: hwFloat) z : hwFloat;
    48 operator / (z1: hwFloat; z2: LongInt) z : hwFloat;
    48 operator / (const z1: hwFloat; const z2: LongInt) z : hwFloat;
    49 
    49 
    50 operator < (z1, z2: hwFloat) b : boolean;
    50 operator < (const z1, z2: hwFloat) b : boolean;
    51 operator > (z1, z2: hwFloat) b : boolean;
    51 operator > (const z1, z2: hwFloat) b : boolean;
    52 
    52 
    53 function cstr(z: hwFloat): string;
    53 function cstr(const z: hwFloat): string;
    54 function hwRound(t: hwFloat): LongInt;
    54 function hwRound(const t: hwFloat): LongInt;
    55 function hwAbs(t: hwFloat): hwFloat;
    55 function hwAbs(const t: hwFloat): hwFloat;
    56 function hwSqr(t: hwFloat): hwFloat;
    56 function hwSqr(const t: hwFloat): hwFloat;
    57 function hwSqrt(t: hwFloat): hwFloat;
    57 function hwSqrt(const t: hwFloat): hwFloat;
    58 function Distance(dx, dy: hwFloat): hwFloat;
    58 function Distance(const dx, dy: hwFloat): hwFloat;
    59 function DistanceI(dx, dy: LongInt): hwFloat;
    59 function DistanceI(const dx, dy: LongInt): hwFloat;
    60 function AngleSin(Angle: Longword): hwFloat;
    60 function AngleSin(const Angle: Longword): hwFloat;
    61 function AngleCos(Angle: Longword): hwFloat;
    61 function AngleCos(const Angle: Longword): hwFloat;
    62 function SignAs(num, signum: hwFloat): hwFloat;
    62 function SignAs(const num, signum: hwFloat): hwFloat;
    63 
    63 
    64 const  _1div1024: hwFloat = (isNegative: false; QWordValue:     4194304);
    64 const  _1div1024: hwFloat = (isNegative: false; QWordValue:     4194304);
    65       _1div10000: hwFloat = (isNegative: false; QWordValue:      429496);
    65       _1div10000: hwFloat = (isNegative: false; QWordValue:      429496);
    66       _1div50000: hwFloat = (isNegative: false; QWordValue:       85899);
    66       _1div50000: hwFloat = (isNegative: false; QWordValue:       85899);
    67      _1div100000: hwFloat = (isNegative: false; QWordValue:       42950);
    67      _1div100000: hwFloat = (isNegative: false; QWordValue:       42950);
   129 implementation
   129 implementation
   130 uses uConsts;
   130 uses uConsts;
   131 
   131 
   132 {$IFDEF FPC}
   132 {$IFDEF FPC}
   133 
   133 
   134 function int2hwFloat (i: LongInt) : hwFloat;
   134 function int2hwFloat (const i: LongInt) : hwFloat;
   135 begin
   135 begin
   136 int2hwFloat.isNegative:= i < 0;
   136 int2hwFloat.isNegative:= i < 0;
   137 int2hwFloat.Round:= abs(i);
   137 int2hwFloat.Round:= abs(i);
   138 int2hwFloat.Frac:= 0
   138 int2hwFloat.Frac:= 0
   139 end;
   139 end;
   140 
   140 
   141 operator + (z1, z2: hwFloat) z : hwFloat;
   141 operator + (const z1, z2: hwFloat) z : hwFloat;
   142 begin
   142 begin
   143 if z1.isNegative = z2.isNegative then
   143 if z1.isNegative = z2.isNegative then
   144    begin
   144    begin
   145    z.isNegative:= z1.isNegative;
   145    z.isNegative:= z1.isNegative;
   146    z.QWordValue:= z1.QWordValue + z2.QWordValue
   146    z.QWordValue:= z1.QWordValue + z2.QWordValue
   155       z.isNegative:= z2.isNegative;
   155       z.isNegative:= z2.isNegative;
   156       z.QWordValue:= z2.QWordValue - z1.QWordValue
   156       z.QWordValue:= z2.QWordValue - z1.QWordValue
   157       end
   157       end
   158 end;
   158 end;
   159 
   159 
   160 operator - (z1, z2: hwFloat) z : hwFloat;
   160 operator - (const z1, z2: hwFloat) z : hwFloat;
   161 begin
   161 begin
   162 if z1.isNegative = z2.isNegative then
   162 if z1.isNegative = z2.isNegative then
   163    if z1.QWordValue > z2.QWordValue then
   163    if z1.QWordValue > z2.QWordValue then
   164       begin
   164       begin
   165       z.isNegative:= z1.isNegative;
   165       z.isNegative:= z1.isNegative;
   173      z.isNegative:= z1.isNegative;
   173      z.isNegative:= z1.isNegative;
   174      z.QWordValue:= z1.QWordValue + z2.QWordValue
   174      z.QWordValue:= z1.QWordValue + z2.QWordValue
   175      end
   175      end
   176 end;
   176 end;
   177 
   177 
   178 operator - (z1: hwFloat) z : hwFloat;
   178 operator - (const z1: hwFloat) z : hwFloat;
   179 begin
   179 begin
   180 z:= z1;
   180 z:= z1;
   181 z.isNegative:= not z.isNegative
   181 z.isNegative:= not z.isNegative
   182 end;
   182 end;
   183 
   183 
   184 
   184 
   185 operator * (z1, z2: hwFloat) z : hwFloat;
   185 operator * (const z1, z2: hwFloat) z : hwFloat;
   186 begin
   186 begin
   187 z.isNegative:= z1.isNegative xor z2.isNegative;
   187 z.isNegative:= z1.isNegative xor z2.isNegative;
   188 z.QWordValue:= QWord(z1.Round) * z2.Frac +
   188 z.QWordValue:= QWord(z1.Round) * z2.Frac +
   189                QWord(z1.Frac) * z2.Round +
   189                QWord(z1.Frac) * z2.Round +
   190                ((QWord(z1.Frac) * z2.Frac) shr 32);
   190                ((QWord(z1.Frac) * z2.Frac) shr 32);
   191 z.Round:= z.Round + QWord(z1.Round) * z2.Round;
   191 z.Round:= z.Round + QWord(z1.Round) * z2.Round;
   192 end;
   192 end;
   193 
   193 
   194 operator * (z1: hwFloat; z2: LongInt) z : hwFloat;
   194 operator * (const z1: hwFloat; const z2: LongInt) z : hwFloat;
   195 begin
   195 begin
   196 z.isNegative:= z1.isNegative xor (z2 < 0);
   196 z.isNegative:= z1.isNegative xor (z2 < 0);
   197 z2:= abs(z2);
   197 z.QWordValue:= z1.QWordValue * abs(z2)
   198 z.QWordValue:= z1.QWordValue * z2
   198 end;
   199 end;
   199 
   200 
   200 operator / (const z1: hwFloat; z2: hwFloat) z : hwFloat;
   201 operator / (z1, z2: hwFloat) z : hwFloat;
       
   202 var t: hwFloat;
   201 var t: hwFloat;
   203 begin
   202 begin
   204 z.isNegative:= z1.isNegative xor z2.isNegative;
   203 z.isNegative:= z1.isNegative xor z2.isNegative;
   205 z.Round:= z1.QWordValue div z2.QWordValue;
   204 z.Round:= z1.QWordValue div z2.QWordValue;
   206 t:= z1 - z2 * z.Round;
   205 t:= z1 - z2 * z.Round;
   216          end;
   215          end;
   217    z.Frac:= (t.QWordValue) div (z2.Round)
   216    z.Frac:= (t.QWordValue) div (z2.Round)
   218    end
   217    end
   219 end;
   218 end;
   220 
   219 
   221 operator / (z1: hwFloat; z2: LongInt) z : hwFloat;
   220 operator / (const z1: hwFloat; const z2: LongInt) z : hwFloat;
   222 begin
   221 begin
   223 z.isNegative:= z1.isNegative xor (z2 < 0);
   222 z.isNegative:= z1.isNegative xor (z2 < 0);
   224 z2:= abs(z2);
   223 z.QWordValue:= z1.QWordValue div abs(z2)
   225 z.QWordValue:= z1.QWordValue div z2
   224 end;
   226 end;
   225 
   227 
   226 operator < (const z1, z2: hwFloat) b : boolean;
   228 operator < (z1, z2: hwFloat) b : boolean;
       
   229 begin
   227 begin
   230 if z1.isNegative <> z2.isNegative then
   228 if z1.isNegative <> z2.isNegative then
   231    b:= z1.isNegative
   229    b:= z1.isNegative
   232 else
   230 else
   233    if z1.QWordValue = z2.QWordValue then
   231    if z1.QWordValue = z2.QWordValue then
   234       b:= false
   232       b:= false
   235    else
   233    else
   236       b:= (z1.QWordValue < z2.QWordValue) xor z1.isNegative
   234       b:= (z1.QWordValue < z2.QWordValue) xor z1.isNegative
   237 end;
   235 end;
   238 
   236 
   239 operator > (z1, z2: hwFloat) b : boolean;
   237 operator > (const z1, z2: hwFloat) b : boolean;
   240 begin
   238 begin
   241 if z1.isNegative <> z2.isNegative then
   239 if z1.isNegative <> z2.isNegative then
   242    b:= z2.isNegative
   240    b:= z2.isNegative
   243 else
   241 else
   244    if z1.QWordValue = z2.QWordValue then
   242    if z1.QWordValue = z2.QWordValue then
   245       b:= false
   243       b:= false
   246    else
   244    else
   247       b:= (z1.QWordValue > z2.QWordValue) xor z2.isNegative
   245       b:= (z1.QWordValue > z2.QWordValue) xor z2.isNegative
   248 end;
   246 end;
   249 
   247 
   250 function cstr(z: hwFloat): string;
   248 function cstr(const z: hwFloat): string;
   251 var tmpstr: string;
   249 var tmpstr: string;
   252 begin
   250 begin
   253 str(z.Round, cstr);
   251 str(z.Round, cstr);
   254 if z.Frac <> 0 then
   252 if z.Frac <> 0 then
   255    begin
   253    begin
   258    cstr:= cstr + '.' + tmpstr
   256    cstr:= cstr + '.' + tmpstr
   259    end;
   257    end;
   260 if z.isNegative then cstr:= '-' + cstr
   258 if z.isNegative then cstr:= '-' + cstr
   261 end;
   259 end;
   262 
   260 
   263 function hwRound(t: hwFloat): LongInt;
   261 function hwRound(const t: hwFloat): LongInt;
   264 begin
   262 begin
   265 if t.isNegative then hwRound:= -t.Round
   263 if t.isNegative then hwRound:= -t.Round
   266                 else hwRound:= t.Round
   264                 else hwRound:= t.Round
   267 end;
   265 end;
   268 
   266 
   269 function hwAbs(t: hwFloat): hwFloat;
   267 function hwAbs(const t: hwFloat): hwFloat;
   270 begin
   268 begin
   271 hwAbs:= t;
   269 hwAbs:= t;
   272 hwAbs.isNegative:= false
   270 hwAbs.isNegative:= false
   273 end;
   271 end;
   274 
   272 
   275 function hwSqr(t: hwFloat): hwFloat;
   273 function hwSqr(const t: hwFloat): hwFloat;
   276 begin
   274 begin
   277 hwSqr:= t * t
   275 hwSqr:= t * t
   278 end;
   276 end;
   279 
   277 
   280 function hwSqrt(t: hwFloat): hwFloat;
   278 function hwSqrt(const t: hwFloat): hwFloat;
   281 begin
   279 begin
   282 hwSqrt.isNegative:= false;
   280 hwSqrt.isNegative:= false;
   283 hwSqrt.QWordValue:= Round(sqrt(1.0 / $100000000 * (t.QWordValue)) * $100000000)
   281 hwSqrt.QWordValue:= Round(sqrt(1.0 / $100000000 * (t.QWordValue)) * $100000000)
   284 end;
   282 end;
   285 
   283 
   286 function Distance(dx, dy: hwFloat): hwFloat;
   284 function Distance(const dx, dy: hwFloat): hwFloat;
   287 var x, y: hwFloat;
   285 var x, y: hwFloat;
   288     Result: hwFloat;
   286     Result: hwFloat;
   289 begin
   287 begin
   290 x:= dx * dx;
   288 x:= dx * dx;
   291 y:= dy * dy;
   289 y:= dy * dy;
   292 Result:= x + y;
   290 Result:= x + y;
   293 Result.QWordValue:= Round(sqrt(1.0 / $100000000 * (Result.QWordValue)) * $100000000);
   291 Result.QWordValue:= Round(sqrt(1.0 / $100000000 * (Result.QWordValue)) * $100000000);
   294 Distance:= Result
   292 Distance:= Result
   295 end;
   293 end;
   296 
   294 
   297 function DistanceI(dx, dy: LongInt): hwFloat;
   295 function DistanceI(const dx, dy: LongInt): hwFloat;
   298 begin
   296 begin
   299 DistanceI:= Distance(int2hwFloat(dx), int2hwFloat(dy))
   297 DistanceI:= Distance(int2hwFloat(dx), int2hwFloat(dy))
   300 end;
   298 end;
   301 
   299 
   302 function SignAs(num, signum: hwFloat): hwFloat;
   300 function SignAs(const num, signum: hwFloat): hwFloat;
   303 begin
   301 begin
   304 SignAs:= num;
   302 SignAs:= num;
   305 SignAs.isNegative:= signum.isNegative
   303 SignAs.isNegative:= signum.isNegative
   306 end;
   304 end;
   307 
   305 
   308 {$INCLUDE SinTable.inc}
   306 {$INCLUDE SinTable.inc}
   309 
   307 
   310 function AngleSin(Angle: Longword): hwFloat;
   308 function AngleSin(const Angle: Longword): hwFloat;
   311 begin
   309 begin
   312 AngleSin.isNegative:= false;
   310 AngleSin.isNegative:= false;
   313 if Angle < 1024 then AngleSin.QWordValue:= SinTable[Angle]
   311 if Angle < 1024 then AngleSin.QWordValue:= SinTable[Angle]
   314                 else AngleSin.QWordValue:= SinTable[2048 - Angle]
   312                 else AngleSin.QWordValue:= SinTable[2048 - Angle]
   315 end;
   313 end;
   316 
   314 
   317 function AngleCos(Angle: Longword): hwFloat;
   315 function AngleCos(const Angle: Longword): hwFloat;
   318 begin
   316 begin
   319 AngleCos.isNegative:= Angle > 1024;
   317 AngleCos.isNegative:= Angle > 1024;
   320 if Angle < 1024 then AngleCos.QWordValue:= SinTable[1024 - Angle]
   318 if Angle < 1024 then AngleCos.QWordValue:= SinTable[1024 - Angle]
   321                 else AngleCos.QWordValue:= SinTable[Angle - 1024]
   319                 else AngleCos.QWordValue:= SinTable[Angle - 1024]
   322 end;
   320 end;