hedgewars/uFloat.pas
changeset 7687 c73fd8cfa7c0
parent 7663 16e1422aee8e
child 7688 9daa06188551
equal deleted inserted replaced
7613:ce6ead3327b2 7687:c73fd8cfa7c0
   113        _0_000064: hwFloat = (isNegative: false; QWordValue:      274878);
   113        _0_000064: hwFloat = (isNegative: false; QWordValue:      274878);
   114          _0_0002: hwFloat = (isNegative: false; QWordValue:      858993);
   114          _0_0002: hwFloat = (isNegative: false; QWordValue:      858993);
   115          _0_0005: hwFloat = (isNegative: false; QWordValue:     2147484);
   115          _0_0005: hwFloat = (isNegative: false; QWordValue:     2147484);
   116           _0_001: hwFloat = (isNegative: false; QWordValue:     4294967);
   116           _0_001: hwFloat = (isNegative: false; QWordValue:     4294967);
   117           _0_003: hwFloat = (isNegative: false; QWordValue:    12884902);
   117           _0_003: hwFloat = (isNegative: false; QWordValue:    12884902);
       
   118          _0_0032: hwFloat = (isNegative: false; QWordValue:    13743895);
   118           _0_004: hwFloat = (isNegative: false; QWordValue:    17179869);
   119           _0_004: hwFloat = (isNegative: false; QWordValue:    17179869);
   119           _0_005: hwFloat = (isNegative: false; QWordValue:    21474836);
   120           _0_005: hwFloat = (isNegative: false; QWordValue:    21474836);
   120           _0_008: hwFloat = (isNegative: false; QWordValue:    34359738);
   121           _0_008: hwFloat = (isNegative: false; QWordValue:    34359738);
   121            _0_01: hwFloat = (isNegative: false; QWordValue:    42949673);
   122            _0_01: hwFloat = (isNegative: false; QWordValue:    42949673);
   122          _0_0128: hwFloat = (isNegative: false; QWordValue:    54975581);
   123          _0_0128: hwFloat = (isNegative: false; QWordValue:    54975581);
   147            _0_96: hwFloat = (isNegative: false; QWordValue:  4123168604);
   148            _0_96: hwFloat = (isNegative: false; QWordValue:  4123168604);
   148           _0_995: hwFloat = (isNegative: false; QWordValue:  4273492459);
   149           _0_995: hwFloat = (isNegative: false; QWordValue:  4273492459);
   149           _0_999: hwFloat = (isNegative: false; QWordValue:  4290672328);
   150           _0_999: hwFloat = (isNegative: false; QWordValue:  4290672328);
   150               _0: hwFloat = (isNegative: false; QWordValue:           0);
   151               _0: hwFloat = (isNegative: false; QWordValue:           0);
   151               _1: hwFloat = (isNegative: false; QWordValue:  4294967296);
   152               _1: hwFloat = (isNegative: false; QWordValue:  4294967296);
       
   153             _1_2: hwFloat = (isNegative: false; QWordValue:  1288490189*4);
   152             _1_5: hwFloat = (isNegative: false; QWordValue:  4294967296 * 3 div 2);
   154             _1_5: hwFloat = (isNegative: false; QWordValue:  4294967296 * 3 div 2);
   153             _1_6: hwFloat = (isNegative: false; QWordValue:  4294967296 * 8 div 5);
   155             _1_6: hwFloat = (isNegative: false; QWordValue:  4294967296 * 8 div 5);
   154             _1_9: hwFloat = (isNegative: false; QWordValue:  8160437862);
   156             _1_9: hwFloat = (isNegative: false; QWordValue:  8160437862);
   155               _2: hwFloat = (isNegative: false; QWordValue:  4294967296 * 2);
   157               _2: hwFloat = (isNegative: false; QWordValue:  4294967296 * 2);
   156             _2_4: hwFloat = (isNegative: false; QWordValue:  4294967296 * 12 div 5);
   158             _2_4: hwFloat = (isNegative: false; QWordValue:  4294967296 * 12 div 5);
   157               _3: hwFloat = (isNegative: false; QWordValue:  4294967296 * 3);
   159               _3: hwFloat = (isNegative: false; QWordValue:  4294967296 * 3);
       
   160             _3_2: hwFloat = (isNegative: false; QWordValue:  3435973837*4);
   158              _PI: hwFloat = (isNegative: false; QWordValue: 13493037704);
   161              _PI: hwFloat = (isNegative: false; QWordValue: 13493037704);
   159               _4: hwFloat = (isNegative: false; QWordValue:  4294967296 * 4);
   162               _4: hwFloat = (isNegative: false; QWordValue:  4294967296 * 4);
   160             _4_5: hwFloat = (isNegative: false; QWordValue:  4294967296 * 9 div 2);
   163             _4_5: hwFloat = (isNegative: false; QWordValue:  4294967296 * 9 div 2);
   161               _5: hwFloat = (isNegative: false; QWordValue:  4294967296 * 5);
   164               _5: hwFloat = (isNegative: false; QWordValue:  4294967296 * 5);
   162               _6: hwFloat = (isNegative: false; QWordValue:  4294967296 * 6);
   165               _6: hwFloat = (isNegative: false; QWordValue:  4294967296 * 6);
   201 uses uSinTable;
   204 uses uSinTable;
   202 
   205 
   203 
   206 
   204 {$IFDEF FPC}
   207 {$IFDEF FPC}
   205 
   208 
   206 function int2hwFloat (const i: LongInt) : hwFloat;
   209 function int2hwFloat (const i: LongInt) : hwFloat; inline;
   207 begin
   210 begin
   208 int2hwFloat.isNegative:= i < 0;
   211 int2hwFloat.isNegative:= i < 0;
   209 int2hwFloat.Round:= abs(i);
   212 int2hwFloat.Round:= abs(i);
   210 int2hwFloat.Frac:= 0
   213 int2hwFloat.Frac:= 0
   211 end;
   214 end;
   212 
   215 
   213 function hwFloat2Float (const i: hwFloat) : extended;
   216 function hwFloat2Float (const i: hwFloat) : extended; inline;
   214 begin
   217 begin
   215 hwFloat2Float:= i.QWordValue / $100000000;
   218 hwFloat2Float:= i.Frac / $100000000 + i.Round;
   216 if i.isNegative then
   219 if i.isNegative then
   217     hwFloat2Float:= -hwFloat2Float;
   220     hwFloat2Float:= -hwFloat2Float;
   218 end;
   221 end;
   219 
   222 
       
   223 {$IFNDEF WEB}
   220 operator = (const z1, z2: hwFloat) z : boolean; inline;
   224 operator = (const z1, z2: hwFloat) z : boolean; inline;
   221 begin
   225 begin
   222     z:= (z1.isNegative = z2.isNegative) and (z1.QWordValue = z2.QWordValue);
   226     z:= (z1.isNegative = z2.isNegative) and (z1.QWordValue = z2.QWordValue);
   223 end;
   227 end;
   224 
   228 
   227 begin
   231 begin
   228     z:= (z1.isNegative <> z2.isNegative) or (z1.QWordValue <> z2.QWordValue);
   232     z:= (z1.isNegative <> z2.isNegative) or (z1.QWordValue <> z2.QWordValue);
   229 end;
   233 end;
   230 {$ENDIF}
   234 {$ENDIF}
   231 
   235 
   232 operator + (const z1, z2: hwFloat) z : hwFloat;
   236 operator + (const z1, z2: hwFloat) z : hwFloat; inline;
   233 begin
   237 begin
   234 if z1.isNegative = z2.isNegative then
   238 if z1.isNegative = z2.isNegative then
   235     begin
   239     begin
   236     z.isNegative:= z1.isNegative;
   240     z.isNegative:= z1.isNegative;
   237     z.QWordValue:= z1.QWordValue + z2.QWordValue
   241     z.QWordValue:= z1.QWordValue + z2.QWordValue
   247         z.isNegative:= z2.isNegative;
   251         z.isNegative:= z2.isNegative;
   248         z.QWordValue:= z2.QWordValue - z1.QWordValue
   252         z.QWordValue:= z2.QWordValue - z1.QWordValue
   249         end
   253         end
   250 end;
   254 end;
   251 
   255 
   252 operator - (const z1, z2: hwFloat) z : hwFloat;
   256 operator - (const z1, z2: hwFloat) z : hwFloat; inline;
   253 begin
   257 begin
   254 if z1.isNegative = z2.isNegative then
   258 if z1.isNegative = z2.isNegative then
   255     if z1.QWordValue > z2.QWordValue then
   259     if z1.QWordValue > z2.QWordValue then
   256         begin
   260         begin
   257         z.isNegative:= z1.isNegative;
   261         z.isNegative:= z1.isNegative;
   267     z.isNegative:= z1.isNegative;
   271     z.isNegative:= z1.isNegative;
   268     z.QWordValue:= z1.QWordValue + z2.QWordValue
   272     z.QWordValue:= z1.QWordValue + z2.QWordValue
   269     end
   273     end
   270 end;
   274 end;
   271 
   275 
   272 operator - (const z1: hwFloat) z : hwFloat;
   276 function isZero(const z: hwFloat): boolean; inline; 
       
   277 begin
       
   278 isZero := z.QWordValue = 0;
       
   279 end;
       
   280 
       
   281 operator < (const z1, z2: hwFloat) b : boolean; inline;
       
   282 begin
       
   283 if z1.isNegative xor z2.isNegative then
       
   284     b:= z1.isNegative
       
   285 else
       
   286     if z1.QWordValue = z2.QWordValue then
       
   287         b:= false
       
   288     else
       
   289         b:= not((z1.QWordValue = z2.QWordValue) or ((z2.QWordValue < z1.QWordValue) <> z1.isNegative))
       
   290 end;
       
   291 
       
   292 operator > (const z1, z2: hwFloat) b : boolean; inline;
       
   293 begin
       
   294 if z1.isNegative xor z2.isNegative then
       
   295     b:= z2.isNegative
       
   296 else
       
   297     if z1.QWordValue = z2.QWordValue then
       
   298         b:= false
       
   299     else
       
   300         b:= (z1.QWordValue > z2.QWordValue) <> z2.isNegative
       
   301 end;
       
   302 {$ENDIF}
       
   303 {$IFDEF WEB}
       
   304 (*
       
   305     Mostly to be kind to JS as of 2012-08-27 where there is no int64/uint64.  This may change though.
       
   306 *)
       
   307 operator = (const z1, z2: hwFloat) z : boolean; inline;
       
   308 begin
       
   309     z:= (z1.isNegative = z2.isNegative) and (z1.Frac = z2.Frac) and (z1.Round = z2.Round);
       
   310 end;
       
   311 
       
   312 operator <> (const z1, z2: hwFloat) z : boolean; inline;
       
   313 begin
       
   314     z:= (z1.isNegative <> z2.isNegative) or (z1.Frac <> z2.Frac) or (z1.Round <> z2.Round);
       
   315 end;
       
   316 
       
   317 operator + (const z1, z2: hwFloat) z : hwFloat; inline;
       
   318 begin
       
   319 if z1.isNegative = z2.isNegative then
       
   320     begin
       
   321     z:= z1;
       
   322     z.Frac:= z.Frac + z2.Frac;
       
   323     z.Round:= z.Round + z2.Round;
       
   324     if z.Frac<z1.Frac then inc(z.Round)
       
   325     end
       
   326 else
       
   327     if (z1.Round > z2.Round) or ((z1.Round = z2.Round) and (z1.Frac > z2.Frac)) then
       
   328         begin
       
   329         z.isNegative:= z1.isNegative;
       
   330         z.Round:= z1.Round - z2.Round;
       
   331         z.Frac:= z1.Frac - z2.Frac;
       
   332         if z2.Frac > z1.Frac then dec(z.Round)
       
   333         end
       
   334     else
       
   335         begin
       
   336         z.isNegative:= z2.isNegative;
       
   337         z.Round:= z2.Round - z1.Round;
       
   338         z.Frac:= z2.Frac-z1.Frac;
       
   339         if z2.Frac < z1.Frac then dec(z.Round)
       
   340         end
       
   341 end;
       
   342 
       
   343 operator - (const z1, z2: hwFloat) z : hwFloat; inline;
       
   344 begin
       
   345 if z1.isNegative = z2.isNegative then
       
   346     if (z1.Round > z2.Round) or ((z1.Round = z2.Round) and (z1.Frac > z2.Frac)) then
       
   347         begin
       
   348         z.isNegative:= z1.isNegative;
       
   349         z.Round:= z1.Round - z2.Round;
       
   350         z.Frac:= z1.Frac-z2.Frac;
       
   351         if z2.Frac > z1.Frac then dec(z.Round)
       
   352         end
       
   353     else
       
   354         begin
       
   355         z.isNegative:= not z2.isNegative;
       
   356         z.Round:= z2.Round - z1.Round;
       
   357         z.Frac:= z2.Frac-z1.Frac;
       
   358         if z2.Frac < z1.Frac then dec(z.Round)
       
   359         end
       
   360 else
       
   361     begin
       
   362     z:= z1;
       
   363     z.Frac:= z.Frac + z2.Frac;
       
   364     z.Round:= z.Round + z2.Round;
       
   365     if z.Frac<z1.Frac then inc(z.Round)
       
   366     end
       
   367 end;
       
   368 
       
   369 operator < (const z1, z2: hwFloat) b : boolean; inline;
       
   370 begin
       
   371 if z1.isNegative xor z2.isNegative then
       
   372     b:= z1.isNegative
       
   373 else
       
   374 (*  Not so sure this specialcase is a win w/ Round/Frac. have to do more tests anyway.
       
   375     if (z1.Round = z2.Round and (z1.Frac = z2.Frac)) then
       
   376         b:= false
       
   377     else *)
       
   378         b:= ((z1.Round < z2.Round) or ((z1.Round = z2.Round) and (z1.Frac < z2.Frac))) <> z1.isNegative
       
   379 end;
       
   380 
       
   381 operator > (const z1, z2: hwFloat) b : boolean; inline;
       
   382 begin
       
   383 if z1.isNegative xor z2.isNegative then
       
   384     b:= z2.isNegative
       
   385 else
       
   386 (*
       
   387     if z1.QWordValue = z2.QWordValue then
       
   388         b:= false
       
   389     else*)
       
   390         b:= ((z1.Round > z2.Round) or ((z1.Round = z2.Round) and (z1.Frac > z2.Frac))) <> z1.isNegative
       
   391 end;
       
   392 
       
   393 function isZero(const z: hwFloat): boolean; inline; 
       
   394 begin
       
   395 isZero := (z.Round = 0) and (z.Frac = 0);
       
   396 end;
       
   397 {$ENDIF}
       
   398 
       
   399 operator - (const z1: hwFloat) z : hwFloat; inline;
   273 begin
   400 begin
   274 z:= z1;
   401 z:= z1;
   275 z.isNegative:= not z.isNegative
   402 z.isNegative:= not z.isNegative
   276 end;
   403 end;
   277 
   404 
   278 
   405 
   279 operator * (const z1, z2: hwFloat) z : hwFloat;
   406 operator * (const z1, z2: hwFloat) z : hwFloat; inline;
   280 begin
   407 begin
   281 z.isNegative:= z1.isNegative xor z2.isNegative;
   408 z.isNegative:= z1.isNegative xor z2.isNegative;
   282 z.QWordValue:= QWord(z1.Round) * z2.Frac + QWord(z1.Frac) * z2.Round + ((QWord(z1.Frac) * z2.Frac) shr 32);
   409 z.QWordValue:= QWord(z1.Round) * z2.Frac + QWord(z1.Frac) * z2.Round + ((QWord(z1.Frac) * z2.Frac) shr 32);
   283 z.Round:= z.Round + QWord(z1.Round) * z2.Round;
   410 z.Round:= z.Round + QWord(z1.Round) * z2.Round;
   284 end;
   411 end;
   285 
   412 
   286 operator * (const z1: hwFloat; const z2: LongInt) z : hwFloat;
   413 operator * (const z1: hwFloat; const z2: LongInt) z : hwFloat; inline;
   287 begin
   414 begin
   288 z.isNegative:= z1.isNegative xor (z2 < 0);
   415 z.isNegative:= z1.isNegative xor (z2 < 0);
   289 z.QWordValue:= z1.QWordValue * abs(z2)
   416 z.QWordValue:= z1.QWordValue * abs(z2)
   290 end;
   417 end;
   291 
   418 
   292 operator / (const z1: hwFloat; z2: hwFloat) z : hwFloat;
   419 operator / (const z1: hwFloat; z2: hwFloat) z : hwFloat; inline;
   293 var t: hwFloat;
   420 var t: hwFloat;
   294 begin
   421 begin
   295 z.isNegative:= z1.isNegative xor z2.isNegative;
   422 z.isNegative:= z1.isNegative xor z2.isNegative;
   296 z.Round:= z1.QWordValue div z2.QWordValue;
   423 z.Round:= z1.QWordValue div z2.QWordValue;
   297 t:= z1 - z2 * z.Round;
   424 t:= z1 - z2 * z.Round;
   309     else
   436     else
   310         z.Frac:= 0
   437         z.Frac:= 0
   311     end
   438     end
   312 end;
   439 end;
   313 
   440 
   314 operator / (const z1: hwFloat; const z2: LongInt) z : hwFloat;
   441 operator / (const z1: hwFloat; const z2: LongInt) z : hwFloat; inline;
   315 begin
   442 begin
   316 z.isNegative:= z1.isNegative xor (z2 < 0);
   443 z.isNegative:= z1.isNegative xor (z2 < 0);
   317 z.QWordValue:= z1.QWordValue div abs(z2)
   444 z.QWordValue:= z1.QWordValue div abs(z2)
   318 end;
       
   319 
       
   320 operator < (const z1, z2: hwFloat) b : boolean;
       
   321 begin
       
   322 if z1.isNegative xor z2.isNegative then
       
   323     b:= z1.isNegative
       
   324 else
       
   325     if z1.QWordValue = z2.QWordValue then
       
   326         b:= false
       
   327     else
       
   328         b:= (z1.QWordValue < z2.QWordValue) xor z1.isNegative
       
   329 end;
       
   330 
       
   331 operator > (const z1, z2: hwFloat) b : boolean;
       
   332 begin
       
   333 if z1.isNegative xor z2.isNegative then
       
   334     b:= z2.isNegative
       
   335 else
       
   336     if z1.QWordValue = z2.QWordValue then
       
   337         b:= false
       
   338     else
       
   339         b:= (z1.QWordValue > z2.QWordValue) xor z2.isNegative
       
   340 end;
   445 end;
   341 
   446 
   342 function cstr(const z: hwFloat): shortstring;
   447 function cstr(const z: hwFloat): shortstring;
   343 var tmpstr: shortstring;
   448 var tmpstr: shortstring;
   344 begin
   449 begin
   365 begin
   470 begin
   366 hwAbs:= t;
   471 hwAbs:= t;
   367 hwAbs.isNegative:= false
   472 hwAbs.isNegative:= false
   368 end;
   473 end;
   369 
   474 
   370 function hwSqr(const t: hwFloat): hwFloat;
   475 function hwSqr(const t: hwFloat): hwFloat; inline;
   371 begin
   476 begin
   372 hwSqr.isNegative:= false;
   477 hwSqr.isNegative:= false;
   373 hwSqr.QWordValue:= ((QWord(t.Round) * t.Round) shl 32) + QWord(t.Round) * t.Frac * 2 + ((QWord(t.Frac) * t.Frac) shr 32);
   478 hwSqr.QWordValue:= ((QWord(t.Round) * t.Round) shl 32) + QWord(t.Round) * t.Frac * 2 + ((QWord(t.Frac) * t.Frac) shr 32);
   374 end;
   479 end;
   375 
   480 
   466 if Angle < 1024 then
   571 if Angle < 1024 then
   467     AngleCos.QWordValue:= SinTable[1024 - Angle]
   572     AngleCos.QWordValue:= SinTable[1024 - Angle]
   468 else
   573 else
   469     AngleCos.QWordValue:= SinTable[Angle - 1024]
   574     AngleCos.QWordValue:= SinTable[Angle - 1024]
   470 end;
   575 end;
   471 
       
   472 function isZero(const z: hwFloat): boolean; inline; 
       
   473 begin
       
   474 isZero := z.QWordValue = 0;
       
   475 end;
       
   476 {$ENDIF}
   576 {$ENDIF}
   477 
   577 
   478 end.
   578 end.