type
THalfFloat = type Word;
function FloatToHalf(Float: Single): THalfFloat;
const
HalfMin: Single = 5.96046448e-08; // Smallest positive half
HalfMinNorm: Single = 6.10351562e-05; // Smallest positive normalized half
HalfMax: Single = 65504.0; // Largest positive half
// Smallest positive e for which half (1.0 + e) != half (1.0)
HalfEpsilon: Single = 0.00097656;
HalfNaN: THalfFloat = 65535;
HalfPosInf: THalfFloat = 31744;
HalfNegInf: THalfFloat = 64512;
var
Src: LongWord;
Sign, Exp, Mantissa: LongInt;
begin
Src := PLongWord(@Float)^;
// Extract sign, exponent, and mantissa from Single number
Sign := Src shr 31;
Exp := LongInt((Src and $7F800000) shr 23) - 127 + 15;
Mantissa := Src and $007FFFFF;
if (Exp > 0) and (Exp < 30) then
begin
// Simple case - round the significand and combine it with the sign and exponent
Result := (Sign shl 15) or (Exp shl 10) or ((Mantissa + $00001000) shr 13);
end
else if Src = 0 then
begin
// Input float is zero - return zero
Result := 0;
end
else
begin
// Difficult case - lengthy conversion
if Exp <= 0 then
begin
if Exp < -10 then
begin
// Input float's value is less than HalfMin, return zero
Result := 0;
end
else
begin
// Float is a normalized Single whose magnitude is less than HalfNormMin.
// We convert it to denormalized half.
Mantissa := (Mantissa or $00800000) shr (1 - Exp);
// Round to nearest
if (Mantissa and $00001000) > 0 then
Mantissa := Mantissa + $00002000;
// Assemble Sign and Mantissa (Exp is zero to get denormalized number)
Result := (Sign shl 15) or (Mantissa shr 13);
end;
end
else if Exp = 255 - 127 + 15 then
begin
if Mantissa = 0 then
begin
// Input float is infinity, create infinity half with original sign
Result := (Sign shl 15) or $7C00;
end
else
begin
// Input float is NaN, create half NaN with original sign and mantissa
Result := (Sign shl 15) or $7C00 or (Mantissa shr 13);
end;
end
else
begin
// Exp is > 0 so input float is normalized Single
// Round to nearest
if (Mantissa and $00001000) > 0 then
begin
Mantissa := Mantissa + $00002000;
if (Mantissa and $00800000) > 0 then
begin
Mantissa := 0;
Exp := Exp + 1;
end;
end;
if Exp > 30 then
begin
// Exponent overflow - return infinity half
Result := (Sign shl 15) or $7C00;
end
else
// Assemble normalized half
Result := (Sign shl 15) or (Exp shl 10) or (Mantissa shr 13);
end;
end;
end;
Page created in 0.014 seconds with 19 queries.