DataMuseum.dk

Presents historical artifacts from the history of:

Rational R1000/400 Tapes

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 Tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download
Index: ┃ B T

⟦cbdf50f4c⟧ TextFile

    Length: 10534 (0x2926)
    Types: TextFile
    Names: »B«

Derivation

└─⟦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⟧ 

TextFile

package body Interchange_Float is

    use Interchange_Defs;

    Radix : constant := 2 ** 8;

    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;  
    subtype Long_Fraction_Type is Long_Integer range 0 .. (2 ** 52) - 1;

    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.
        -- The answer is found by binary search.

        Answer : Long_Exponent_Type;  
        Temp : Long_Integer;

        procedure Binary_Search is  
            Step : Long_Exponent_Type;  
        begin  
            Step := abs (Answer) / 2;

            while Step /= 0 loop  
                if (Answer < Long_Exponent_Type'Last) and then  
                   Data >= (2.0 ** Standard.Integer (Answer + Step)) then  
                    Answer := Answer + Step;  
                else
                    -- Take some care to avoid numeric_error:
                    if Answer < Long_Exponent_Type'Last then  
                        if Data < (2.0 ** Standard.Integer  
                                             (Answer - Step + 1)) then  
                            Answer := Answer - Step;  
                        end if;  
                    else  
                        if (Data / 2.0) < (2.0 ** Standard.Integer  
                                                     (Answer - Step)) then  
                            Answer := Answer - Step;  
                        end if;  
                    end if;
                    -- Both alternatives really do the same thing, but they're
                    -- set up so they don't produce intermediate results which
                    -- would be out of range.
                end if;

                Step := Step / 2;  
            end loop;  
        end Binary_Search;

    begin  
        pragma Assert (Data > 0.0);

        if Data >= 2.0 then  
            Answer := 1;

            while Data >= (2.0 ** Standard.Integer (Answer + 1)) loop  
                Answer := 2 * Answer;  
                exit when Answer >= Long_Exponent_Type'Last;
                -- Long_Exponent_Type'Last is a power of 2.
            end loop;

            Binary_Search;  
        elsif Data < 1.0 then  
            Answer := -1;

            while Data < (2.0 ** Standard.Integer (Answer)) loop  
                Temp := 2 * Long_Integer (Answer);

                if Temp < Long_Exponent_Type'First then  
                    exit;  
                else  
                    Answer := Long_Exponent_Type (Temp);  
                end if;
                -- Long_Exponent_Type'First is not a power of 2.
            end loop;

            Binary_Search;  
        else  
            Answer := 0;  
        end if;

        return Answer;  
    end Find_Exponent;

    function Convert (X : Interchange_Float.Float)  
                     return Interchange_Defs.Float is  
        Bytes : Interchange_Float.Float := X;  
        Data : Interchange_Defs.Float;  
        Negative : Boolean := False;  
        Exponent : Exponent_Type := 0;  
        Fraction : Fraction_Type := 0;  
        Biased_Exponent : Natural;  
    begin  
        declare  
            use Byte_Defs; -- byte operations
        begin  
            if "/=" ((Bytes (1) / 128), 0) then  
                Negative := True;  
                Bytes (1) := Bytes (1) mod 128;  
            end if;

            Biased_Exponent := (Natural (Bytes (1)) * 2)  
                                   + (Natural (Bytes (2)) / 128);  
            Bytes (2) := Bytes (2) mod 128;

            for I in 2 .. 4 loop  
                Fraction := (Fraction * Fraction_Type (Radix))  
                                + Fraction_Type (Bytes (I));  
            end loop;  
        end;

        Exponent := Exponent_Type (Biased_Exponent - 127);

        if Exponent = 128 then  
            Data := Interchange_Defs.Float'Last;  
        elsif Exponent > -127 then  
            Data :=  
               (1.0 + (Interchange_Defs.Float (Fraction) * (2.0 ** (-23))))  
                   * (2.0 ** Standard.Integer (Exponent));  
        elsif Fraction /= 0 then  
            Data := (Interchange_Defs.Float (Fraction) * (2.0 ** (-23)))  
                        * (2.0 ** (-126));  
        else  
            Data := 0.0;  
        end if;

        if Negative then  
            Data := -Data;  
        end if;

        return Data;  
    end Convert;

    function Convert (X : Interchange_Defs.Float)  
                     return Interchange_Float.Float is  
        Data : Interchange_Defs.Float := X;  
        Bytes : Interchange_Float.Float;  
        Negative : Boolean := False;  
        Exponent : Exponent_Type;  
        Fraction : Fraction_Type;  
        Biased_Exponent : Long_Natural;  
    begin  
        if Data < 0.0 then  
            Negative := True;  
            Data := -Data;  
        end if;

        if Data = 0.0 then  
            Exponent := Exponent_Type'First;  
            Fraction := 0;  
        elsif Data < (2.0 ** (-126)) then  
            Exponent := Exponent_Type'First;  
            Data := Data * (2.0 ** 126);  
            Fraction := Fraction_Type (Data * (2.0 ** 23));  
        elsif Data > (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  
                                              (Data)));  
            Data := Data * (2.0 ** Standard.Integer (-Exponent));  
            Fraction := Fraction_Type ((Data - 1.0) * (2.0 ** 23));  
        end if;

        Biased_Exponent := Exponent + 127;

        for I in reverse 2 .. 4 loop  
            Bytes (I) := Byte_Defs.Byte (Fraction mod Fraction_Type (Radix));  
            Fraction := Fraction / Fraction_Type (Radix);  
        end loop;

        if Biased_Exponent mod 2 /= 0 then  
            Bytes (2) := Byte_Defs."+" (Bytes (2), 128);  
        end if;

        Bytes (1) := Byte_Defs.Byte (Biased_Exponent / 2);

        if Negative then  
            Bytes (1) := Byte_Defs."+" (Bytes (1), 128);  
        end if;  
        return Bytes;  
    end Convert;

    function Convert (X : Interchange_Float.Long_Float)  
                     return Interchange_Defs.Long_Float is  
        Data : Interchange_Defs.Long_Float;  
        Bytes : Interchange_Float.Long_Float := X;  
        Negative : Boolean := False;  
        Exponent : Long_Exponent_Type := 0;  
        Fraction : Long_Fraction_Type := 0;  
        Biased_Exponent : Natural;  
    begin  
        declare  
            use Byte_Defs; -- byte operations
        begin
            -- get sign bit:
            if "/=" ((Bytes (1) / 128), 0) then  
                Negative := True;  
                Bytes (1) := Bytes (1) - 128;  
            end if;

            -- get biased exponent:
            Biased_Exponent := (Natural (Bytes (1)) * 16)  
                                   + (Natural (Bytes (2)) / 16);

            -- get fraction:
            Fraction := Long_Fraction_Type (Bytes (2)) mod 16;

            for I in 3 .. 8 loop  
                Fraction := (Fraction * Long_Fraction_Type (Radix))  
                                + Long_Fraction_Type (Bytes (I));  
            end loop;  
        end;

        Exponent := Long_Exponent_Type (Biased_Exponent - 1023);

        if Exponent = 1024 then  
            Data := Interchange_Defs.Long_Float'Last;  
        elsif Exponent > -1023 then  
            Data := (1.0 + (Interchange_Defs.Long_Float (Fraction) *  
                            (2.0 ** (-52))))  
                     * (2.0 ** Standard.Integer (Exponent));  
        elsif Fraction /= 0 then  
            Data := (Interchange_Defs.Long_Float (Fraction) * (2.0 ** (-52)))  
                        * (2.0 ** (-1022));  
        else  
            Data := 0.0;  
        end if;

        if Negative then  
            Data := -Data;  
        end if;

        return Data;  
    end Convert;

    function Convert (X : Interchange_Defs.Long_Float)  
                     return Interchange_Float.Long_Float is  
        Data : Interchange_Defs.Long_Float := X;  
        Bytes : Interchange_Float.Long_Float;  
        Negative : Boolean := False;  
        Exponent : Long_Exponent_Type;  
        Fraction : Long_Fraction_Type;  
        Biased_Exponent : Long_Natural;  
    begin  
        if Data < 0.0 then  
            Negative := True;  
            Data := -Data;  
        end if;

        if Data = 0.0 then  
            Exponent := Long_Exponent_Type'First;  
            Fraction := 0;  
        elsif Data < (2.0 ** (-1022)) then  
            Exponent := Long_Exponent_Type'First;  
            Data := Data * (2.0 ** 1022);  
            Fraction := Long_Fraction_Type (Data * (2.0 ** 52));  
        elsif Data > (2.0 - (2.0 ** (-52))) * (2.0 ** 1023) then  
            Exponent := Long_Exponent_Type'Last;  
            Fraction := 0;  
        else  
            Exponent := Long_Exponent_Type (Find_Exponent (Data));  
            Data := Data * (2.0 ** Standard.Integer (-Exponent));  
            Fraction := Long_Fraction_Type  
                           ((Data - 1.0) * (2.0 ** 52));  
        end if;

        Biased_Exponent := Exponent + 1023;

        -- put fraction:
        for I in reverse 2 .. 8 loop  
            Bytes (I) := Byte_Defs.Byte  
                            (Fraction mod Long_Fraction_Type (Radix));  
            Fraction := Fraction / Long_Fraction_Type (Radix);  
        end loop;

        -- put biased exponent:
        Bytes (2) := Byte_Defs."+"  
                        (Bytes (2), Byte_Defs.Byte  
                                       (16 * (Biased_Exponent mod 16)));  
        Bytes (1) := Byte_Defs.Byte (Biased_Exponent / 16);

        -- put sign bit:
        if Negative then  
            Bytes (1) := Byte_Defs."+" (Bytes (1), 128);  
        end if;

        return Bytes;  
    end Convert;

end Interchange_Float;