hedgewars/uFloat.pas
changeset 7628 bc7b1d228a2c
parent 7624 03d662ff9c41
child 7638 4560cd5b6ad0
equal deleted inserted replaced
7533:7ee319134713 7628:bc7b1d228a2c
   117           _0_003: hwFloat = (isNegative: false; QWordValue:    12884902);
   117           _0_003: hwFloat = (isNegative: false; QWordValue:    12884902);
   118           _0_004: hwFloat = (isNegative: false; QWordValue:    17179869);
   118           _0_004: hwFloat = (isNegative: false; QWordValue:    17179869);
   119           _0_005: hwFloat = (isNegative: false; QWordValue:    21474836);
   119           _0_005: hwFloat = (isNegative: false; QWordValue:    21474836);
   120           _0_008: hwFloat = (isNegative: false; QWordValue:    34359738);
   120           _0_008: hwFloat = (isNegative: false; QWordValue:    34359738);
   121            _0_01: hwFloat = (isNegative: false; QWordValue:    42949673);
   121            _0_01: hwFloat = (isNegative: false; QWordValue:    42949673);
       
   122          _0_0128: hwFloat = (isNegative: false; QWordValue:    54975581);
   122            _0_02: hwFloat = (isNegative: false; QWordValue:    85899345);
   123            _0_02: hwFloat = (isNegative: false; QWordValue:    85899345);
   123            _0_03: hwFloat = (isNegative: false; QWordValue:   128849018);
   124            _0_03: hwFloat = (isNegative: false; QWordValue:   128849018);
   124            _0_07: hwFloat = (isNegative: false; QWordValue:   300647710);
   125            _0_07: hwFloat = (isNegative: false; QWordValue:   300647710);
   125            _0_08: hwFloat = (isNegative: false; QWordValue:   343597383);
   126            _0_08: hwFloat = (isNegative: false; QWordValue:   343597383);
   126             _0_1: hwFloat = (isNegative: false; QWordValue:   429496730);
   127             _0_1: hwFloat = (isNegative: false; QWordValue:   429496730);
   147           _0_995: hwFloat = (isNegative: false; QWordValue:  4273492459);
   148           _0_995: hwFloat = (isNegative: false; QWordValue:  4273492459);
   148           _0_999: hwFloat = (isNegative: false; QWordValue:  4290672328);
   149           _0_999: hwFloat = (isNegative: false; QWordValue:  4290672328);
   149               _0: hwFloat = (isNegative: false; QWordValue:           0);
   150               _0: hwFloat = (isNegative: false; QWordValue:           0);
   150               _1: hwFloat = (isNegative: false; QWordValue:  4294967296);
   151               _1: hwFloat = (isNegative: false; QWordValue:  4294967296);
   151             _1_5: hwFloat = (isNegative: false; QWordValue:  4294967296 * 3 div 2);
   152             _1_5: hwFloat = (isNegative: false; QWordValue:  4294967296 * 3 div 2);
       
   153             _1_6: hwFloat = (isNegative: false; QWordValue:  4294967296 * 8 div 5);
   152             _1_9: hwFloat = (isNegative: false; QWordValue:  8160437862);
   154             _1_9: hwFloat = (isNegative: false; QWordValue:  8160437862);
   153               _2: hwFloat = (isNegative: false; QWordValue:  4294967296 * 2);
   155               _2: hwFloat = (isNegative: false; QWordValue:  4294967296 * 2);
       
   156             _2_4: hwFloat = (isNegative: false; QWordValue:  4294967296 * 12 div 5);
   154               _3: hwFloat = (isNegative: false; QWordValue:  4294967296 * 3);
   157               _3: hwFloat = (isNegative: false; QWordValue:  4294967296 * 3);
   155              _PI: hwFloat = (isNegative: false; QWordValue: 13493037704);
   158              _PI: hwFloat = (isNegative: false; QWordValue: 13493037704);
   156               _4: hwFloat = (isNegative: false; QWordValue:  4294967296 * 4);
   159               _4: hwFloat = (isNegative: false; QWordValue:  4294967296 * 4);
   157             _4_5: hwFloat = (isNegative: false; QWordValue:  4294967296 * 9 div 2);
   160             _4_5: hwFloat = (isNegative: false; QWordValue:  4294967296 * 9 div 2);
   158               _5: hwFloat = (isNegative: false; QWordValue:  4294967296 * 5);
   161               _5: hwFloat = (isNegative: false; QWordValue:  4294967296 * 5);
   159               _6: hwFloat = (isNegative: false; QWordValue:  4294967296 * 6);
   162               _6: hwFloat = (isNegative: false; QWordValue:  4294967296 * 6);
       
   163             _6_4: hwFloat = (isNegative: false; QWordValue:  3435973837 * 8);
       
   164               _7: hwFloat = (isNegative: false; QWordValue:  4294967296 * 7);
   160              _10: hwFloat = (isNegative: false; QWordValue:  4294967296 * 10);
   165              _10: hwFloat = (isNegative: false; QWordValue:  4294967296 * 10);
   161              _12: hwFloat = (isNegative: false; QWordValue:  4294967296 * 12);
   166              _12: hwFloat = (isNegative: false; QWordValue:  4294967296 * 12);
   162              _16: hwFloat = (isNegative: false; QWordValue:  4294967296 * 16);
   167              _16: hwFloat = (isNegative: false; QWordValue:  4294967296 * 16);
   163              _19: hwFloat = (isNegative: false; QWordValue:  4294967296 * 19);
   168              _19: hwFloat = (isNegative: false; QWordValue:  4294967296 * 19);
   164              _20: hwFloat = (isNegative: false; QWordValue:  4294967296 * 20);
   169              _20: hwFloat = (isNegative: false; QWordValue:  4294967296 * 20);
   165              _25: hwFloat = (isNegative: false; QWordValue:  4294967296 * 25);
   170              _25: hwFloat = (isNegative: false; QWordValue:  4294967296 * 25);
   166              _30: hwFloat = (isNegative: false; QWordValue:  4294967296 * 30);
   171              _30: hwFloat = (isNegative: false; QWordValue:  4294967296 * 30);
   167              _40: hwFloat = (isNegative: false; QWordValue:  4294967296 * 40);
   172              _40: hwFloat = (isNegative: false; QWordValue:  4294967296 * 40);
       
   173              _41: hwFloat = (isNegative: false; QWordValue:  4294967296 * 41);
       
   174              _49: hwFloat = (isNegative: false; QWordValue:  4294967296 * 49);
   168              _50: hwFloat = (isNegative: false; QWordValue:  4294967296 * 50);
   175              _50: hwFloat = (isNegative: false; QWordValue:  4294967296 * 50);
   169              _70: hwFloat = (isNegative: false; QWordValue:  4294967296 * 70);
   176              _70: hwFloat = (isNegative: false; QWordValue:  4294967296 * 70);
   170              _90: hwFloat = (isNegative: false; QWordValue:  4294967296 * 90);
   177              _90: hwFloat = (isNegative: false; QWordValue:  4294967296 * 90);
   171             _128: hwFloat = (isNegative: false; QWordValue:  4294967296 * 128);
   178             _128: hwFloat = (isNegative: false; QWordValue:  4294967296 * 128);
   172             _180: hwFloat = (isNegative: false; QWordValue:  4294967296 * 180);
   179             _180: hwFloat = (isNegative: false; QWordValue:  4294967296 * 180);
   194 uses uSinTable;
   201 uses uSinTable;
   195 
   202 
   196 
   203 
   197 {$IFDEF FPC}
   204 {$IFDEF FPC}
   198 
   205 
   199 function int2hwFloat (const i: LongInt) : hwFloat;
   206 function int2hwFloat (const i: LongInt) : hwFloat; inline;
   200 begin
   207 begin
   201 int2hwFloat.isNegative:= i < 0;
   208 int2hwFloat.isNegative:= i < 0;
   202 int2hwFloat.Round:= abs(i);
   209 int2hwFloat.Round:= abs(i);
   203 int2hwFloat.Frac:= 0
   210 int2hwFloat.Frac:= 0
   204 end;
   211 end;
   205 
   212 
   206 function hwFloat2Float (const i: hwFloat) : extended;
   213 function hwFloat2Float (const i: hwFloat) : extended; inline;
   207 begin
   214 begin
   208 hwFloat2Float:= i.QWordValue / $100000000;
   215 hwFloat2Float:= i.Frac / $100000000 + i.Round;
   209 if i.isNegative then
   216 if i.isNegative then
   210     hwFloat2Float:= -hwFloat2Float;
   217     hwFloat2Float:= -hwFloat2Float;
   211 end;
   218 end;
   212 
   219 
       
   220 {$IFNDEF WEB}
   213 operator = (const z1, z2: hwFloat) z : boolean; inline;
   221 operator = (const z1, z2: hwFloat) z : boolean; inline;
   214 begin
   222 begin
   215     z:= (z1.isNegative = z2.isNegative) and (z1.QWordValue = z2.QWordValue);
   223     z:= (z1.isNegative = z2.isNegative) and (z1.QWordValue = z2.QWordValue);
   216 end;
   224 end;
   217 
   225 
   220 begin
   228 begin
   221     z:= (z1.isNegative <> z2.isNegative) or (z1.QWordValue <> z2.QWordValue);
   229     z:= (z1.isNegative <> z2.isNegative) or (z1.QWordValue <> z2.QWordValue);
   222 end;
   230 end;
   223 {$ENDIF}
   231 {$ENDIF}
   224 
   232 
   225 operator + (const z1, z2: hwFloat) z : hwFloat;
   233 operator + (const z1, z2: hwFloat) z : hwFloat; inline;
   226 begin
   234 begin
   227 if z1.isNegative = z2.isNegative then
   235 if z1.isNegative = z2.isNegative then
   228     begin
   236     begin
   229     z.isNegative:= z1.isNegative;
   237     z.isNegative:= z1.isNegative;
   230     z.QWordValue:= z1.QWordValue + z2.QWordValue
   238     z.QWordValue:= z1.QWordValue + z2.QWordValue
   240         z.isNegative:= z2.isNegative;
   248         z.isNegative:= z2.isNegative;
   241         z.QWordValue:= z2.QWordValue - z1.QWordValue
   249         z.QWordValue:= z2.QWordValue - z1.QWordValue
   242         end
   250         end
   243 end;
   251 end;
   244 
   252 
   245 operator - (const z1, z2: hwFloat) z : hwFloat;
   253 operator - (const z1, z2: hwFloat) z : hwFloat; inline;
   246 begin
   254 begin
   247 if z1.isNegative = z2.isNegative then
   255 if z1.isNegative = z2.isNegative then
   248     if z1.QWordValue > z2.QWordValue then
   256     if z1.QWordValue > z2.QWordValue then
   249         begin
   257         begin
   250         z.isNegative:= z1.isNegative;
   258         z.isNegative:= z1.isNegative;
   260     z.isNegative:= z1.isNegative;
   268     z.isNegative:= z1.isNegative;
   261     z.QWordValue:= z1.QWordValue + z2.QWordValue
   269     z.QWordValue:= z1.QWordValue + z2.QWordValue
   262     end
   270     end
   263 end;
   271 end;
   264 
   272 
   265 operator - (const z1: hwFloat) z : hwFloat;
   273 function isZero(const z: hwFloat): boolean; inline; 
       
   274 begin
       
   275 isZero := z.QWordValue = 0;
       
   276 end;
       
   277 
       
   278 operator < (const z1, z2: hwFloat) b : boolean; inline;
       
   279 begin
       
   280 if z1.isNegative xor z2.isNegative then
       
   281     b:= z1.isNegative
       
   282 else
       
   283     if z1.QWordValue = z2.QWordValue then
       
   284         b:= false
       
   285     else
       
   286         b:= not((z1.QWordValue = z2.QWordValue) or ((z2.QWordValue < z1.QWordValue) <> z1.isNegative))
       
   287 end;
       
   288 
       
   289 operator > (const z1, z2: hwFloat) b : boolean; inline;
       
   290 begin
       
   291 if z1.isNegative xor z2.isNegative then
       
   292     b:= z2.isNegative
       
   293 else
       
   294     if z1.QWordValue = z2.QWordValue then
       
   295         b:= false
       
   296     else
       
   297         b:= (z1.QWordValue > z2.QWordValue) <> z2.isNegative
       
   298 end;
       
   299 {$ENDIF}
       
   300 {$IFDEF WEB}
       
   301 (*
       
   302     Mostly to be kind to JS as of 2012-08-27 where there is no int64/uint64.  This may change though.
       
   303 *)
       
   304 operator = (const z1, z2: hwFloat) z : boolean; inline;
       
   305 begin
       
   306     z:= (z1.isNegative = z2.isNegative) and (z1.Frac = z2.Frac) and (z1.Round = z2.Round);
       
   307 end;
       
   308 
       
   309 operator <> (const z1, z2: hwFloat) z : boolean; inline;
       
   310 begin
       
   311     z:= (z1.isNegative <> z2.isNegative) or (z1.Frac <> z2.Frac) or (z1.Round <> z2.Round);
       
   312 end;
       
   313 
       
   314 operator + (const z1, z2: hwFloat) z : hwFloat; inline;
       
   315 begin
       
   316 if z1.isNegative = z2.isNegative then
       
   317     begin
       
   318     z:= z1;
       
   319     z.Frac:= z.Frac + z2.Frac;
       
   320     z.Round:= z.Round + z2.Round;
       
   321     if z.Frac<z1.Frac then inc(z.Round)
       
   322     end
       
   323 else
       
   324     if (z1.Round > z2.Round) or ((z1.Round = z2.Round) and (z1.Frac > z2.Frac)) then
       
   325         begin
       
   326         z.isNegative:= z1.isNegative;
       
   327         z.Round:= z1.Round - z2.Round;
       
   328         z.Frac:= z1.Frac - z2.Frac;
       
   329         if z2.Frac > z1.Frac then dec(z.Round)
       
   330         end
       
   331     else
       
   332         begin
       
   333         z.isNegative:= z2.isNegative;
       
   334         z.Round:= z2.Round - z1.Round;
       
   335         z.Frac:= z2.Frac-z1.Frac;
       
   336         if z2.Frac < z1.Frac then dec(z.Round)
       
   337         end
       
   338 end;
       
   339 
       
   340 operator - (const z1, z2: hwFloat) z : hwFloat; inline;
       
   341 begin
       
   342 if z1.isNegative = z2.isNegative then
       
   343     if (z1.Round > z2.Round) or ((z1.Round = z2.Round) and (z1.Frac > z2.Frac)) then
       
   344         begin
       
   345         z.isNegative:= z1.isNegative;
       
   346         z.Round:= z1.Round - z2.Round;
       
   347         z.Frac:= z1.Frac-z2.Frac;
       
   348         if z2.Frac > z1.Frac then dec(z.Round)
       
   349         end
       
   350     else
       
   351         begin
       
   352         z.isNegative:= not z2.isNegative;
       
   353         z.Round:= z2.Round - z1.Round;
       
   354         z.Frac:= z2.Frac-z1.Frac;
       
   355         if z2.Frac < z1.Frac then dec(z.Round)
       
   356         end
       
   357 else
       
   358     begin
       
   359     z:= z1;
       
   360     z.Frac:= z.Frac + z2.Frac;
       
   361     z.Round:= z.Round + z2.Round;
       
   362     if z.Frac<z1.Frac then inc(z.Round)
       
   363     end
       
   364 end;
       
   365 
       
   366 operator < (const z1, z2: hwFloat) b : boolean; inline;
       
   367 begin
       
   368 if z1.isNegative xor z2.isNegative then
       
   369     b:= z1.isNegative
       
   370 else
       
   371 (*  Not so sure this specialcase is a win w/ Round/Frac. have to do more tests anyway.
       
   372     if (z1.Round = z2.Round and (z1.Frac = z2.Frac)) then
       
   373         b:= false
       
   374     else *)
       
   375         b:= ((z1.Round < z2.Round) or ((z1.Round = z2.Round) and (z1.Frac < z2.Frac))) <> z1.isNegative
       
   376 end;
       
   377 
       
   378 operator > (const z1, z2: hwFloat) b : boolean; inline;
       
   379 begin
       
   380 if z1.isNegative xor z2.isNegative then
       
   381     b:= z2.isNegative
       
   382 else
       
   383 (*
       
   384     if z1.QWordValue = z2.QWordValue then
       
   385         b:= false
       
   386     else*)
       
   387         b:= ((z1.Round > z2.Round) or ((z1.Round = z2.Round) and (z1.Frac > z2.Frac))) <> z1.isNegative
       
   388 end;
       
   389 
       
   390 function isZero(const z: hwFloat): boolean; inline; 
       
   391 begin
       
   392 isZero := z.Round = 0 and z.Frac = 0;
       
   393 end;
       
   394 {$ENDIF}
       
   395 
       
   396 operator - (const z1: hwFloat) z : hwFloat; inline;
   266 begin
   397 begin
   267 z:= z1;
   398 z:= z1;
   268 z.isNegative:= not z.isNegative
   399 z.isNegative:= not z.isNegative
   269 end;
   400 end;
   270 
   401 
   271 
   402 
   272 operator * (const z1, z2: hwFloat) z : hwFloat;
   403 operator * (const z1, z2: hwFloat) z : hwFloat; inline;
   273 begin
   404 begin
   274 z.isNegative:= z1.isNegative xor z2.isNegative;
   405 z.isNegative:= z1.isNegative xor z2.isNegative;
   275 z.QWordValue:= QWord(z1.Round) * z2.Frac + QWord(z1.Frac) * z2.Round + ((QWord(z1.Frac) * z2.Frac) shr 32);
   406 z.QWordValue:= QWord(z1.Round) * z2.Frac + QWord(z1.Frac) * z2.Round + ((QWord(z1.Frac) * z2.Frac) shr 32);
   276 z.Round:= z.Round + QWord(z1.Round) * z2.Round;
   407 z.Round:= z.Round + QWord(z1.Round) * z2.Round;
   277 end;
   408 end;
   278 
   409 
   279 operator * (const z1: hwFloat; const z2: LongInt) z : hwFloat;
   410 operator * (const z1: hwFloat; const z2: LongInt) z : hwFloat; inline;
   280 begin
   411 begin
   281 z.isNegative:= z1.isNegative xor (z2 < 0);
   412 z.isNegative:= z1.isNegative xor (z2 < 0);
   282 z.QWordValue:= z1.QWordValue * abs(z2)
   413 z.QWordValue:= z1.QWordValue * abs(z2)
   283 end;
   414 end;
   284 
   415 
   285 operator / (const z1: hwFloat; z2: hwFloat) z : hwFloat;
   416 operator / (const z1: hwFloat; z2: hwFloat) z : hwFloat; inline;
   286 var t: hwFloat;
   417 var t: hwFloat;
   287 begin
   418 begin
   288 z.isNegative:= z1.isNegative xor z2.isNegative;
   419 z.isNegative:= z1.isNegative xor z2.isNegative;
   289 z.Round:= z1.QWordValue div z2.QWordValue;
   420 z.Round:= z1.QWordValue div z2.QWordValue;
   290 t:= z1 - z2 * z.Round;
   421 t:= z1 - z2 * z.Round;
   302     else
   433     else
   303         z.Frac:= 0
   434         z.Frac:= 0
   304     end
   435     end
   305 end;
   436 end;
   306 
   437 
   307 operator / (const z1: hwFloat; const z2: LongInt) z : hwFloat;
   438 operator / (const z1: hwFloat; const z2: LongInt) z : hwFloat; inline;
   308 begin
   439 begin
   309 z.isNegative:= z1.isNegative xor (z2 < 0);
   440 z.isNegative:= z1.isNegative xor (z2 < 0);
   310 z.QWordValue:= z1.QWordValue div abs(z2)
   441 z.QWordValue:= z1.QWordValue div abs(z2)
   311 end;
       
   312 
       
   313 operator < (const z1, z2: hwFloat) b : boolean;
       
   314 begin
       
   315 if z1.isNegative xor z2.isNegative then
       
   316     b:= z1.isNegative
       
   317 else
       
   318     if z1.QWordValue = z2.QWordValue then
       
   319         b:= false
       
   320     else
       
   321         b:= (z1.QWordValue < z2.QWordValue) xor z1.isNegative
       
   322 end;
       
   323 
       
   324 operator > (const z1, z2: hwFloat) b : boolean;
       
   325 begin
       
   326 if z1.isNegative xor z2.isNegative then
       
   327     b:= z2.isNegative
       
   328 else
       
   329     if z1.QWordValue = z2.QWordValue then
       
   330         b:= false
       
   331     else
       
   332         b:= (z1.QWordValue > z2.QWordValue) xor z2.isNegative
       
   333 end;
   442 end;
   334 
   443 
   335 function cstr(const z: hwFloat): shortstring;
   444 function cstr(const z: hwFloat): shortstring;
   336 var tmpstr: shortstring;
   445 var tmpstr: shortstring;
   337 begin
   446 begin
   358 begin
   467 begin
   359 hwAbs:= t;
   468 hwAbs:= t;
   360 hwAbs.isNegative:= false
   469 hwAbs.isNegative:= false
   361 end;
   470 end;
   362 
   471 
   363 function hwSqr(const t: hwFloat): hwFloat;
   472 function hwSqr(const t: hwFloat): hwFloat; inline;
   364 begin
   473 begin
   365 hwSqr.isNegative:= false;
   474 hwSqr.isNegative:= false;
   366 hwSqr.QWordValue:= ((QWord(t.Round) * t.Round) shl 32) + QWord(t.Round) * t.Frac * 2 + ((QWord(t.Frac) * t.Frac) shr 32);
   475 hwSqr.QWordValue:= ((QWord(t.Round) * t.Round) shl 32) + QWord(t.Round) * t.Frac * 2 + ((QWord(t.Frac) * t.Frac) shr 32);
   367 end;
   476 end;
   368 
   477 
   369 function hwPow(const t: hwFloat;p: LongWord): hwFloat;
   478 function hwPow(const t: hwFloat;p: LongWord): hwFloat;
   370 begin
   479 begin
   371 hwPow:= t;
   480 hwPow:= t;
   372 if p mod 2 = 0 then hwPow.isNegative:= t.isNegative;
   481 if p mod 2 = 0 then hwPow.isNegative:= false;
   373 
   482 
   374 while p > 0 do
   483 while p > 0 do
   375     begin
   484     begin
   376     hwPow.QWordValue:= QWord(hwPow.Round) * t.Frac + QWord(hwPow.Frac) * t.Round + ((QWord(hwPow.Frac) * t.Frac) shr 32);
   485     hwPow.QWordValue:= QWord(hwPow.Round) * t.Frac + QWord(hwPow.Frac) * t.Round + ((QWord(hwPow.Frac) * t.Frac) shr 32);
   377     dec(p)
   486     dec(p)
   459 if Angle < 1024 then
   568 if Angle < 1024 then
   460     AngleCos.QWordValue:= SinTable[1024 - Angle]
   569     AngleCos.QWordValue:= SinTable[1024 - Angle]
   461 else
   570 else
   462     AngleCos.QWordValue:= SinTable[Angle - 1024]
   571     AngleCos.QWordValue:= SinTable[Angle - 1024]
   463 end;
   572 end;
   464 
       
   465 function isZero(const z: hwFloat): boolean; inline; 
       
   466 begin
       
   467 isZero := z.QWordValue = 0;
       
   468 end;
       
   469 {$ENDIF}
   573 {$ENDIF}
   470 
   574 
   471 end.
   575 end.