148 _0_96: hwFloat = (isNegative: false; QWordValue: 4123168604); |
144 _0_96: hwFloat = (isNegative: false; QWordValue: 4123168604); |
149 _0_995: hwFloat = (isNegative: false; QWordValue: 4273492459); |
145 _0_995: hwFloat = (isNegative: false; QWordValue: 4273492459); |
150 _0_999: hwFloat = (isNegative: false; QWordValue: 4290672328); |
146 _0_999: hwFloat = (isNegative: false; QWordValue: 4290672328); |
151 _0: hwFloat = (isNegative: false; QWordValue: 0); |
147 _0: hwFloat = (isNegative: false; QWordValue: 0); |
152 _1: hwFloat = (isNegative: false; QWordValue: 4294967296); |
148 _1: hwFloat = (isNegative: false; QWordValue: 4294967296); |
153 _1_2: hwFloat = (isNegative: false; QWordValue: 1288490189*4); |
149 _1_2: hwFloat = (isNegative: false; QWordValue: 4294967296 * 6 div 5 + 1); |
154 _1_5: hwFloat = (isNegative: false; QWordValue: 4294967296 * 3 div 2); |
150 _1_5: hwFloat = (isNegative: false; QWordValue: 4294967296 * 3 div 2); |
155 _1_6: hwFloat = (isNegative: false; QWordValue: 4294967296 * 8 div 5); |
151 _1_6: hwFloat = (isNegative: false; QWordValue: 4294967296 * 8 div 5); |
156 _1_9: hwFloat = (isNegative: false; QWordValue: 8160437862); |
152 _1_9: hwFloat = (isNegative: false; QWordValue: 8160437862); |
157 _2: hwFloat = (isNegative: false; QWordValue: 4294967296 * 2); |
153 _2: hwFloat = (isNegative: false; QWordValue: 4294967296 * 2); |
158 _2_4: hwFloat = (isNegative: false; QWordValue: 4294967296 * 12 div 5); |
154 _2_4: hwFloat = (isNegative: false; QWordValue: 4294967296 * 12 div 5); |
159 _3: hwFloat = (isNegative: false; QWordValue: 4294967296 * 3); |
155 _3: hwFloat = (isNegative: false; QWordValue: 4294967296 * 3); |
160 _3_2: hwFloat = (isNegative: false; QWordValue: 3435973837*4); |
156 _3_2: hwFloat = (isNegative: false; QWordValue: 4294967296 * 16 div 5); |
161 _PI: hwFloat = (isNegative: false; QWordValue: 13493037704); |
157 _PI: hwFloat = (isNegative: false; QWordValue: 13493037704); |
162 _4: hwFloat = (isNegative: false; QWordValue: 4294967296 * 4); |
158 _4: hwFloat = (isNegative: false; QWordValue: 4294967296 * 4); |
163 _4_5: hwFloat = (isNegative: false; QWordValue: 4294967296 * 9 div 2); |
159 _4_5: hwFloat = (isNegative: false; QWordValue: 4294967296 * 9 div 2); |
164 _5: hwFloat = (isNegative: false; QWordValue: 4294967296 * 5); |
160 _5: hwFloat = (isNegative: false; QWordValue: 4294967296 * 5); |
165 _6: hwFloat = (isNegative: false; QWordValue: 4294967296 * 6); |
161 _6: hwFloat = (isNegative: false; QWordValue: 4294967296 * 6); |
166 _6_4: hwFloat = (isNegative: false; QWordValue: 3435973837 * 8); |
162 _6_4: hwFloat = (isNegative: false; QWordValue: 4294967296 * 32 div 5); |
167 _7: hwFloat = (isNegative: false; QWordValue: 4294967296 * 7); |
163 _7: hwFloat = (isNegative: false; QWordValue: 4294967296 * 7); |
168 _10: hwFloat = (isNegative: false; QWordValue: 4294967296 * 10); |
164 _10: hwFloat = (isNegative: false; QWordValue: 4294967296 * 10); |
169 _12: hwFloat = (isNegative: false; QWordValue: 4294967296 * 12); |
165 _12: hwFloat = (isNegative: false; QWordValue: 4294967296 * 12); |
170 _16: hwFloat = (isNegative: false; QWordValue: 4294967296 * 16); |
166 _16: hwFloat = (isNegative: false; QWordValue: 4294967296 * 16); |
171 _19: hwFloat = (isNegative: false; QWordValue: 4294967296 * 19); |
167 _19: hwFloat = (isNegative: false; QWordValue: 4294967296 * 19); |
292 b:= (z1.QWordValue > z2.QWordValue) <> z2.isNegative |
288 b:= (z1.QWordValue > z2.QWordValue) <> z2.isNegative |
293 end; |
289 end; |
294 |
290 |
295 operator - (const z1: hwFloat) z : hwFloat; inline; |
291 operator - (const z1: hwFloat) z : hwFloat; inline; |
296 begin |
292 begin |
297 z:= z1; |
293 z:= z1; |
298 z.isNegative:= not z.isNegative |
294 z.isNegative:= not z.isNegative |
299 end; |
295 end; |
300 |
296 |
301 |
297 |
302 operator * (const z1, z2: hwFloat) z : hwFloat; inline; |
298 operator * (const z1, z2: hwFloat) z : hwFloat; inline; |
303 begin |
299 begin |
304 z.isNegative:= z1.isNegative xor z2.isNegative; |
300 z.isNegative:= z1.isNegative xor z2.isNegative; |
305 z.QWordValue:= QWord(z1.Round) * z2.Frac + QWord(z1.Frac) * z2.Round + ((QWord(z1.Frac) * z2.Frac) shr 32); |
301 z.QWordValue:= QWord(z1.Round) * z2.Frac + QWord(z1.Frac) * z2.Round + ((QWord(z1.Frac) * z2.Frac) shr 32); |
306 z.Round:= z.Round + QWord(z1.Round) * z2.Round; |
302 z.Round:= z.Round + QWord(z1.Round) * z2.Round; |
307 end; |
303 end; |
308 |
304 |
309 operator * (const z1: hwFloat; const z2: LongInt) z : hwFloat; inline; |
305 operator * (const z1: hwFloat; const z2: LongInt) z : hwFloat; inline; |
310 begin |
306 begin |
311 z.isNegative:= z1.isNegative xor (z2 < 0); |
307 z.isNegative:= z1.isNegative xor (z2 < 0); |
312 z.QWordValue:= z1.QWordValue * abs(z2) |
308 z.QWordValue:= z1.QWordValue * abs(z2) |
313 end; |
309 end; |
314 |
310 |
315 operator / (const z1: hwFloat; z2: hwFloat) z : hwFloat; inline; |
311 operator / (const z1: hwFloat; z2: hwFloat) z : hwFloat; inline; |
316 var t: QWord; |
312 var t: QWord; |
317 begin |
313 begin |
318 z.isNegative:= z1.isNegative xor z2.isNegative; |
314 z.isNegative:= z1.isNegative xor z2.isNegative; |
319 z.Round:= z1.QWordValue div z2.QWordValue; |
315 z.Round:= z1.QWordValue div z2.QWordValue; |
320 t:= z1.QWordValue - z2.QWordValue * z.Round; |
316 t:= z1.QWordValue - z2.QWordValue * z.Round; |
321 z.Frac:= 0; |
317 z.Frac:= 0; |
322 |
318 |
323 if t <> 0 then |
319 if t <> 0 then |
324 begin |
320 begin |
325 while ((t and $FF00000000000000) = 0) and ((z2.QWordValue and $FF00000000000000) = 0) do |
321 while ((t and $FF00000000000000) = 0) and ((z2.QWordValue and $FF00000000000000) = 0) do |
326 begin |
322 begin |
327 t:= t shl 8; |
323 t:= t shl 8; |
328 z2.QWordValue:= z2.QWordValue shl 8 |
324 z2.QWordValue:= z2.QWordValue shl 8 |
329 end; |
325 end; |
330 |
326 |
331 if z2.Round > 0 then |
327 if z2.Round > 0 then |
332 inc(z.QWordValue, t div z2.Round); |
328 inc(z.QWordValue, t div z2.Round); |
333 end |
329 end |
334 end; |
330 end; |
335 |
331 |
336 operator / (const z1: hwFloat; const z2: LongInt) z : hwFloat; inline; |
332 operator / (const z1: hwFloat; const z2: LongInt) z : hwFloat; inline; |
337 begin |
333 begin |
338 z.isNegative:= z1.isNegative xor (z2 < 0); |
334 z.isNegative:= z1.isNegative xor (z2 < 0); |
339 z.QWordValue:= z1.QWordValue div abs(z2) |
335 z.QWordValue:= z1.QWordValue div abs(z2) |
340 end; |
336 end; |
341 |
337 |
342 function cstr(const z: hwFloat): shortstring; |
338 function cstr(const z: hwFloat): shortstring; |
343 var tmpstr: shortstring; |
339 var tmpstr: shortstring; |
344 begin |
340 begin |
345 str(z.Round, cstr); |
341 str(z.Round, cstr); |
346 if z.Frac <> 0 then |
342 if z.Frac <> 0 then |
347 begin |
343 begin |
348 str(z.Frac / $100000000, tmpstr); |
344 str(z.Frac / $100000000, tmpstr); |
349 delete(tmpstr, 1, 2); |
345 delete(tmpstr, 1, 2); |
350 cstr:= cstr + '.' + copy(tmpstr, 1, 10) |
346 cstr:= cstr + '.' + copy(tmpstr, 1, 10) |
351 end; |
347 end; |
352 if z.isNegative then |
348 if z.isNegative then |
353 cstr:= '-' + cstr |
349 cstr:= '-' + cstr |
354 end; |
350 end; |
355 |
351 |
356 function hwRound(const t: hwFloat): LongInt; |
352 function hwRound(const t: hwFloat): LongInt; |
357 begin |
353 begin |
358 if t.isNegative then |
354 if t.isNegative then |
359 hwRound:= -(t.Round and $7FFFFFFF) |
355 hwRound:= -(t.Round and $7FFFFFFF) |
360 else |
356 else |
361 hwRound:= t.Round and $7FFFFFFF |
357 hwRound:= t.Round and $7FFFFFFF |
362 end; |
358 end; |
363 |
359 |
364 function hwAbs(const t: hwFloat): hwFloat; |
360 function hwAbs(const t: hwFloat): hwFloat; |
365 begin |
361 begin |
366 hwAbs:= t; |
362 hwAbs:= t; |
367 hwAbs.isNegative:= false |
363 hwAbs.isNegative:= false |
368 end; |
364 end; |
369 |
365 |
370 function hwSqr(const t: hwFloat): hwFloat; inline; |
366 function hwSqr(const t: hwFloat): hwFloat; inline; |
371 begin |
367 begin |
372 hwSqr.isNegative:= false; |
368 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); |
369 hwSqr.QWordValue:= ((QWord(t.Round) * t.Round) shl 32) + QWord(t.Round) * t.Frac * 2 + ((QWord(t.Frac) * t.Frac) shr 32); |
374 end; |
370 end; |
375 |
371 |
376 function hwPow(const t: hwFloat;p: LongWord): hwFloat; |
372 function hwPow(const t: hwFloat;p: LongWord): hwFloat; |
377 begin |
373 begin |
378 hwPow:= t; |
374 hwPow:= t; |
379 if p mod 2 = 0 then hwPow.isNegative:= false; |
375 if p mod 2 = 0 then hwPow.isNegative:= false; |
380 |
376 |
381 while p > 0 do |
377 while p > 0 do |
382 begin |
378 begin |
383 hwPow.QWordValue:= QWord(hwPow.Round) * t.Frac + QWord(hwPow.Frac) * t.Round + ((QWord(hwPow.Frac) * t.Frac) shr 32); |
379 hwPow.QWordValue:= QWord(hwPow.Round) * t.Frac + QWord(hwPow.Frac) * t.Round + ((QWord(hwPow.Frac) * t.Frac) shr 32); |
384 dec(p) |
380 dec(p) |
385 end |
381 end |
386 end; |
382 end; |
387 |
383 |
388 function hwSqrt1(const t: hwFloat): hwFloat; |
384 function hwSqrt1(const t: hwFloat): hwFloat; |
389 const pwr = 8; // even value, feel free to adjust |
385 const pwr = 8; // even value, feel free to adjust |
390 rThreshold = 1 shl (pwr + 32); |
386 rThreshold = 1 shl (pwr + 32); |
391 lThreshold = 1 shl (pwr div 2 + 32); |
387 lThreshold = 1 shl (pwr div 2 + 32); |
392 var l, r: QWord; |
388 var l, r: QWord; |
393 c: hwFloat; |
389 c: hwFloat; |
394 begin |
390 begin |
395 hwSqrt1.isNegative:= false; |
391 hwSqrt1.isNegative:= false; |
396 |
392 |
397 if t.Round = 0 then |
393 if t.Round = 0 then |
398 begin |
394 begin |
399 l:= t.QWordValue; |
395 l:= t.QWordValue; |
400 r:= $100000000 |
396 r:= $100000000 |
401 end |
397 end |
402 else |
398 else |
403 begin |
399 begin |
404 if t.QWordValue > $FFFFFFFFFFFF then // t.Round > 65535.9999 |
400 if t.QWordValue > $FFFFFFFFFFFF then // t.Round > 65535.9999 |
405 begin |
|
406 l:= $10000000000; // 256 |
|
407 r:= $FFFFFFFFFFFF; // 65535.9999 |
|
408 end else |
|
409 if t.QWordValue >= rThreshold then |
|
410 begin |
401 begin |
411 l:= lThreshold; |
402 l:= $10000000000; // 256 |
412 r:= $10000000000; // 256 |
403 r:= $FFFFFFFFFFFF; // 65535.9999 |
413 end else |
404 end |
414 begin |
405 else |
415 l:= $100000000; |
406 if t.QWordValue >= rThreshold then |
416 r:= lThreshold; |
407 begin |
417 end; |
408 l:= lThreshold; |
|
409 r:= $10000000000; // 256 |
|
410 end |
|
411 else |
|
412 begin |
|
413 l:= $100000000; |
|
414 r:= lThreshold; |
|
415 end; |
418 end; |
416 end; |
419 |
417 |
420 repeat |
418 repeat |
421 c.QWordValue:= (l + r) shr 1; |
419 c.QWordValue:= (l + r) shr 1; |
422 if hwSqr(c).QWordValue > t.QWordValue then |
420 if hwSqr(c).QWordValue > t.QWordValue then |
423 r:= c.QWordValue |
421 r:= c.QWordValue |
424 else |
422 else |
425 l:= c.QWordValue |
423 l:= c.QWordValue |
426 until r - l <= 1; |
424 until r - l <= 1; |
427 |
425 |
428 hwSqrt1.QWordValue:= l |
426 hwSqrt1.QWordValue:= l |
429 end; |
427 end; |
430 |
428 |
431 function hwSqrt(const x: hwFloat): hwFloat; |
429 function hwSqrt(const x: hwFloat): hwFloat; |
432 var r, t, s, q: QWord; |
430 var r, t, s, q: QWord; |
433 i: integer; |
431 i: integer; |
434 begin |
432 begin |
435 hwSqrt.isNegative:= false; |
433 hwSqrt.isNegative:= false; |
436 |
434 |
437 t:= $4000000000000000; |
435 t:= $4000000000000000; |
438 r:= 0; |
436 r:= 0; |
439 q:= x.QWordValue; |
437 q:= x.QWordValue; |
440 |
438 |
441 for i:= 0 to 31 do |
439 for i:= 0 to 31 do |
442 begin |
440 begin |
443 s:= r + t; |
441 s:= r + t; |
444 r:= r shr 1; |
442 r:= r shr 1; |
445 if s <= q then |
443 if s <= q then |
446 begin |
444 begin |
447 dec(q, s); |
445 dec(q, s); |
448 inc(r, t); |
446 inc(r, t); |
|
447 end; |
|
448 t:= t shr 2; |
449 end; |
449 end; |
450 t:= t shr 2; |
450 |
451 end; |
451 hwSqrt.QWordValue:= r shl 16 |
452 |
|
453 hwSqrt.QWordValue:= r shl 16 |
|
454 end; |
452 end; |
455 |
453 |
456 |
454 |
457 |
455 |
458 function Distance(const dx, dy: hwFloat): hwFloat; |
456 function Distance(const dx, dy: hwFloat): hwFloat; |
459 var r: QWord; |
457 var r: QWord; |
460 begin |
458 begin |
461 r:= dx.QWordValue or dy.QWordValue; |
459 r:= dx.QWordValue or dy.QWordValue; |
462 |
460 |
463 if r < $10000 then |
461 if r < $10000 then |
464 begin |
462 begin |
465 Distance.QWordValue:= r; |
463 Distance.QWordValue:= r; |
466 Distance.isNegative:= false |
464 Distance.isNegative:= false |
467 end else |
465 end |
468 Distance:= hwSqrt(hwSqr(dx) + hwSqr(dy)) |
466 else |
|
467 Distance:= hwSqrt(hwSqr(dx) + hwSqr(dy)) |
469 end; |
468 end; |
470 |
469 |
471 function DistanceI(const dx, dy: LongInt): hwFloat; |
470 function DistanceI(const dx, dy: LongInt): hwFloat; |
472 begin |
471 begin |
473 DistanceI:= hwSqrt(int2hwFloat(sqr(dx) + sqr(dy))) |
472 DistanceI:= hwSqrt(int2hwFloat(sqr(dx) + sqr(dy))) |
474 end; |
473 end; |
475 |
474 |
476 function SignAs(const num, signum: hwFloat): hwFloat; |
475 function SignAs(const num, signum: hwFloat): hwFloat; |
477 begin |
476 begin |
478 SignAs.QWordValue:= num.QWordValue; |
477 SignAs.QWordValue:= num.QWordValue; |
479 SignAs.isNegative:= signum.isNegative |
478 SignAs.isNegative:= signum.isNegative |
480 end; |
479 end; |
481 |
480 |
482 function hwSign(r: hwFloat): LongInt; |
481 function hwSign(r: hwFloat): LongInt; |
483 begin |
482 begin |
484 // yes, we have negative zero for a reason |
483 // yes, we have negative zero for a reason |