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

⟦402c81667⟧ TextFile

    Length: 23654 (0x5c66)
    Types: TextFile
    Names: »B«

Derivation

└─⟦afbc8121e⟧ Bits:30000532 8mm tape, Rational 1000, MC68020_OS2000 7_2_2
    └─ ⟦77aa8350c⟧ »DATA« 
        └─⟦f794ecd1d⟧ 
            └─⟦4c85d69e2⟧ 
                └─⟦this⟧ 

TextFile

--    The use of this system is subject to the software license terms and
--    conditions agreed upon between Rational and the Customer.
--
--                Copyright 1988 by Rational.
--
--                          RESTRICTED RIGHTS LEGEND
--
--    Use, duplication, or disclosure by the Government is subject to
--    restrictions as set forth in subdivision (b)(3)(ii) of the Rights in
--    Technical Data and Computer Software clause at 52.227-7013.
--
--
--                Rational
--                3320 Scott Boulevard
--                Santa Clara, California 95054-3197
--
--   PROPRIETARY AND CONFIDENTIAL INFORMATION OF RATIONAL;
--   USE OR COPYING WITHOUT EXPRESS WRITTEN AUTHORIZATION
--   IS STRICTLY PROHIBITED.  THIS MATERIAL IS PROTECTED AS
--   AN UNPUBLISHED WORK UNDER THE U.S. COPYRIGHT ACT OF
--   1976.  CREATED 1988.  ALL RIGHTS RESERVED.
--
--

with M68k_Floats;
with Primitive_Io;

package body M68k_Float_Conversions is

    package Flt renames M68k_Floats;

--    procedure Debug (S : String; Absorb_Output : Boolean := False)
--                  Absorb_Output : Boolean := Primitive_Io.Global_Absorb_Output)
--        renames Primitive_Io.Put_Line;

    function From_Decimal_Digit (D : Flt.Decimal_Digit) return Character is
    begin
        return Character'Val (Character'Pos ('0') + Natural (D));
    end From_Decimal_Digit;

    function Image (P : Flt.Packed_Float) return String is
        Result : String (1 .. 25);
    begin
        if P.Negative_Mantissa then
            Result (1) := '-';
        else
            Result (1) := '+';
        end if;
        Result (2) := From_Decimal_Digit (P.Integral);  
        Result (3) := '.';
        for I in 0 .. 15 loop
            Result (4 + I) := From_Decimal_Digit (P.Fraction (I));
        end loop;
        Result (20) := 'E';
        if P.Negative_Exponent then
            Result (21) := '-';
        else
            Result (21) := '+';
        end if;
        Result (22) := From_Decimal_Digit (P.Expspare);
        for I in 0 .. 2 loop
            Result (23 + I) := From_Decimal_Digit (P.Exponent (I));  
        end loop;
        return Result;
    end Image;

    function Based_Value (S : String) return Flt.Extended_Float is separate;

    function To_Decimal_Digit (C : Character) return Flt.Decimal_Digit is
    begin
        case C is
            when '0' .. '9' =>
                return Flt.Decimal_Digit
                          (Character'Pos (C) - Character'Pos ('0'));

            when others =>
                -- Debug ("TO_DECIMAL_DIGIT illegal character");
                raise Constraint_Error;
        end case;
    end To_Decimal_Digit;


    function Value (S : in String) return Flt.Extended_Float is
        Si   : Natural          := S'First;  -- index into literal
        Last : constant Natural := S'Last;

        Result          : Flt.Packed_Float;
        Extended_Result : Flt.Extended_Float;
        Fraction_Index  : Natural := 0;

        Found_Point : Boolean := False;
        Found_E     : Boolean := False;

        Integral_Exp      : Integer := 0;
        Exponent          : Integer := 0;
        Exponent_Negative : Boolean;
        Exponent_Overflow : Integer := 0;

        -- Si, Found_Point, Found_E, Integral_Exp used up-level
        function Find_Integral_Digit return Flt.Decimal_Digit is
            Char : Character;
        begin
            while Si <= Last loop
                Char := S (Si);
                Si   := Si + 1;

                case Char is
                    when '0' .. '9' =>
                        if Found_Point then
                            Integral_Exp := Integral_Exp - 1;
                        end if;
                        if Char /= '0' then
                            return To_Decimal_Digit (Char);
                        end if;

                    when '.' =>
                        Found_Point := True;

                    when 'E' | 'e' =>
                        if not Found_Point then
                            -- Debug ("VALUE found 'E' before '.'");
                            raise Constraint_Error;
                        end if;
                        Found_E := True;
                        exit;

                    when '_' =>
                        null;

                    when others =>
                        -- Should not happen for a valid literal
                        raise Constraint_Error;
                end case;
            end loop;

            -- Read complete mantissa xxx.yyy without finding a nonzero
            -- digit; either found E or ran out of characters.

            -- Debug ("VALUE mantissa is all zeros.");
            return 0;
        end Find_Integral_Digit;

        procedure Insert_Fraction (D : Flt.Decimal_Digit) is
        begin
            if Fraction_Index <= Result.Fraction'Last then
                Result.Fraction (Fraction_Index) := D;
            end if;
            Fraction_Index := Fraction_Index + 1;
        end Insert_Fraction;

        -- *** Kludge workaround for cg bug exiting from loop
        procedure Do_Remaining_Mantissa is
        begin
            Foo:
                while Si <= Last loop
                    --Simple_Io.Put ("Next is ");
                    --Simple_Io.Put (S (Si));
                    --Simple_Io.New_Line;
                    case S (Si) is
                        when '0' .. '9' =>
                            Insert_Fraction (To_Decimal_Digit (S (Si)));

                        when 'E' | 'e' =>
                            Found_E := True;
                            Si      := Si + 1;
                            --Simple_Io.Put
                            --   ("VALUE found 'E'; the next char is ");
                            --Simple_Io.Put (S (Si));
                            --Simple_Io.New_Line;
                            exit Foo;
                            goto Stupid; --*** workaround for code generator bug
                            -- return/exit;

                        when '_' =>
                            null;

                        when others =>
                            exit Foo;
                            goto Stupid; --*** workaround for code generator bug
                            -- return/exit;
                    end case;
                    Si := Si + 1;
                end loop Foo;
            <<Stupid>> null;
        end Do_Remaining_Mantissa;

    begin
        -- Debug ("VALUE (" & S & ')');

        -- Skip whitespace (blanks, tabs, line terminators, page terminators)
        begin
            --Debug ("VALUE skipping whitespace");
            loop
                declare
                    C : constant Character := S (Si);
                begin
                    exit when not (C = ' ' or C = Ascii.Ht or C = Ascii.Lf or
                                   C = Ascii.Ff or C = Ascii.Cr);
                    Si := Si + 1;
                end;
            end loop;

            -- Eventually, literal parser will give an indication of whether
            -- was based, so won't have to do this scan.
            for I in Si .. Last loop
                if S (I) = '#' or S (I) = ':' then
                    -- Must be a based literal.
                    return Based_Value (S (Si .. Last));
                end if;
            end loop;

        exception
            when Constraint_Error =>
                -- This should never happen:  We were supposed to have a
                -- valid literal which therefore should have non-whitespace!
                -- raise Data_Error;
                -- Debug ("VALUE Constraint_Error while skipping whitespace");
                raise Constraint_Error;
        end;

        -- Check for a sign for the entire literal
        if S (Si) = '+' then
            Result.Negative_Mantissa := False;
            Si                       := Si + 1;
            -- Debug ("Value found +");
        elsif S (Si) = '-' then
            Result.Negative_Mantissa := True;
            Si                       := Si + 1;
            -- Debug ("Value found -");
        else
            Result.Negative_Mantissa := False;
            -- Debug ("Value found no sign");
        end if;

        -- Now we are read to find the integral digit of the packed float;
        -- this may involve reading past the decimal point.

        -- Debug ("VALUE reading integer part");
        Result.Integral := Find_Integral_Digit;

        if not Found_Point then
            while S (Si) /= '.' loop
                if S (Si) /= '_' then
                    Insert_Fraction (To_Decimal_Digit (S (Si)));
                    Integral_Exp := Integral_Exp + 1;
                end if;
                Si := Si + 1;
            end loop;
            Si := Si + 1;  -- skip over '.'
        end if;

        -- Debug ("VALUE finished integer; int_exp = " &
        --        Integer'Image (Integral_Exp));

        if not Found_E then
            -- *** Kludge workaround for cg bug.
            Do_Remaining_Mantissa;
        end if;

        for I in Fraction_Index .. Result.Fraction'Last loop
            Result.Fraction (I) := 0;
        end loop;

        if Found_E then
            -- Debug ("VALUE processing exponent = " & S (Si .. Last));

            -- Check for a sign for the exponent
            if S (Si) = '+' then
                Exponent_Negative := False;
                Si                := Si + 1;
                -- Debug ("Value found +");
            elsif S (Si) = '-' then
                Exponent_Negative := True;
                Si                := Si + 1;
                -- Debug ("Value found -");
            else
                Exponent_Negative := False;
                -- Debug ("Value found no sign");
            end if;

            while Si <= Last loop
                if S (Si) in '0' .. '9' then
                    Exponent := Exponent * 10 + (Character'Pos (S (Si)) -
                                                 Character'Pos ('0'));
                elsif S (Si) /= '_' then
                    exit;
                end if;
                Si := Si + 1;
            end loop;

            if Exponent_Negative then
                Exponent := Integral_Exp - Exponent;
            else
                Exponent := Integral_Exp + Exponent;
            end if;
        else
            Exponent := Integral_Exp;
        end if;

        -- Debug ("VALUE exponent is " & Integer'Image (Exponent));

        if Exponent < -999 then
            Exponent_Overflow := Exponent + 999;
            Exponent          := -999;
        elsif Exponent > 999 then
            Exponent_Overflow := Exponent - 999;
            Exponent          := 999;
        end if;

        if Exponent < 0 then
            Result.Negative_Exponent := True;
            Exponent                 := -Exponent;
        else
            Result.Negative_Exponent := False;
        end if;

        for I in reverse 0 .. 2 loop
            Result.Exponent (I) := Flt.Decimal_Digit (Exponent mod 10);
            Exponent            := Exponent / 10;
        end loop;

        if Exponent_Overflow = 0 then
            Flt.Packed_To_Extended (Result, Extended_Result);
        else
            Flt.Packed_Exponentiate (Exponent_Overflow,
                                     Result, Extended_Result);
            Flt.Extended_To_Packed (Extended_Result, Result);
        end if;

        -- Debug ("Packed string is " & Image (Result));

        return Extended_Result;
    end Value;

    function Value (S : in String) return Float is
        P : Flt.Extended_Float := Value (S);
    begin
        return Flt.Extended_To_Single (P);
    end Value;

    function Value (S : in String) return Long_Float is
        P : Flt.Extended_Float := Value (S);
    begin
        return Flt.Extended_To_Double (P);
    end Value;

\f

    function Min (I, J : Integer) return Integer is
    begin
        if I < J then
            return I;
        else
            return J;
        end if;
    end Min;

    function Max (I, J : Integer) return Integer is
    begin
        if I < J then
            return J;
        else
            return I;
        end if;
    end Max;

    function Cond (Condition : Boolean; If_True : Integer; If_False : Integer)
                  return Integer is
    begin
        if Condition then
            return If_True;
        else
            return If_False;
        end if;
    end Cond;

    procedure Compute_Format_Params (Digits_Fore   :        Natural;
                                     Digits_Aft    :        Natural;
                                     Has_Exponent  :        Boolean;
                                     Log10         :        Integer;
                                     Digits_After  : in out Natural;
                                     Digits_Before : in out Natural;
                                     Zeros_Before  : in out Natural;
                                     K_Factor      : in out Natural) is
        Digits_Integer_Part : Integer;
    begin
        Digits_Before :=
           Cond (Has_Exponent, If_True => 1, If_False => Max (1, Log10 + 1));
        Digits_Integer_Part :=
           Cond (Has_Exponent, If_True => 1, If_False => Log10 + 1);
        Digits_After := Max (1, Digits_Aft);
        Zeros_Before :=
           Cond (Has_Exponent,
                 If_True  => 0,
                 If_False => Min (Max (0, -Log10 - 1), Digits_After));
        K_Factor := Max (1, Min (17, Digits_Integer_Part + Digits_After));

        -- Debug ("FORMAT_PARAMS: ");
        -- Debug ("    Digits_Before = " & Integer'Image (Digits_Before));
        -- Debug ("   Digits_Integer = " & Integer'Image (Digits_Integer_Part));
        -- Debug ("    Digits_After  = " & Integer'Image (Digits_After));
        -- Debug ("    Zeros_Before  = " & Integer'Image (Zeros_Before));
        -- Debug ("    K_Factor      = " & Integer'Image (K_Factor));
    end Compute_Format_Params;

    function Get_Log10 (P : Flt.Packed_Float) return Integer is
        Value : Integer := Integer (P.Expspare);
    begin
        -- Debug ("Get_Log10 packed float is " & Image (P));
        for I in 0 .. 2 loop
            Value := 10 * Value + Integer (P.Exponent (I));
        end loop;
        if P.Negative_Exponent then
            Value := -Value;
        end if;
        return Value;
    end Get_Log10;

    procedure Image (P : Flt.Packed_Float;
                     Digits_Fore, Digits_Aft, Digits_Exp : Natural;
                     Digits_Before, Digits_After, Zeros_Before : Natural;
                     Log10 : Integer;
                     Result_Str : out String;
                     Result_Last : out Natural) is

        Last    : Natural := Result_Str'First - 1;
        Next_In : Integer := -2;

        procedure Put_Char (C : Character) is
        begin
            Last              := Last + 1;
            Result_Str (Last) := C;
        end Put_Char;

        function Get_Char return Character is
            D : Flt.Decimal_Digit;
        begin
            Next_In := Next_In + 1;
            if Next_In < 0 then
                D := P.Integral;
                --    return From_Decimal_Digit (P.Integral);
            elsif Next_In <= 15 then
                D := P.Fraction (Next_In);
                --    return From_Decimal_Digit (P.Fraction (Next_In));
            else
                D := 0;
                --    return '0';
            end if;
            return From_Decimal_Digit (D);
        end Get_Char;


    begin
        -- Debug ("IMAGE packed string is " & Image (P));
        -- Debug ("IMAGE log 10 is " & Integer'Image (Log10));

        declare
            Space_Fore     : constant Natural :=
               Digits_Before +
                  Cond (P.Negative_Mantissa, If_True => 1, If_False => 0);
            Leading_Blanks : constant Natural :=
               Max (0, Digits_Fore - Space_Fore);
        begin
            -- Debug ("Leading blanks = " & Integer'Image (Leading_Blanks));
            for I in 1 .. Leading_Blanks loop
                Put_Char (' ');
            end loop;
        end;

        if P.Negative_Mantissa then
            Put_Char ('-');
        end if;

        if Digits_Exp = 0 and then Log10 < 0 then
            Put_Char ('0');
        else
            for I in 1 .. Digits_Before loop
                Put_Char (Get_Char);
            end loop;
        end if;

        Put_Char ('.');

        for I in 1 .. Zeros_Before loop
            Put_Char ('0');
        end loop;

        for I in Zeros_Before + 1 .. Digits_After loop
            Put_Char (Get_Char);
        end loop;

        if Digits_Exp > 0 then
            Put_Char ('E');

            if P.Negative_Exponent then
                Put_Char ('-');
            else
                Put_Char ('+');
            end if;

            declare
                Exp : constant String  := Integer'Image (Log10);
                Len : constant Natural := Exp'Length;
            begin
                for I in 1 .. Max (0, Digits_Exp - Len) loop
                    Put_Char ('0');
                end loop;

                for I in 2 .. Len loop
                    Put_Char (Exp (I));
                end loop;
            end;

        end if;

        Result_Last := Last;

    end Image;

    procedure Zero_Image (Result_Str  : out String;
                          Result_Last : out Natural;
                          Digits_Fore :     Natural;
                          Digits_Aft  :     Natural;
                          Digits_Exp  :     Natural) is

        Pad_Fore : constant Integer := Digits_Fore - 1;
        Pad_Aft  : constant Integer := Digits_Aft - 1;
        Pad_Exp  : constant Integer := Digits_Exp - 2;

        Last : Natural := Result_Str'First - 1;

        procedure Put_Char (C : Character) is
        begin
            Last              := Last + 1;
            Result_Str (Last) := C;
        end Put_Char;

    begin
        for I in 1 .. Pad_Fore loop
            Put_Char (' ');
        end loop;

        Put_Char ('0');
        Put_Char ('.');
        Put_Char ('0');

        for I in 1 .. Pad_Aft loop
            Put_Char ('0');
        end loop;

        if Digits_Exp > 0 then
            Put_Char ('E');
            Put_Char ('+');
            Put_Char ('0');
            for I in 1 .. Pad_Exp loop
                Put_Char ('0');
            end loop;
        end if;

        Result_Last := Last;
    end Zero_Image;

    procedure Image (F : in Float;  
                     Digits_Fore, Digits_Aft, Digits_Exp : in Natural;
                     Result_Str : out String;
                     Result_Last : out Natural) is
        P             : Flt.Packed_Float;
        Log10         : Integer;
        Digits_After  : Natural;
        Digits_Before : Natural;
        Zeros_Before  : Natural;
        K_Factor      : Natural;
    begin
        if F /= 0.0 then
            Flt.Single_To_Packed (F, P, 6);

            -- get estimate of log 10 and formatting params
            Log10 := Get_Log10 (P);
            Compute_Format_Params (Digits_Fore   => Digits_Fore,
                                   Digits_Aft    => Digits_Aft,
                                   Has_Exponent  => (Digits_Exp /= 0),
                                   Log10         => Log10,
                                   Digits_After  => Digits_After,
                                   Digits_Before => Digits_Before,
                                   Zeros_Before  => Zeros_Before,
                                   K_Factor      => K_Factor);
            Flt.Single_To_Packed (F, P, K_Factor);

            -- get corrected value of log 10 and formatting params
            Log10 := Get_Log10 (P);
            Compute_Format_Params (Digits_Fore   => Digits_Fore,
                                   Digits_Aft    => Digits_Aft,
                                   Has_Exponent  => (Digits_Exp /= 0),
                                   Log10         => Log10,
                                   Digits_After  => Digits_After,
                                   Digits_Before => Digits_Before,
                                   Zeros_Before  => Zeros_Before,
                                   K_Factor      => K_Factor);

            Image (P             => P,
                   Digits_Fore   => Digits_Fore,
                   Digits_Aft    => Digits_Aft,
                   Digits_Exp    => Digits_Exp,
                   Digits_Before => Digits_Before,
                   Digits_After  => Digits_After,
                   Zeros_Before  => Zeros_Before,
                   Log10         => Log10,
                   Result_Str    => Result_Str,
                   Result_Last   => Result_Last);
        else
            Zero_Image (Result_Str  => Result_Str,
                        Result_Last => Result_Last,
                        Digits_Fore => Digits_Fore,
                        Digits_Aft  => Digits_Aft,
                        Digits_Exp  => Digits_Exp);
        end if;
    end Image;

    procedure Image (F : in Long_Float;  
                     Digits_Fore, Digits_Aft, Digits_Exp : in Natural;
                     Result_Str : out String;
                     Result_Last : out Natural) is
        P             : Flt.Packed_Float;
        Log10         : Integer;
        Digits_After  : Natural;
        Digits_Before : Natural;
        Zeros_Before  : Natural;
        K_Factor      : Natural;
    begin
        if F /= 0.0 then
            Flt.Double_To_Packed (F, P, 15);

            -- get estimate of log 10 and format params
            Log10 := Get_Log10 (P);
            Compute_Format_Params (Digits_Fore   => Digits_Fore,
                                   Digits_Aft    => Digits_Aft,
                                   Has_Exponent  => (Digits_Exp /= 0),
                                   Log10         => Log10,
                                   Digits_After  => Digits_After,
                                   Digits_Before => Digits_Before,
                                   Zeros_Before  => Zeros_Before,
                                   K_Factor      => K_Factor);
            Flt.Double_To_Packed (F, P, K_Factor);

            -- now get corrected value of log 10 and formatting params
            Log10 := Get_Log10 (P);
            Compute_Format_Params (Digits_Fore   => Digits_Fore,
                                   Digits_Aft    => Digits_Aft,
                                   Has_Exponent  => (Digits_Exp /= 0),
                                   Log10         => Log10,
                                   Digits_After  => Digits_After,
                                   Digits_Before => Digits_Before,
                                   Zeros_Before  => Zeros_Before,
                                   K_Factor      => K_Factor);

            Image (P             => P,
                   Digits_Fore   => Digits_Fore,
                   Digits_Aft    => Digits_Aft,
                   Digits_Exp    => Digits_Exp,
                   Digits_Before => Digits_Before,
                   Digits_After  => Digits_After,
                   Zeros_Before  => Zeros_Before,
                   Log10         => Log10,
                   Result_Str    => Result_Str,
                   Result_Last   => Result_Last);
        else
            Zero_Image (Result_Str  => Result_Str,
                        Result_Last => Result_Last,
                        Digits_Fore => Digits_Fore,
                        Digits_Aft  => Digits_Aft,
                        Digits_Exp  => Digits_Exp);
        end if;
    end Image;

end M68k_Float_Conversions;