DataMuseum.dk

Presents historical artifacts from the history of:

Rational R1000/400

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about Rational R1000/400

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download

⟦a660ec777⟧ TextFile

    Length: 12524 (0x30ec)
    Types: TextFile
    Notes: R1k Text-file segment

Derivation

└─⟦8527c1e9b⟧ Bits:30000544 8mm tape, Rational 1000, Arrival backup of disks in PAM's R1000
    └─ ⟦5a81ac88f⟧ »Space Info Vol 1« 
        └─⟦9e8cb5d2a⟧ 
            └─⟦this⟧ 

TextFile

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;