|
|
DataMuseum.dkPresents historical artifacts from the history of: Rational R1000/400 Tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Rational R1000/400 Tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: I T
Length: 12525 (0x30ed)
Types: TextFile
Names: »INTERCHANGE_FLOAT_B«
└─⟦5f3412b64⟧ Bits:30000745 8mm tape, Rational 1000, ENVIRONMENT 12_6_5 TOOLS
└─⟦91c658230⟧ »DATA«
└─⟦458657fb6⟧
└─⟦a5bbbb819⟧
└─⟦this⟧
└─⟦d10a02448⟧ Bits:30000409 8mm tape, Rational 1000, ENVIRONMENT, D_12_7_3
└─⟦fc9b38f02⟧ »DATA«
└─⟦9b46a407a⟧
└─⟦eec0a994f⟧
└─⟦this⟧
with System;
with Unchecked_Conversion;
package body Interchange_Float is
-- This implementation is specific to VAX/VMS.
use Byte_Defs;
use Interchange_Defs;
Radix : constant := 256;
subtype Long_Integer is Interchange_Defs.Longest_Integer;
subtype Long_Natural is Long_Integer range 0..Long_Integer'Last;
subtype Exponent_Type is Long_Integer range - 127..128;
subtype Fraction_Type is Long_Integer range 0..(2 ** 23) - 1;
subtype Long_Exponent_Type is Long_Integer range - 1023..1024;
-- The following is Vax-specific.
-- Turns out that Vax Ada runtime does not have an integer
-- long enough to contain the fractional part of a long float.
subtype Long_Fraction_Type is Byte_Defs.Byte_String (2..8);
Zero : constant Long_Fraction_Type := (others => 0);
function "=" (X, Y : Long_Fraction_Type) return Boolean
renames Byte_Defs."=";
type Long_Float_Bits is
record
Word_0 : System.Unsigned_Word;
Word_1 : System.Unsigned_Word;
Word_2 : System.Unsigned_Word;
Word_3 : System.Unsigned_Word;
Word_4 : System.Unsigned_Word;
Word_5 : System.Unsigned_Word;
Word_6 : System.Unsigned_Word;
Word_7 : System.Unsigned_Word;
end record;
function Force is new Unchecked_Conversion
(Source => Interchange_Defs.Long_Float,
Target => Long_Float_Bits);
function Force is new Unchecked_Conversion
(Source => Long_Float_Bits,
Target => Interchange_Defs.Long_Float);
function To_Fraction (X : Interchange_Defs.Long_Float) return Long_Fraction_Type is
-- Extract the most significant 52 bits of X.fraction.
-- Return them in the fraction bits of an IEEE float.
Answer : Long_Fraction_Type;
X_Copy : Long_Float_Bits;
function "+" (X, Y : System.Unsigned_Word)
return System.Unsigned_Word renames System."+";
function "/" (X, Y : System.Unsigned_Word)
return System.Unsigned_Word renames System."/";
function "*" (X, Y : System.Unsigned_Word)
return System.Unsigned_Word renames System."*";
function "mod" (X, Y : System.Unsigned_Word)
return System.Unsigned_Word renames System."mod";
begin
X_Copy := Force (X);
Answer (2) := Byte_Defs.Byte (X_Copy.Word_1 / 4096);
Answer (3) := Byte_Defs.Byte ((X_Copy.Word_1 / 16) mod Radix);
Answer (4) := Byte_Defs.Byte (((X_Copy.Word_1 mod 16) * 16) +
(X_Copy.Word_2 / 4096));
Answer (5) := Byte_Defs.Byte ((X_Copy.Word_2 / 16) mod Radix);
Answer (6) := Byte_Defs.Byte (((X_Copy.Word_2 mod 16) * 16) +
(X_Copy.Word_3 / 4096));
Answer (7) := Byte_Defs.Byte ((X_Copy.Word_3 / 16) mod Radix);
Answer (8) := Byte_Defs.Byte (((X_Copy.Word_3 mod 16) * 16) +
(X_Copy.Word_4 / 4096));
return Answer;
end To_Fraction;
function To_Float (X : Long_Fraction_Type) return Interchange_Defs.Long_Float is
-- Store the fraction part of an IEEE float
-- into the fraction bits of a Long_Float.
Answer : Long_Float_Bits;
-- We have to do arithmetic in unsigned_words,
-- because byte arithmetic does sign-extension.
T1, T2, T3 : System.Unsigned_Word;
function "+" (X, Y : System.Unsigned_Word)
return System.Unsigned_Word renames System."+";
function "/" (X, Y : System.Unsigned_Word)
return System.Unsigned_Word renames System."/";
function "*" (X, Y : System.Unsigned_Word)
return System.Unsigned_Word renames System."*";
function "mod" (X, Y : System.Unsigned_Word)
return System.Unsigned_Word renames System."mod";
begin
Answer.Word_0 := System.Unsigned_Word ((2 ** 14) + 1); -- exponent
T1 := System.Unsigned_Word (X (2));
T2 := System.Unsigned_Word (X (3));
T3 := System.Unsigned_Word (X (4));
Answer.Word_1 := ((T1 mod 16) * 4096) + (T2 * 16) + (T3 / 16);
T1 := T3;
T2 := System.Unsigned_Word (X (5));
T3 := System.Unsigned_Word (X (6));
Answer.Word_2 := ((T1 mod 16) * 4096) + (T2 * 16) + (T3 / 16);
T1 := T3;
T2 := System.Unsigned_Word (X (7));
T3 := System.Unsigned_Word (X (8));
Answer.Word_3 := ((T1 mod 16) * 4096) + (T2 * 16) + (T3 / 16);
T1 := T3;
Answer.Word_4 := ((T1 mod 16) * 4096);
Answer.Word_5 := 0;
Answer.Word_6 := 0;
Answer.Word_7 := 0;
return Force (Answer);
end To_Float;
function Find_Exponent
(Data : Interchange_Defs.Long_Float) return Long_Exponent_Type is
-- Return the (unbiased) exponent part of an IEEE float.
-- The DATA must be > 0.0.
-- The exponent must be > exponent'first.
Temp : Long_Float_Bits;
Answer : Long_Exponent_Type;
function "-" (X, Y : Long_Integer)
return Long_Integer renames Interchange_Defs."-";
function "**" (X : Interchange_Defs.Long_Float;
Y : Long_Integer)
return Interchange_Defs.Long_Float is
begin
return Interchange_Defs."**" (X, Standard.Integer (Y));
end "**";
pragma Inline ("**");
begin
Temp := Force (Data);
Answer := Long_Integer (Temp.Word_0) - 16_384;
if Data < (2.0 ** Answer) then
Answer := Answer - 1;
if Data < (2.0 ** Answer) then
Answer := Answer - 1;
end if;
end if;
return Answer;
end Find_Exponent;
function Convert (X : Interchange_Float.Float) return Interchange_Defs.Float is
X_Copy : Interchange_Float.Float := X;
Negative : Boolean := False;
Exponent : Exponent_Type := 0;
Fraction : Fraction_Type := 0;
Biased_Exponent : Natural;
Answer : Interchange_Defs.Float;
begin
if "/=" ((X_Copy (1) / 128), 0) then
Negative := True;
X_Copy (1) := X_Copy (1) mod 128;
end if;
Biased_Exponent := (Natural (X_Copy (1)) * 2)
+ (Natural (X_Copy (2)) / 128);
X_Copy (2) := X_Copy (2) mod 128;
for I in 2..4 loop
Fraction := (Fraction * Fraction_Type (Radix))
+ Fraction_Type (X_Copy (I));
end loop;
Exponent := Exponent_Type (Biased_Exponent - 127);
if Exponent = 128 then
Answer := Interchange_Defs.Float'Last;
elsif Exponent > - 127 then
Answer := (1.0 + (Interchange_Defs.Float (Fraction) *
(2.0 ** (- 23))))
* (2.0 ** Standard.Integer (Exponent));
elsif Fraction /= 0 then
Answer := (Interchange_Defs.Float (Fraction) * (2.0 ** (- 23)))
* (2.0 ** (- 126));
else
Answer := 0.0;
end if;
if Negative then
Answer := - Answer;
end if;
return Answer;
end Convert;
function Convert (X : Interchange_Defs.Float) return Interchange_Float.Float is
X_Copy : Interchange_Defs.Float := X;
Negative : Boolean := False;
Exponent : Exponent_Type;
Fraction : Fraction_Type;
Biased_Exponent : Long_Natural;
Answer : Interchange_Float.Float;
begin
if X_Copy < 0.0 then
Negative := True;
X_Copy := - X_Copy;
end if;
if X_Copy = 0.0 then
Exponent := Exponent_Type'First;
Fraction := 0;
elsif X_Copy < (2.0 ** (- 126)) then
Exponent := Exponent_Type'First;
X_Copy := X_Copy * (2.0 ** 126);
Fraction := Fraction_Type (X_Copy * (2.0 ** 23));
elsif X_Copy > (2.0 - (2.0 ** (- 23))) * (2.0 ** 127) then
Exponent := Exponent_Type'Last;
Fraction := 0;
else
Exponent := Exponent_Type (Find_Exponent
(Interchange_Defs.Long_Float (X_Copy)));
X_Copy := X_Copy * (2.0 ** Standard.Integer (- Exponent));
Fraction := Fraction_Type ((X_Copy - 1.0) * (2.0 ** 23));
end if;
Biased_Exponent := Exponent + 127;
for I in reverse 2..4 loop
Answer (I) := Byte (Fraction mod Fraction_Type (Radix));
Fraction := Fraction / Fraction_Type (Radix);
end loop;
if Biased_Exponent mod 2 /= 0 then
Answer (2) := Byte_Defs."+" (Answer (2), 128);
end if;
Answer (1) := Byte (Biased_Exponent / 2);
if Negative then
Answer (1) := Byte_Defs."+" (Answer (1), 128);
end if;
return Answer;
end Convert;
function Convert (X : Interchange_Float.Long_Float) return Interchange_Defs.Long_Float is
X_Copy : Interchange_Float.Long_Float := X;
Negative : Boolean := False;
Exponent : Long_Exponent_Type := 0;
Fraction : Long_Fraction_Type := Zero;
Biased_Exponent : Natural;
Answer : Interchange_Defs.Long_Float;
begin
-- get sign bit:
if "/=" ((X_Copy (1) / 128), 0) then
Negative := True;
X_Copy (1) := X_Copy (1) - 128;
end if;
-- get biased exponent:
Biased_Exponent := (Natural (X_Copy (1)) * 16)
+ (Natural (X_Copy (2)) / 16);
-- get fraction:
Fraction (2) := X_Copy (2) mod 16;
Fraction (3..8) := Byte_Defs.Byte_String (X_Copy (3..8));
Exponent := Long_Exponent_Type (Biased_Exponent - 1023);
if Exponent = 1024 then
Answer := Interchange_Defs.Long_Float'Last;
elsif Exponent > - 1023 then
Answer := To_Float (Fraction) *
(2.0 ** Standard.Integer (Exponent));
elsif "/=" (Fraction, Zero) then
Answer := (To_Float (Fraction) - 1.0) *
(2.0 ** (- 1022));
else
Answer := 0.0;
end if;
if Negative then
Answer := - Answer;
end if;
return Answer;
end Convert;
function Convert (X : Interchange_Defs.Long_Float) return Interchange_Float.Long_Float is
X_Copy : Interchange_Defs.Long_Float := X;
Negative : Boolean := False;
Exponent : Long_Exponent_Type;
Fraction : Long_Fraction_Type;
Biased_Exponent : Long_Natural;
Answer :
Byte_Defs.Byte_String (Interchange_Float.Long_Float'Range);
begin
if X_Copy < 0.0 then
Negative := True;
X_Copy := - X_Copy;
end if;
if X_Copy = 0.0 then
Exponent := Long_Exponent_Type'First;
Fraction := Zero;
elsif X_Copy > (2.0 - (2.0 ** (- 52))) * (2.0 ** 1023) then
Exponent := Long_Exponent_Type'Last;
Fraction := Zero;
elsif X_Copy < (2.0 ** (- 1022)) then
Exponent := Long_Exponent_Type'First;
X_Copy := X_Copy * (2.0 ** 1022);
Fraction := To_Fraction (X_Copy + 1.0);
else
Exponent := Long_Exponent_Type (Find_Exponent (X_Copy));
X_Copy := X_Copy * (2.0 ** Standard.Integer (- Exponent));
Fraction := To_Fraction (X_Copy);
end if;
Biased_Exponent := Exponent + 1023;
-- put fraction:
Answer (2..8) := Fraction;
-- put biased exponent:
Answer (2) := Byte_Defs."+"
(Answer (2), Byte_Defs.Byte
((Biased_Exponent mod 16) *
16));
Answer (1) := Byte_Defs.Byte (Biased_Exponent / 16);
-- put sign bit:
if Negative then
Answer (1) := Byte_Defs."+" (Answer (1), 128);
end if;
return Interchange_Float.Long_Float (Answer);
end Convert;
end Interchange_Float;