hedgewars/uFloat.pas
changeset 7624 03d662ff9c41
parent 7623 addc5b262617
child 7638 4560cd5b6ad0
equal deleted inserted replaced
7623:addc5b262617 7624:03d662ff9c41
   201 uses uSinTable;
   201 uses uSinTable;
   202 
   202 
   203 
   203 
   204 {$IFDEF FPC}
   204 {$IFDEF FPC}
   205 
   205 
   206 function int2hwFloat (const i: LongInt) : hwFloat;
   206 function int2hwFloat (const i: LongInt) : hwFloat; inline;
   207 begin
   207 begin
   208 int2hwFloat.isNegative:= i < 0;
   208 int2hwFloat.isNegative:= i < 0;
   209 int2hwFloat.Round:= abs(i);
   209 int2hwFloat.Round:= abs(i);
   210 int2hwFloat.Frac:= 0
   210 int2hwFloat.Frac:= 0
   211 end;
   211 end;
   212 
   212 
   213 function hwFloat2Float (const i: hwFloat) : extended;
   213 function hwFloat2Float (const i: hwFloat) : extended; inline;
   214 begin
   214 begin
   215 hwFloat2Float:= i.Frac / $100000000 + i.Round;
   215 hwFloat2Float:= i.Frac / $100000000 + i.Round;
   216 if i.isNegative then
   216 if i.isNegative then
   217     hwFloat2Float:= -hwFloat2Float;
   217     hwFloat2Float:= -hwFloat2Float;
   218 end;
   218 end;
   228 begin
   228 begin
   229     z:= (z1.isNegative <> z2.isNegative) or (z1.QWordValue <> z2.QWordValue);
   229     z:= (z1.isNegative <> z2.isNegative) or (z1.QWordValue <> z2.QWordValue);
   230 end;
   230 end;
   231 {$ENDIF}
   231 {$ENDIF}
   232 
   232 
   233 operator + (const z1, z2: hwFloat) z : hwFloat;
   233 operator + (const z1, z2: hwFloat) z : hwFloat; inline;
   234 begin
   234 begin
   235 if z1.isNegative = z2.isNegative then
   235 if z1.isNegative = z2.isNegative then
   236     begin
   236     begin
   237     z.isNegative:= z1.isNegative;
   237     z.isNegative:= z1.isNegative;
   238     z.QWordValue:= z1.QWordValue + z2.QWordValue
   238     z.QWordValue:= z1.QWordValue + z2.QWordValue
   248         z.isNegative:= z2.isNegative;
   248         z.isNegative:= z2.isNegative;
   249         z.QWordValue:= z2.QWordValue - z1.QWordValue
   249         z.QWordValue:= z2.QWordValue - z1.QWordValue
   250         end
   250         end
   251 end;
   251 end;
   252 
   252 
   253 operator - (const z1, z2: hwFloat) z : hwFloat;
   253 operator - (const z1, z2: hwFloat) z : hwFloat; inline;
   254 begin
   254 begin
   255 if z1.isNegative = z2.isNegative then
   255 if z1.isNegative = z2.isNegative then
   256     if z1.QWordValue > z2.QWordValue then
   256     if z1.QWordValue > z2.QWordValue then
   257         begin
   257         begin
   258         z.isNegative:= z1.isNegative;
   258         z.isNegative:= z1.isNegative;
   271 end;
   271 end;
   272 
   272 
   273 function isZero(const z: hwFloat): boolean; inline; 
   273 function isZero(const z: hwFloat): boolean; inline; 
   274 begin
   274 begin
   275 isZero := z.QWordValue = 0;
   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
   276 end;
   298 end;
   277 {$ENDIF}
   299 {$ENDIF}
   278 {$IFDEF WEB}
   300 {$IFDEF WEB}
   279 (*
   301 (*
   280     Mostly to be kind to JS as of 2012-08-27 where there is no int64/uint64.  This may change though.
   302     Mostly to be kind to JS as of 2012-08-27 where there is no int64/uint64.  This may change though.
   287 operator <> (const z1, z2: hwFloat) z : boolean; inline;
   309 operator <> (const z1, z2: hwFloat) z : boolean; inline;
   288 begin
   310 begin
   289     z:= (z1.isNegative <> z2.isNegative) or (z1.Frac <> z2.Frac) or (z1.Round <> z2.Round);
   311     z:= (z1.isNegative <> z2.isNegative) or (z1.Frac <> z2.Frac) or (z1.Round <> z2.Round);
   290 end;
   312 end;
   291 
   313 
   292 operator + (const z1, z2: hwFloat) z : hwFloat;
   314 operator + (const z1, z2: hwFloat) z : hwFloat; inline;
   293 begin
   315 begin
   294 if z1.isNegative = z2.isNegative then
   316 if z1.isNegative = z2.isNegative then
   295     begin
   317     begin
   296 //  z.QWordValue:= z1.QWordValue + z2.QWordValue
       
   297     z:= z1;
   318     z:= z1;
   298     z.Frac:= z.Frac + z2.Frac;
   319     z.Frac:= z.Frac + z2.Frac;
   299     z.Round:= z.Round + z2.Round;
   320     z.Round:= z.Round + z2.Round;
   300     if z.Frac<z1.Frac then inc(z.Round)
   321     if z.Frac<z1.Frac then inc(z.Round)
   301     end
   322     end
   302 else
   323 else
   303 //  if z1.QWordValue > z2.QWordValue then
       
   304     if (z1.Round > z2.Round) or ((z1.Round = z2.Round) and (z1.Frac > z2.Frac)) then
   324     if (z1.Round > z2.Round) or ((z1.Round = z2.Round) and (z1.Frac > z2.Frac)) then
   305         begin
   325         begin
   306         z.isNegative:= z1.isNegative;
   326         z.isNegative:= z1.isNegative;
   307 //      z.QWordValue:= z1.QWordValue - z2.QWordValue
       
   308         z.Round:= z1.Round - z2.Round;
   327         z.Round:= z1.Round - z2.Round;
   309         z.Frac:= z1.Frac - z2.Frac;
   328         z.Frac:= z1.Frac - z2.Frac;
   310         if z2.Frac > z1.Frac then dec(z.Round)
   329         if z2.Frac > z1.Frac then dec(z.Round)
   311         end
   330         end
   312     else
   331     else
   313         begin
   332         begin
   314         z.isNegative:= z2.isNegative;
   333         z.isNegative:= z2.isNegative;
   315 //      z.QWordValue:= z2.QWordValue - z1.QWordValue
       
   316         z.Round:= z2.Round - z1.Round;
   334         z.Round:= z2.Round - z1.Round;
   317         z.Frac:= z2.Frac-z1.Frac;
   335         z.Frac:= z2.Frac-z1.Frac;
   318         if z2.Frac < z1.Frac then dec(z.Round)
   336         if z2.Frac < z1.Frac then dec(z.Round)
   319         end
   337         end
   320 end;
   338 end;
   321 
   339 
   322 operator - (const z1, z2: hwFloat) z : hwFloat;
   340 operator - (const z1, z2: hwFloat) z : hwFloat; inline;
   323 begin
   341 begin
   324 if z1.isNegative = z2.isNegative then
   342 if z1.isNegative = z2.isNegative then
   325 //  if z1.QWordValue > z2.QWordValue then
       
   326     if (z1.Round > z2.Round) or ((z1.Round = z2.Round) and (z1.Frac > z2.Frac)) then
   343     if (z1.Round > z2.Round) or ((z1.Round = z2.Round) and (z1.Frac > z2.Frac)) then
   327         begin
   344         begin
   328         z.isNegative:= z1.isNegative;
   345         z.isNegative:= z1.isNegative;
   329 //      z.QWordValue:= z1.QWordValue - z2.QWordValue
       
   330         z.Round:= z1.Round - z2.Round;
   346         z.Round:= z1.Round - z2.Round;
   331         z.Frac:= z1.Frac-z2.Frac;
   347         z.Frac:= z1.Frac-z2.Frac;
   332         if z2.Frac > z1.Frac then dec(z.Round)
   348         if z2.Frac > z1.Frac then dec(z.Round)
   333         end
   349         end
   334     else
   350     else
   335         begin
   351         begin
   336         z.isNegative:= not z2.isNegative;
   352         z.isNegative:= not z2.isNegative;
   337 //      z.QWordValue:= z2.QWordValue - z1.QWordValue
       
   338         z.Round:= z2.Round - z1.Round;
   353         z.Round:= z2.Round - z1.Round;
   339         z.Frac:= z2.Frac-z1.Frac;
   354         z.Frac:= z2.Frac-z1.Frac;
   340         if z2.Frac < z1.Frac then dec(z.Round)
   355         if z2.Frac < z1.Frac then dec(z.Round)
   341         end
   356         end
   342 else
   357 else
   343     begin
   358     begin
   344 //  z.QWordValue:= z1.QWordValue + z2.QWordValue
       
   345     z:= z1;
   359     z:= z1;
   346     z.Frac:= z.Frac + z2.Frac;
   360     z.Frac:= z.Frac + z2.Frac;
   347     z.Round:= z.Round + z2.Round;
   361     z.Round:= z.Round + z2.Round;
   348     if z.Frac<z1.Frac then inc(z.Round)
   362     if z.Frac<z1.Frac then inc(z.Round)
   349     end
   363     end
   350 end;
   364 end;
   351 
   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 
   352 function isZero(const z: hwFloat): boolean; inline; 
   390 function isZero(const z: hwFloat): boolean; inline; 
   353 begin
   391 begin
   354 isZero := z.Round = 0 and z.Frac = 0;
   392 isZero := z.Round = 0 and z.Frac = 0;
   355 end;
   393 end;
   356 {$ENDIF}
   394 {$ENDIF}
   357 
   395 
   358 operator - (const z1: hwFloat) z : hwFloat;
   396 operator - (const z1: hwFloat) z : hwFloat; inline;
   359 begin
   397 begin
   360 z:= z1;
   398 z:= z1;
   361 z.isNegative:= not z.isNegative
   399 z.isNegative:= not z.isNegative
   362 end;
   400 end;
   363 
   401 
   364 
   402 
   365 operator * (const z1, z2: hwFloat) z : hwFloat;
   403 operator * (const z1, z2: hwFloat) z : hwFloat; inline;
   366 begin
   404 begin
   367 z.isNegative:= z1.isNegative xor z2.isNegative;
   405 z.isNegative:= z1.isNegative xor z2.isNegative;
   368 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);
   369 z.Round:= z.Round + QWord(z1.Round) * z2.Round;
   407 z.Round:= z.Round + QWord(z1.Round) * z2.Round;
   370 end;
   408 end;
   371 
   409 
   372 operator * (const z1: hwFloat; const z2: LongInt) z : hwFloat;
   410 operator * (const z1: hwFloat; const z2: LongInt) z : hwFloat; inline;
   373 begin
   411 begin
   374 z.isNegative:= z1.isNegative xor (z2 < 0);
   412 z.isNegative:= z1.isNegative xor (z2 < 0);
   375 z.QWordValue:= z1.QWordValue * abs(z2)
   413 z.QWordValue:= z1.QWordValue * abs(z2)
   376 end;
   414 end;
   377 
   415 
   378 operator / (const z1: hwFloat; z2: hwFloat) z : hwFloat;
   416 operator / (const z1: hwFloat; z2: hwFloat) z : hwFloat; inline;
   379 var t: hwFloat;
   417 var t: hwFloat;
   380 begin
   418 begin
   381 z.isNegative:= z1.isNegative xor z2.isNegative;
   419 z.isNegative:= z1.isNegative xor z2.isNegative;
   382 z.Round:= z1.QWordValue div z2.QWordValue;
   420 z.Round:= z1.QWordValue div z2.QWordValue;
   383 t:= z1 - z2 * z.Round;
   421 t:= z1 - z2 * z.Round;
   395     else
   433     else
   396         z.Frac:= 0
   434         z.Frac:= 0
   397     end
   435     end
   398 end;
   436 end;
   399 
   437 
   400 operator / (const z1: hwFloat; const z2: LongInt) z : hwFloat;
   438 operator / (const z1: hwFloat; const z2: LongInt) z : hwFloat; inline;
   401 begin
   439 begin
   402 z.isNegative:= z1.isNegative xor (z2 < 0);
   440 z.isNegative:= z1.isNegative xor (z2 < 0);
   403 z.QWordValue:= z1.QWordValue div abs(z2)
   441 z.QWordValue:= z1.QWordValue div abs(z2)
   404 end;
       
   405 
       
   406 operator < (const z1, z2: hwFloat) b : boolean;
       
   407 begin
       
   408 if z1.isNegative xor z2.isNegative then
       
   409     b:= z1.isNegative
       
   410 else
       
   411     if z1.QWordValue = z2.QWordValue then
       
   412         b:= false
       
   413     else
       
   414         b:= (z1.QWordValue < z2.QWordValue) xor z1.isNegative
       
   415 end;
       
   416 
       
   417 operator > (const z1, z2: hwFloat) b : boolean;
       
   418 begin
       
   419 if z1.isNegative xor z2.isNegative then
       
   420     b:= z2.isNegative
       
   421 else
       
   422     if z1.QWordValue = z2.QWordValue then
       
   423         b:= false
       
   424     else
       
   425         b:= (z1.QWordValue > z2.QWordValue) xor z2.isNegative
       
   426 end;
   442 end;
   427 
   443 
   428 function cstr(const z: hwFloat): shortstring;
   444 function cstr(const z: hwFloat): shortstring;
   429 var tmpstr: shortstring;
   445 var tmpstr: shortstring;
   430 begin
   446 begin
   451 begin
   467 begin
   452 hwAbs:= t;
   468 hwAbs:= t;
   453 hwAbs.isNegative:= false
   469 hwAbs.isNegative:= false
   454 end;
   470 end;
   455 
   471 
   456 function hwSqr(const t: hwFloat): hwFloat;
   472 function hwSqr(const t: hwFloat): hwFloat; inline;
   457 begin
   473 begin
   458 hwSqr.isNegative:= false;
   474 hwSqr.isNegative:= false;
   459 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);
   460 end;
   476 end;
   461 
   477