home *** CD-ROM | disk | FTP | other *** search
/ Programmer's ROM - The Computer Language Library / programmersrom.iso / ada / math / m36.src < prev    next >
Encoding:
Text File  |  1988-05-03  |  238.5 KB  |  6,522 lines

  1. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  2. --maebasic.txt
  3. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  4. -------------------------------------------------------------------------------
  5. --                                                                           --
  6. --             Emulation of Machine Arithmetic - a WIS Ada Tool              --
  7. --                                                                           --
  8. --                         Ada Technology Group                              --
  9. --                         SYSCON Corporation                                --
  10. --                         3990 Sherman Street                               --
  11. --                         San Diego, CA. 92110                              --
  12. --                                                                           --
  13. --                        John Long & John Reddan                            --
  14. --                                                                           --
  15. -------------------------------------------------------------------------------
  16.  
  17. package MAE_BASIC_OPERATIONS is
  18. -------------------------------------------------------------------
  19. -- The emulation packages are currently configured 
  20. -- to support Honeywell 36-bit arithmetic.
  21. --
  22. -- The purpose of this package is to provide general machine
  23. -- arithmetic types and functions to support integer and floating
  24. -- point variables.  The underlying arithmetic operations will
  25. -- be performed component-wise.  It is assumed that the system
  26. -- provides for integer operations.
  27.  
  28. -------------------------------------------------------------------
  29. -- Here are the declarations of the basic constants and variables.
  30. -- Some of these constants reflect the emulation target and the
  31. -- implementation host (and compiler) dependencies.
  32. -- It is possible that changing these constants and variables could
  33. -- improve software performance.  They are the basic elements for
  34. -- building the MAE_INTEGER_TYPE and MAE_FLOAT_TYPE types.
  35. --
  36.    -- number of bits in a component
  37.       NO_COMP_BITS : constant INTEGER := 7;
  38.    -- maximum value of a component
  39.       MAX_COMP_VALUE : constant INTEGER := (2**NO_COMP_BITS)-1;
  40.    -- component base value
  41.       BASE_COMP_VALUE : constant INTEGER := MAX_COMP_VALUE+1;
  42.    -- the values associated with a bit position,
  43.    --  initialized in the body of this package
  44.       BIT_VALUE : array (1 .. NO_COMP_BITS) of INTEGER; 
  45.    -- a component, note that the range of a true component is
  46.    -- 0 .. MAX_COMP_VALUE, although intermediate values, obtained
  47.    -- during computations, lie outside the range.
  48.       subtype COMP is INTEGER;
  49.    -- an array of components
  50.       type COMPONENT_ARRAY_TYPE is array (NATURAL range <>) of COMP;
  51.    -- the use of representation specifications could direct the
  52.    --  compiler how to store the array and possibly increase efficiency.
  53.    --  note that the least significant COMP is the first in the
  54.    --  array, and consequently the most significant COMP is the last.
  55.    --
  56.    --  most signif                                     least signif
  57.    --    'last                            . .            'first
  58.    -- --------------  --------------                  --------------  
  59.    -- | 1 2 3 .. n |  | 1 2 3 .. n |      . .         | 1 2 3 .. n |
  60.    -- --------------  --------------                  -------------- 
  61.  
  62.    -- Identification of the caller
  63.       type CLASSIFICATION is (INTEGER_CLASS, SHORT_FLOAT_CLASS,
  64.                                LONG_FLOAT_CLASS);
  65.  
  66.    -- Declaration for short comp arrays
  67.       SHORT_NUM_COMPS : constant INTEGER := 6;
  68.       SHORT_NUM_BITS : constant INTEGER := SHORT_NUM_COMPS * NO_COMP_BITS;
  69.       subtype SHORT_COMPONENT_ARRAY is 
  70.                  COMPONENT_ARRAY_TYPE (1 .. SHORT_NUM_COMPS);
  71.       SHORT_ZERO_ARRAY : constant SHORT_COMPONENT_ARRAY :=
  72.                     (1 .. SHORT_NUM_COMPS => 0);
  73.  
  74.       type SHORT_COMP_ARRAY is
  75.          record
  76.             COMPONENT_ARRAY : SHORT_COMPONENT_ARRAY;
  77.             CLASS_OF_ARRAY : CLASSIFICATION;
  78.             BITS_SHIFTED : INTEGER;
  79.          end record;
  80.  
  81.       INTEGER_COMP_ARRAY : SHORT_COMP_ARRAY :=
  82.                                   (SHORT_ZERO_ARRAY, INTEGER_CLASS, 0);
  83.       SHORT_FLOAT_COMP_ARRAY : SHORT_COMP_ARRAY :=
  84.                                   (SHORT_ZERO_ARRAY, SHORT_FLOAT_CLASS, 0);
  85.  
  86.    -- The emulated target dependent constants for 36-bit storage
  87.       TARGET_INTEGER_NUM_BITS : constant INTEGER := 35;
  88.       TARGET_SHORT_NUM_BITS : constant INTEGER := 28;
  89.  
  90.    -- Declaration for long comp arrays
  91.       LONG_NUM_COMPS : constant INTEGER := (2 * SHORT_NUM_COMPS);
  92.       LONG_NUM_BITS : constant INTEGER := LONG_NUM_COMPS * NO_COMP_BITS;
  93.       subtype LONG_COMPONENT_ARRAY is 
  94.                  COMPONENT_ARRAY_TYPE (1 .. LONG_NUM_COMPS);
  95.       LONG_ZERO_ARRAY : LONG_COMPONENT_ARRAY :=
  96.                     (1 .. LONG_NUM_COMPS => 0);
  97.  
  98.       type LONG_COMP_ARRAY is
  99.          record
  100.             COMPONENT_ARRAY : LONG_COMPONENT_ARRAY;
  101.             CLASS_OF_ARRAY : CLASSIFICATION;
  102.             BITS_SHIFTED : INTEGER;
  103.          end record;
  104.  
  105.       LONG_FLOAT_COMP_ARRAY : LONG_COMP_ARRAY :=
  106.                    (LONG_ZERO_ARRAY, LONG_FLOAT_CLASS, 0);
  107.  
  108.    -- The emulated target dependent constants for 72-bit storage
  109.       TARGET_LONG_NUM_BITS : constant INTEGER := 64;
  110.  
  111.    -- Extended array length for LONG multiplication
  112.       subtype EXTRA_COMPONENT_ARRAY is
  113.                  COMPONENT_ARRAY_TYPE  (1 .. LONG_NUM_COMPS*2);
  114.       EXTRA_ZERO_ARRAY : EXTRA_COMPONENT_ARRAY :=
  115.                     (1 .. LONG_NUM_COMPS*2 => 0);
  116.  
  117.    -- Extended array for spaces filling string arrays
  118.       EMPTY_STRING : STRING (1 .. 40) :=
  119.           "                                        ";
  120.  
  121.    -- the sign of a number
  122.       subtype SIGN_TYPE is BOOLEAN;
  123.       NEG_SIGN : constant BOOLEAN := FALSE;
  124.       POS_SIGN : constant BOOLEAN := TRUE;
  125.    -- the exponent of a floating type
  126.       subtype EXPONENT_TYPE is INTEGER;
  127.       MIN_EXPONENT_VALUE : constant INTEGER := -128;
  128.       MAX_EXPONENT_VALUE : constant INTEGER := 127;
  129.  
  130.    -- The follow declarations specify the value of the most
  131.    -- significant component for the digits ONE .. TEN and their
  132.    -- corresponding exponents.  The component values can be thought
  133.    -- of as a binary representation (picture) of the most signif.
  134.    -- comp.  Applying the binary exponent as left shifts, it is 
  135.    -- easy to see how the digit is obtained.  This allows
  136.    -- for the length of the array to change without affecting
  137.    -- the code in the higher level packages.
  138.       POINT_FIVE : constant INTEGER := 2**(NO_COMP_BITS-1);
  139.       POINT_FIVE_SIX_TWO_FIVE : constant INTEGER :=
  140.          2**(NO_COMP_BITS-1) + 2**(NO_COMP_BITS-4);
  141.       POINT_SIX_TWO_FIVE : constant INTEGER :=
  142.          2**(NO_COMP_BITS-1) + 2**(NO_COMP_BITS-3);
  143.       POINT_SEVEN_FIVE : constant INTEGER :=
  144.          2**(NO_COMP_BITS-1) + 2**(NO_COMP_BITS-2);
  145.       POINT_EIGHT_SEVEN_FIVE : constant INTEGER :=
  146.          2**(NO_COMP_BITS-1) + 2**(NO_COMP_BITS-2) + 2**(NO_COMP_BITS-3);
  147.       DIGIT_PICTURE : constant array (1 .. 10) of INTEGER :=
  148.          (POINT_FIVE,
  149.           POINT_FIVE,
  150.           POINT_SEVEN_FIVE,
  151.           POINT_FIVE,
  152.           POINT_SIX_TWO_FIVE,
  153.           POINT_SEVEN_FIVE,
  154.           POINT_EIGHT_SEVEN_FIVE,
  155.           POINT_FIVE,
  156.           POINT_FIVE_SIX_TWO_FIVE,
  157.           POINT_SIX_TWO_FIVE);
  158.       DIGIT_BINARY_EXPONENT : constant array (1 .. 10) of INTEGER :=
  159.          (1, 2, 2, 3, 3, 3, 3, 4, 4, 4); 
  160.  
  161.  
  162.    -- String IO constants
  163.    -- the only base available is base 10
  164.       subtype NUMBER_BASE is INTEGER range 2 .. 16;
  165.       DEFAULT_BASE : constant NUMBER_BASE := 10;
  166.       subtype FIELD is INTEGER range 0 .. INTEGER'last;
  167.  
  168.    -- a TeleSoft 1.5 restriction that is detected in the package
  169.    -- above this package does not allow
  170.    --   SHORT_DEFAULT_AFT : constant FIELD := SHORT_FLOAT_DIGITS-1;
  171.    --   LONG_DEFAULT_AFT : constant FIELD := LONG_FLOAT_DIGITS-1;
  172.       SHORT_DEFAULT_AFT : constant FIELD := 7;
  173.       LONG_DEFAULT_AFT : constant FIELD := 17;
  174.  
  175.       SHORT_DEFAULT_EXP : constant FIELD := 3;
  176.       LONG_DEFAULT_EXP : constant FIELD := 3;
  177.  
  178.  
  179.    -- predefined attributes
  180.       LOG_2 : constant FLOAT := 0.30103;
  181.       SHORT_FLOAT_DIGITS : constant INTEGER :=
  182.           INTEGER((FLOAT(TARGET_SHORT_NUM_BITS-1)*LOG_2)-0.5);
  183.       LONG_FLOAT_DIGITS : constant INTEGER :=
  184.           INTEGER((FLOAT(TARGET_LONG_NUM_BITS-1)*LOG_2)-0.5);
  185.       -- the next declaration is not exported from MAE, it
  186.       -- is only used in the integer PUT and IMAGE routines
  187.       INTEGER_DIGITS : constant INTEGER :=
  188.           INTEGER((FLOAT(TARGET_INTEGER_NUM_BITS)*LOG_2)+0.5);
  189.  
  190.       SHORT_FLOAT_EMAX : INTEGER renames MAX_EXPONENT_VALUE;
  191.       LONG_FLOAT_EMAX : INTEGER renames MAX_EXPONENT_VALUE;
  192.  
  193.       SHORT_FLOAT_MACHINE_EMAX : INTEGER renames MAX_EXPONENT_VALUE;
  194.       LONG_FLOAT_MACHINE_EMAX : INTEGER renames MAX_EXPONENT_VALUE;
  195.  
  196.       SHORT_FLOAT_MACHINE_EMIN : INTEGER renames MIN_EXPONENT_VALUE;
  197.       LONG_FLOAT_MACHINE_EMIN : INTEGER renames MIN_EXPONENT_VALUE;
  198.  
  199.       SHORT_FLOAT_MACHINE_MANTISSA : INTEGER 
  200.            renames TARGET_SHORT_NUM_BITS;
  201.       LONG_FLOAT_MACHINE_MANTISSA : INTEGER
  202.            renames TARGET_LONG_NUM_BITS;
  203.  
  204.       SHORT_FLOAT_MACHINE_OVERFLOWS : constant BOOLEAN := TRUE;
  205.       LONG_FLOAT_MACHINE_OVERFLOWS : constant BOOLEAN := TRUE;
  206.  
  207.       SHORT_FLOAT_MACHINE_RADIX : constant INTEGER := 2;
  208.       LONG_FLOAT_MACHINE_RADIX : constant INTEGER := 2;
  209.  
  210.       SHORT_FLOAT_MACHINE_ROUNDS : constant BOOLEAN := TRUE;
  211.       LONG_FLOAT_MACHINE_ROUNDS : constant BOOLEAN := TRUE;
  212.  
  213.       SHORT_FLOAT_SAFE_EMAX : INTEGER renames MAX_EXPONENT_VALUE;
  214.       LONG_FLOAT_SAFE_EMAX : INTEGER renames MAX_EXPONENT_VALUE;
  215.  
  216.  
  217. -------------------------------------------------------------------
  218. -- The exception to be raised for all arithmetic and boolean
  219. -- functions defined in this package.
  220. --
  221.    MAE_NUMERIC_ERROR : EXCEPTION renames STANDARD.NUMERIC_ERROR;
  222.  
  223. -------------------------------------------------------------------
  224. -- Function to determine the number of components for 
  225. -- the representation.
  226. --
  227.    function BITS_TO_COMPS (NO_OF_BITS : INTEGER) return INTEGER;
  228.  
  229. -------------------------------------------------------------------
  230. -- Operations on the sign
  231. --
  232.    -- Since the SIGN_TYPE is a BOOLEAN, most of the operations
  233.    -- are assumed system functions
  234.   
  235.    function CHANGE_SIGN (SIGN : SIGN_TYPE) return SIGN_TYPE;
  236.  
  237. -------------------------------------------------------------------
  238. -- Operations on the exponent
  239. --
  240.    -- Since the EXPONENT_TYPE is an INTEGER, the operations
  241.    -- are assumed system functions
  242.  
  243. -------------------------------------------------------------------
  244. -- Operations on the component
  245. --
  246.    -- If the variable NO_COMP_BITS is chosen properly, an assumption
  247.    -- on which the entire package design is based, COMP and any
  248.    -- result of binary operation (except exponentiation which is
  249.    -- never used with COMP) of two COMPs is an INTEGER.
  250.    -- Therefore, the operations are assumed system functions 
  251.  
  252. -------------------------------------------------------------------
  253. -- Operations on short component arrays
  254. --
  255.    -- Predefined system functions : function "=" and function "/=". 
  256.    -- Comparisons are handled under variable-sized arrays.
  257.    -- The array parameters must have the same length and the same
  258.    -- CLASSIFICATION (both INTEGER_CLASS or both SHORT_FLOAT_CLASS).
  259.    -- The returning result component array will contain the same
  260.    -- number of elements.
  261.    -- For SHORT_FLOAT_CLASS parameters, the BITS_SHIFTED variable within
  262.    -- the array is set for higher level exponent operation.
  263.    -- The SHORT_FLOAT_CLASS array will be normalized by these routines.
  264.    -- Note that the least significant COMP is the first in the
  265.    -- array, and consequently the most significant COMP is the last.
  266.  
  267.    function "+"    (LEFT,RIGHT : SHORT_COMP_ARRAY) return SHORT_COMP_ARRAY;
  268.    function "-"    (LEFT,RIGHT : SHORT_COMP_ARRAY) return SHORT_COMP_ARRAY;
  269.    function "*"    (LEFT,RIGHT : SHORT_COMP_ARRAY) return SHORT_COMP_ARRAY;
  270.    function "/"    (LEFT,RIGHT : SHORT_COMP_ARRAY) return SHORT_COMP_ARRAY;
  271.    function "rem"  (LEFT,RIGHT : SHORT_COMP_ARRAY) return SHORT_COMP_ARRAY;
  272.  
  273.  
  274. -------------------------------------------------------------------
  275. -- Operations on long component arrays
  276. --
  277.    -- Predefined system functions : function "=" and function "/=". 
  278.    -- Comparisions are handled under variable-sized arrays.
  279.    -- The array parameters must have the same length.
  280.    -- The returning result component array will contain the same
  281.    -- number of elements.
  282.    -- For LONG_FLOAT_CLASS parameters, the BITS_SHIFTED variable within
  283.    -- the array is set for higher level exponent operation.
  284.    -- The LONG_FLOAT_CLASS array will be normalized by these routines.
  285.  
  286.    function "+"    (LEFT,RIGHT : LONG_COMP_ARRAY) return LONG_COMP_ARRAY;
  287.    function "-"    (LEFT,RIGHT : LONG_COMP_ARRAY) return LONG_COMP_ARRAY;
  288.    function "*"    (LEFT,RIGHT : LONG_COMP_ARRAY) return LONG_COMP_ARRAY;
  289.    function "/"    (LEFT,RIGHT : LONG_COMP_ARRAY) return LONG_COMP_ARRAY;
  290.  
  291.  
  292. -------------------------------------------------------------------
  293. -- Operations on variable-sized component arrays
  294. --
  295.    -- The array parameters are only comprised of components,
  296.    -- no CLASSIFICATION or BITS_SHIFTED info is included.
  297.    -- The array will not be normalized by these routines, that
  298.    -- is the responsibility of a higher level routine.
  299.  
  300.    -- The comparison functions.
  301.    -- Predefined system functions : function "=" and function "/=". 
  302.  
  303.    function "<"    (LEFT, RIGHT : COMPONENT_ARRAY_TYPE) return BOOLEAN;
  304.    function "<="   (LEFT, RIGHT : COMPONENT_ARRAY_TYPE) return BOOLEAN;
  305.    function ">"    (LEFT, RIGHT : COMPONENT_ARRAY_TYPE) return BOOLEAN;
  306.    function ">="   (LEFT, RIGHT : COMPONENT_ARRAY_TYPE) return BOOLEAN;
  307.  
  308.    -- This routine performs a divide by two on the array,
  309.    -- with rounding to even.
  310.    procedure DIVIDE_ARRAY_BY_TWO (INTERMEDIATE : in out COMPONENT_ARRAY_TYPE);
  311.  
  312.    -- This routine sets the range of all individual COMPs within
  313.    -- (0 .. MAX_COMP_VALUE) by looping through the array from the least 
  314.    -- significant COMP to the most significant COMP, performing
  315.    -- carries and borrows as necessary.  Since the most significant
  316.    -- COMP has nowhere to carry or borrow, it is left unbounded.
  317.    -- This allows the higher level routine to determine if shifting
  318.    -- must occur, an error exists, or whatever.
  319.    procedure RANGE_CHECK (INTERMEDIATE : in out COMPONENT_ARRAY_TYPE);
  320.  
  321.    -- This routine shifts to the right and truncates a
  322.    -- component array.  The BITS variable is the number of bits
  323.    -- to shift the array and must be positive.
  324.    procedure ARRAY_TRUNCATION_SHIFT_RIGHT 
  325.       (INTERMEDIATE : in out COMPONENT_ARRAY_TYPE; BITS : in NATURAL);
  326.  
  327.    -- This routine sets the most significant bit in the array to one
  328.    -- (normalized), by shifting the array to the left.
  329.    -- The BITS variable is the number of bits the array was shifted.
  330.    procedure ARRAY_NORMALIZE
  331.       (INTERMEDIATE : in out COMPONENT_ARRAY_TYPE; BITS : out INTEGER);
  332.  
  333. -------------------------------------------------------------------
  334. end MAE_BASIC_OPERATIONS;
  335.  
  336. -------------------------------------------------------------------
  337. -------------------------------------------------------------------
  338.  
  339. package body MAE_BASIC_OPERATIONS is
  340. -------------------------------------------------------------------
  341. -- The purpose of this package is to provide general 
  342. -- arithmetic operations for computation of integer and floating
  343. -- point variables.
  344.  
  345.  
  346. -------------------------------------------------------------------
  347. -- Local exceptions
  348. --
  349.    MAE_INTEGER_OVERFLOW : EXCEPTION;
  350.    MAE_DIVIDE_BY_ZERO : EXCEPTION;
  351.    MAE_INVALID_OPERATION : EXCEPTION;
  352.    MAE_IMPOSSIBLE : EXCEPTION;
  353.  
  354. -------------------------------------------------------------------
  355. -- Function to determine the number of components needed for
  356. -- the representation. 
  357. --
  358.    function BITS_TO_COMPS (NO_OF_BITS : NATURAL) return NATURAL is
  359.       -- This routine returns number of components needed in the
  360.       -- array to hold at least all the bits.  
  361.    begin
  362.      return (((NO_OF_BITS - 1) / NO_COMP_BITS) + 1);
  363.    end BITS_TO_COMPS;
  364.  
  365. -------------------------------------------------------------------
  366. -- Operations on the sign
  367. --
  368.    function CHANGE_SIGN (SIGN : SIGN_TYPE) return SIGN_TYPE is
  369.       -- The purpose of this function is to change
  370.       -- the sign.
  371.    begin
  372.       -- Change the sign by using a case on possible values
  373.       case SIGN is
  374.          when POS_SIGN => return NEG_SIGN;
  375.          when NEG_SIGN => return POS_SIGN;
  376.       end case;
  377.    end CHANGE_SIGN;
  378.  
  379. -------------------------------------------------------------------
  380. -- Operations on component arrays
  381. --
  382. -- For all the operations on two component arrays, the component
  383. -- arrays must have the same number of elements(components) and
  384. -- the returning result component array will contain the same
  385. -- number of elements.
  386. --
  387.    function "<"    (LEFT, RIGHT : COMPONENT_ARRAY_TYPE) return BOOLEAN is
  388.       -- Compare arrays from the most significant component to the
  389.       -- least significant component until the compare is resolved.
  390.       -- Since this routine is internal to the MAE package, it is 
  391.       -- assumed the caller will pass identically sized arrays.
  392.       -- Therefore, there are no error checks.
  393.    begin
  394.       for I in reverse LEFT'first .. LEFT'last loop
  395.           if LEFT(I) < RIGHT(I) then
  396.             return TRUE;
  397.           elsif LEFT(I) > RIGHT(I) then 
  398.             return FALSE;
  399.           end if;
  400.       end loop;
  401.       -- The arrays were equal.
  402.       return FALSE;
  403.    end "<";
  404.  
  405. -----------------------------
  406.  
  407.    function "<="   (LEFT, RIGHT : COMPONENT_ARRAY_TYPE) return BOOLEAN is
  408.       -- Compare arrays from the most significant component to the
  409.       -- least significant component until the compare is resolved.
  410.       -- Since this routine is internal to the MAE package, it is 
  411.       -- assumed the caller will pass identically sized arrays.
  412.       -- Therefore, there are no error checks.
  413.    begin
  414.  
  415.       for I in reverse LEFT'first .. LEFT'last loop
  416.           if LEFT(I) < RIGHT(I) then
  417.             return TRUE;
  418.           elsif LEFT(I) > RIGHT(I) then 
  419.             return FALSE;
  420.           end if;
  421.       end loop;
  422.       -- The arrays were equal.
  423.       return TRUE;
  424.    end "<=";
  425.  
  426. -----------------------------
  427.  
  428.    function ">"    (LEFT, RIGHT : COMPONENT_ARRAY_TYPE) return BOOLEAN is
  429.       -- Compare arrays from the most significant component to the
  430.       -- least significant component until the compare is resolved.
  431.       -- Since this routine is internal to the MAE package, it is 
  432.       -- assumed the caller will pass identically sized arrays.
  433.       -- Therefore, there are no error checks.
  434.    begin
  435.  
  436.       for I in reverse LEFT'first .. LEFT'last loop
  437.           if LEFT(I) > RIGHT(I) then
  438.             return TRUE;
  439.           elsif LEFT(I) < RIGHT(I) then 
  440.             return FALSE;
  441.           end if;
  442.       end loop;
  443.       -- The arrays were equal.
  444.       return FALSE;
  445.    end ">";
  446.  
  447. -----------------------------
  448.  
  449.    function ">="   (LEFT, RIGHT : COMPONENT_ARRAY_TYPE) return BOOLEAN is
  450.       -- Compare arrays from the most significant component to the
  451.       -- least significant component until the compare is resolved.
  452.       -- Since this routine is internal to the MAE package, it is 
  453.       -- assumed the caller will pass identically sized arrays.
  454.       -- Therefore, there are no error checks.
  455.    begin
  456.       for I in reverse LEFT'first .. LEFT'last loop
  457.           if LEFT(I) > RIGHT(I) then
  458.             return TRUE;
  459.           elsif LEFT(I) < RIGHT(I) then 
  460.             return FALSE;
  461.           end if;
  462.       end loop;
  463.       -- The arrays were equal.
  464.       return TRUE;
  465.    end ">=";
  466.  
  467. -------------------------------------------------------------------
  468. -- This section contains a set of tools to be used by the higher
  469. -- level routines
  470. --
  471.  
  472.    procedure DIVIDE_ARRAY_BY_TWO(INTERMEDIATE : in out COMPONENT_ARRAY_TYPE) is
  473.       -- The purpose of this procedure is to divide the component
  474.       -- array by two (it is equilvalent to a right shift)
  475.       -- with rounding to even.
  476.       CARRY_DOWN : INTEGER := 0;
  477.       INDEX, TEMP : INTEGER;
  478.       CARRY_VALUE : constant INTEGER := BIT_VALUE(BIT_VALUE'first);
  479.    begin
  480.       -- Loop over the array from the most signif to the least
  481.       -- signif, dividing the individual COMP by two and carrying
  482.       -- down the remainder.
  483.       for I in reverse INTERMEDIATE'first .. INTERMEDIATE'last loop
  484.          TEMP := INTERMEDIATE(I);
  485.          INTERMEDIATE(I) := (TEMP / 2) + (CARRY_DOWN * CARRY_VALUE);
  486.          CARRY_DOWN := TEMP rem 2;
  487.       end loop;
  488.  
  489.       -- Check for rounding to even.
  490.       -- Since we have shifted only one bit, if the least signif
  491.       -- bit in the array is one, then add the shifted bit back
  492.       -- into the least signif COMP and do a inline RANGE_CHECK.
  493.       if (INTERMEDIATE(INTERMEDIATE'first) rem 2) = 1 then
  494.          INTERMEDIATE(INTERMEDIATE'first) := 
  495.             INTERMEDIATE(INTERMEDIATE'first) + CARRY_DOWN;
  496.  
  497.          -- Since the maximum value for the carry down was one,
  498.          -- all carries must equal one and remainders must equal zero.
  499.          INDEX := INTERMEDIATE'first;
  500.          while INTERMEDIATE(INDEX) > MAX_COMP_VALUE loop
  501.             -- The comp is oversized, the carry value will be one.
  502.             INTERMEDIATE(INDEX) := 0;
  503.             INDEX := INDEX + 1;
  504.             INTERMEDIATE(INDEX) := INTERMEDIATE(INDEX) + 1;
  505.          end loop;
  506.       end if;         
  507.          
  508.    end DIVIDE_ARRAY_BY_TWO;
  509.  
  510. -----------------------------
  511.  
  512.    procedure RANGE_CHECK(INTERMEDIATE : in out COMPONENT_ARRAY_TYPE) is
  513.       -- This routine sets the range of all individual COMPs within
  514.       -- (0 .. MAX_COMP_VALUE) by looping through the array from the least 
  515.       -- significant COMP to the most significant COMP, performing
  516.       -- carries and borrows as necessary.  Since the most significant
  517.       -- COMP has nowhere to carry or borrow, it is left unbounded.
  518.       -- This allows the higher level routine to determine if shifting
  519.       -- must occur, an error exists, or whatever.
  520.       CARRY : INTEGER;
  521.    begin
  522.       -- Loop over array from the least to the most signif.
  523.       -- If the COMP is oversized, modulo it to within size
  524.       -- and add the carry to the next higher COMP.
  525.       -- If the COMP is undersized, modulo it to within size
  526.       -- and add the borrow to the next higher COMP.
  527.       for I in INTERMEDIATE'first .. INTERMEDIATE'last-1 loop
  528.          if INTERMEDIATE(I) > MAX_COMP_VALUE then
  529.             -- The comp is oversized, the carry value will be positive.
  530.             CARRY := INTERMEDIATE(I) / BASE_COMP_VALUE;
  531.             INTERMEDIATE(I) := INTERMEDIATE(I) MOD BASE_COMP_VALUE;
  532.             INTERMEDIATE(I+1) := INTERMEDIATE(I+1) + CARRY;
  533.          elsif INTERMEDIATE(I) < 0 then
  534.             -- The comp is negative, the carry value will be negative.
  535.             CARRY := ((INTERMEDIATE(I)+1) / BASE_COMP_VALUE) - 1;
  536.             INTERMEDIATE(I) := INTERMEDIATE(I) MOD BASE_COMP_VALUE;
  537.             INTERMEDIATE(I+1) := INTERMEDIATE(I+1) + CARRY;
  538.          end if;
  539.       end loop;
  540.    end RANGE_CHECK;
  541.  
  542. -----------------------------
  543.  
  544.    procedure ARRAY_TRUNCATION_SHIFT_RIGHT
  545.           (INTERMEDIATE : in out COMPONENT_ARRAY_TYPE; BITS : in NATURAL) is
  546.       -- The purpose of this function is a right shift, truncating
  547.       -- any bits shift beyond the array bounds.  First shift across
  548.       -- whole components, then shift bits.
  549.       CARRY_DOWN : INTEGER := 0;
  550.       TEMP : INTEGER;
  551.       WHOLE_COMPS, WHOLE_COMPS_OPPOSITE : INTEGER;
  552.       INNER_BITS, INNER_BITS_OPPOSITE : INTEGER;
  553.       DIVIDER_VALUE, CARRY_VALUE : INTEGER;
  554.    begin
  555.       -- First determine if BITS is greater than the size of
  556.       -- a COMP, if it is then shift whole COMPS.
  557.       WHOLE_COMPS := BITS / NO_COMP_BITS;
  558.       WHOLE_COMPS_OPPOSITE := INTERMEDIATE'last - WHOLE_COMPS;
  559.       if WHOLE_COMPS > 0 then
  560.  
  561.          -- Shift in the order of least to most signif component 
  562.          -- so as not to overwrite any of the number.
  563.          for I in INTERMEDIATE'first .. WHOLE_COMPS_OPPOSITE loop
  564.             INTERMEDIATE(I) := INTERMEDIATE(I+WHOLE_COMPS);
  565.          end loop;
  566.  
  567.          -- Zero fill the components that are above where the 
  568.          -- most signif component was moved.
  569.          for I in WHOLE_COMPS_OPPOSITE+1 .. INTERMEDIATE'last loop
  570.             INTERMEDIATE(I) := 0;
  571.          end loop;
  572.       end if;
  573.  
  574.       -- Now perform bit shifts within, and across, components.
  575.       INNER_BITS := BITS rem NO_COMP_BITS;
  576.       if INNER_BITS > 0 then
  577.          CARRY_DOWN := 0;
  578.  
  579.          -- Since shifts across components can occur, a constant
  580.          -- carry down multiplier value, dependent on the bits
  581.          -- shifted, must be determined.
  582.          CARRY_VALUE := BIT_VALUE(INNER_BITS);
  583.          INNER_BITS_OPPOSITE := NO_COMP_BITS - INNER_BITS;
  584.          -- Since shifts across components can occur, a constant
  585.          -- modulo divider value, dependent on the bits
  586.          -- shifted, must be determined.
  587.          DIVIDER_VALUE := BIT_VALUE(INNER_BITS_OPPOSITE);
  588.  
  589.          -- Shift in the order of most to least signif so as 
  590.          -- to add in the carry down.
  591.          for I in reverse INTERMEDIATE'first .. WHOLE_COMPS_OPPOSITE loop
  592.             TEMP := INTERMEDIATE(I);
  593.             INTERMEDIATE(I) := (TEMP / DIVIDER_VALUE)
  594.                                    + (CARRY_DOWN * CARRY_VALUE);
  595.             CARRY_DOWN := TEMP rem DIVIDER_VALUE;
  596.          end loop;
  597.       end if;         
  598.          
  599.    end ARRAY_TRUNCATION_SHIFT_RIGHT;
  600.  
  601. -----------------------------
  602.   
  603.    function FIND_MOST_SIGNIF_BIT (MOST_SIGNIF_COMP : COMP) return INTEGER is
  604.       -- The purpose of this function is to return the bit position
  605.       -- of the most signif bit that is on in a COMP, where the
  606.       -- most signif position is one and the least signif is NO_COMP_BITS.
  607.       -- Since this routine is internal to the MAE package, it is 
  608.       -- assumed the caller will pass a non-zero COMP.
  609.       -- Therefore, there are no error checks.
  610.       BIT : INTEGER;
  611.    begin
  612.       for I in 1 .. NO_COMP_BITS loop
  613.          BIT := I;
  614.          exit when MOST_SIGNIF_COMP >= BIT_VALUE(BIT);
  615.       end loop;
  616.       return BIT;
  617.    end FIND_MOST_SIGNIF_BIT;
  618.  
  619. -----------------------------
  620.  
  621.    procedure ARRAY_NORMALIZE (INTERMEDIATE : in out COMPONENT_ARRAY_TYPE; 
  622.                               BITS : out INTEGER) is
  623.       -- The purpose of this function is to normalize a COMPONENT_ARRAY.
  624.       -- First find the most signif comp in the array.  Then shift across
  625.       -- whole comps to place the most signif comp.  Now multiply the
  626.       -- array by a constant that sets the most signif bit.
  627.       -- Returning the number of bits shifted and a normalized
  628.       -- COMPONENT_ARRAY.
  629.       -- Note that the routine does not adjust for oversized
  630.       -- COMPs.  The array should be RANGE_CHECKed and the most
  631.       -- signif component inpected, before passing to this routine.
  632.       MULTIPLIER : INTEGER;
  633.       MSC, MSC_OPPOSITE : INTEGER;
  634.    begin
  635.       BITS := 0;
  636.       -- Check if already normal.
  637.       if INTERMEDIATE(INTERMEDIATE'last) >= BIT_VALUE(BIT_VALUE'first) then
  638.          return;
  639.       end if;
  640.  
  641.       -- Check for zero, if not zero, then the most signif comp is located.
  642.       MSC := INTERMEDIATE'last;
  643.       while INTERMEDIATE(MSC) = 0 loop
  644.          MSC := MSC - 1;
  645.          if MSC = 0 then
  646.             -- The array is zero.
  647.             return;
  648.          end if;
  649.       end loop;
  650.       MSC_OPPOSITE := INTERMEDIATE'last - MSC;
  651.  
  652.       -- Shift across array comps if necessary, zeroing the trailing.
  653.       if MSC < INTERMEDIATE'last then
  654.          -- Shift in the order of most to least signif so as not
  655.          -- to overwrite any of the number.
  656.          for J in reverse INTERMEDIATE'first .. MSC loop
  657.             INTERMEDIATE(J+MSC_OPPOSITE) := INTERMEDIATE(J);
  658.          end loop;
  659.          for J in INTERMEDIATE'first .. MSC_OPPOSITE loop
  660.             INTERMEDIATE(J) := 0;
  661.          end loop;
  662.       end if;
  663.  
  664.       -- Set the most signif bit by finding the highest valued bit
  665.       -- that is on, then multipling the array by a constant that
  666.       -- moves the highest bit into the most signif bit
  667.       -- position in the array.
  668.       BITS := FIND_MOST_SIGNIF_BIT(INTERMEDIATE(INTERMEDIATE'last)) - 1;
  669.       MULTIPLIER := BIT_VALUE(NO_COMP_BITS-BITS);
  670.       if MULTIPLIER > 1 then
  671.          for J in INTERMEDIATE'range loop
  672.             INTERMEDIATE(J) := INTERMEDIATE(J) * MULTIPLIER;
  673.          end loop;
  674.          RANGE_CHECK(INTERMEDIATE);
  675.       end if;
  676.  
  677.       -- Set the returned value of the number of bits shifted,
  678.       -- which includes whole components and bits shifted.
  679.       BITS := BITS + (MSC_OPPOSITE * NO_COMP_BITS);
  680.  
  681.     end ARRAY_NORMALIZE;
  682.  
  683. -------------------------------------------------------------------
  684.  
  685.    function "+"    (LEFT,RIGHT : SHORT_COMP_ARRAY) return SHORT_COMP_ARRAY is
  686.       -- The purpose of this function is to add SHORT_COMP_ARRAYs
  687.       -- returning a SHORT_COMP_ARRAY value.  
  688.       -- For SHORT_FLOAT_CLASS the array will be normalized and the BITS_SHIFTED
  689.       -- variable will be set to a value corresponding to the number
  690.       -- of bits the result array needed to be shifted to the left to
  691.       -- be normalized.  It is possible for BITS_SHIFTED to equal -1.
  692.       -- For INTEGER_CLASS the array will be checked for overflow.
  693.       RESULT : SHORT_COMP_ARRAY := LEFT;
  694.       C_RESULT : SHORT_COMPONENT_ARRAY := SHORT_ZERO_ARRAY;
  695.       C_LEFT : SHORT_COMPONENT_ARRAY := LEFT.COMPONENT_ARRAY;
  696.       C_RIGHT : SHORT_COMPONENT_ARRAY := RIGHT.COMPONENT_ARRAY;
  697.       SHIFT_BITS : INTEGER := 0;
  698.    begin
  699.  
  700.       -- Check for matching array types
  701.       if LEFT.CLASS_OF_ARRAY /= RIGHT.CLASS_OF_ARRAY then
  702.          raise MAE_INVALID_OPERATION;
  703.       end if;
  704.  
  705.       -- Loop over the array, adding adjacent components
  706.       for I in C_LEFT'range loop
  707.          C_RESULT(I) := C_LEFT(I) + C_RIGHT(I);
  708.       end loop;
  709.       RANGE_CHECK(C_RESULT);
  710.  
  711.       case RESULT.CLASS_OF_ARRAY is
  712.          when SHORT_FLOAT_CLASS =>
  713.             -- If the most signif comp is greater than the maximum
  714.             -- value divide the array by two.  This will make the
  715.             -- array normalized since the add operation would only
  716.             -- generate maximum value of (2 * BASE_COMP_VALUE) - 1.
  717.             if C_RESULT(C_RESULT'last) > MAX_COMP_VALUE then
  718.                DIVIDE_ARRAY_BY_TWO(C_RESULT);
  719.                SHIFT_BITS := -1;
  720.             else
  721.                -- Otherwise normalize by calling the routine
  722.                ARRAY_NORMALIZE(C_RESULT, SHIFT_BITS);
  723.             end if;
  724.             RESULT.COMPONENT_ARRAY := C_RESULT;
  725.             RESULT.BITS_SHIFTED := SHIFT_BITS;
  726.  
  727.          when INTEGER_CLASS =>
  728.             -- If the most signif comp is greater than the maximum
  729.             -- value it is an overflow.
  730.             if C_RESULT(C_RESULT'last) > MAX_COMP_VALUE then
  731.                raise MAE_INTEGER_OVERFLOW;
  732.             end if;
  733.             RESULT.COMPONENT_ARRAY := C_RESULT;
  734.             RESULT.BITS_SHIFTED := 0;
  735.  
  736.          when others =>
  737.             raise MAE_INVALID_OPERATION;
  738.  
  739.       end case;
  740.  
  741.       return RESULT;
  742.  
  743.    exception
  744.       when others =>
  745.          raise MAE_NUMERIC_ERROR;
  746.  
  747.    end "+";
  748.  
  749. -----------------------------
  750.  
  751.    function "-"    (LEFT,RIGHT : SHORT_COMP_ARRAY) return SHORT_COMP_ARRAY is
  752.       -- The purpose of this function is to subtract SHORT_COMP_ARRAYs
  753.       -- returning a SHORT_COMP_ARRAY value.  
  754.       -- ASSUME : LEFT >= RIGHT
  755.       RESULT : SHORT_COMP_ARRAY := LEFT;
  756.       C_RESULT : SHORT_COMPONENT_ARRAY := SHORT_ZERO_ARRAY;
  757.       C_LEFT : SHORT_COMPONENT_ARRAY := LEFT.COMPONENT_ARRAY;
  758.       C_RIGHT : SHORT_COMPONENT_ARRAY := RIGHT.COMPONENT_ARRAY;
  759.       SHIFT_BITS : INTEGER := 0;
  760.    begin
  761.  
  762.       if LEFT.CLASS_OF_ARRAY /= RIGHT.CLASS_OF_ARRAY then
  763.          raise MAE_INVALID_OPERATION;
  764.       end if;
  765.  
  766.       -- validate the assumption left >= right
  767.       if C_LEFT < C_RIGHT then
  768.          raise MAE_INVALID_OPERATION;
  769.       end if;
  770.  
  771.       -- Loop over the array, subtracting adjacent components
  772.       for I in C_LEFT'range loop
  773.          C_RESULT(I) := C_LEFT(I) - C_RIGHT(I);
  774.       end loop;
  775.       RANGE_CHECK(C_RESULT);
  776.  
  777.       case RESULT.CLASS_OF_ARRAY is
  778.          when SHORT_FLOAT_CLASS =>
  779.             -- Normalize by calling the routine
  780.             ARRAY_NORMALIZE(C_RESULT, SHIFT_BITS);
  781.             RESULT.COMPONENT_ARRAY := C_RESULT;
  782.             RESULT.BITS_SHIFTED := SHIFT_BITS;
  783.  
  784.          when INTEGER_CLASS =>
  785.             -- Just return the result, since the LEFT >= RIGHT
  786.             -- the result must be zero or positive.
  787.             RESULT.COMPONENT_ARRAY := C_RESULT;
  788.             RESULT.BITS_SHIFTED := 0;
  789.  
  790.          when others =>
  791.             raise MAE_INVALID_OPERATION;
  792.  
  793.       end case;
  794.  
  795.       return RESULT;
  796.  
  797.   exception
  798.      when others =>
  799.         raise MAE_NUMERIC_ERROR;
  800.    end "-";
  801.  
  802. -----------------------------
  803.  
  804.    function "*"    (LEFT,RIGHT : SHORT_COMP_ARRAY) return SHORT_COMP_ARRAY is
  805.       -- The purpose of this function is to multiply SHORT_COMP_ARRAYs
  806.       -- returning a SHORT_COMP_ARRAY value.  This requires much
  807.       -- range checking of the individual COMPs.
  808.       RESULT : SHORT_COMP_ARRAY := LEFT;
  809.       RESULT_LAST : constant INTEGER := SHORT_NUM_COMPS;
  810.       C_RESULT : LONG_COMPONENT_ARRAY := LONG_ZERO_ARRAY;
  811.       C_LEFT : SHORT_COMPONENT_ARRAY := LEFT.COMPONENT_ARRAY;
  812.       C_RIGHT : SHORT_COMPONENT_ARRAY := RIGHT.COMPONENT_ARRAY;
  813.       SHIFT_BITS : INTEGER := 0;
  814.       INDEX : INTEGER;
  815.    begin
  816.       -- Do the multiply by looping over the arrays
  817.  
  818.       -- loop over LEFT array
  819.       for I in C_LEFT'range loop
  820.          -- Zero check
  821.          if C_LEFT(I) /= 0 then
  822.             -- loop over RIGHT array
  823.             for J in C_RIGHT'range loop
  824.                -- Zero check
  825.                if C_RIGHT(J) /= 0 then
  826.                   -- Multiply the two COMPs
  827.                   INDEX := I + J - 1;
  828.                   C_RESULT(INDEX) := C_RESULT(INDEX) + (C_LEFT(I)*C_RIGHT(J));
  829.                end if;
  830.             end loop;
  831.             -- RANGE_CHECK the intermediate result
  832.             RANGE_CHECK(C_RESULT);
  833.          end if;
  834.       end loop;
  835.  
  836.       RESULT.BITS_SHIFTED := 0;
  837.       case RESULT.CLASS_OF_ARRAY is
  838.          -- Called by an MAE_INTEGER_TYPE      
  839.          when INTEGER_CLASS =>
  840.             -- Overflow condition if outside the range of the
  841.             -- input SHORT_COMP_ARRAY.
  842.             for I in RESULT_LAST+1 .. LONG_NUM_COMPS loop
  843.                if C_RESULT(I) /= 0 then
  844.                   raise MAE_INTEGER_OVERFLOW;
  845.                end if;
  846.             end loop;
  847.             RESULT.COMPONENT_ARRAY := C_RESULT(1 .. RESULT_LAST);
  848.  
  849.          when SHORT_FLOAT_CLASS =>
  850.             -- Normalize the result.
  851.             ARRAY_NORMALIZE(C_RESULT, SHIFT_BITS);
  852.             RESULT.COMPONENT_ARRAY :=
  853.                C_RESULT((C_RESULT'last-RESULT_LAST)+1 .. C_RESULT'last);
  854.             -- Check for rounding to even.
  855.             -- Look beyond the array for the rounding bits.
  856.             -- Because the rounding technique is
  857.                -- If round value is (0 <= x < .5), round down (no action)
  858.                -- If least signif bit is on (1,odd)
  859.                   -- then round up if round value is (.5 <= x < 1)
  860.                -- If least signif bit is off (0,even),
  861.                   -- then round up if round value is (.5 < x < 1),
  862.                   -- else round down if round value is (x = .5)
  863.  
  864.             -- Assume that a round up will occur if round value
  865.             -- is (.5 <= x < 1), then correct if the one case of a
  866.             -- round down occurs.
  867.             if C_RESULT(C_RESULT'last-RESULT_LAST) >=
  868.                                    BIT_VALUE(BIT_VALUE'first) then
  869.                -- the round value is (.5 <= x < 1), assume round up
  870.                RESULT.COMPONENT_ARRAY(1) := RESULT.COMPONENT_ARRAY(1) + 1;
  871.                -- check for the one round down case
  872.                if C_RESULT(C_RESULT'last-RESULT_LAST) = 
  873.                                    BIT_VALUE(BIT_VALUE'first) then
  874.                   -- Since we already added 1 to the least signif bit,
  875.                   -- check if the least signif bit is now 1
  876.                   -- (therefore it was zero).
  877.                   if (RESULT.COMPONENT_ARRAY(1) rem 2) = 1 then
  878.                      INDEX := (C_RESULT'last-RESULT_LAST)-1;
  879.                      -- Loop over the remaining components, if they are
  880.                      -- all zero then the round value equaled .5
  881.                      while C_RESULT(INDEX) = 0 loop
  882.                         INDEX := INDEX - 1;
  883.                         if INDEX = 0 then
  884.                            -- assumption incorrect, subtract 1 to correct
  885.                            -- the assumption.
  886.                            RESULT.COMPONENT_ARRAY(1) := 
  887.                                         RESULT.COMPONENT_ARRAY(1) - 1;
  888.                            exit;
  889.                         end if;
  890.                      end loop;
  891.                   end if;
  892.                end if;
  893.                -- Do an inline RANGE_CHECK.
  894.                -- next line should be INDEX := RESULT.COMPONENT_ARRAY'first;
  895.                INDEX := 1;
  896.                while RESULT.COMPONENT_ARRAY(INDEX) > MAX_COMP_VALUE loop
  897.                   -- The comp is oversized, the carry value will be positive.
  898.                   RESULT.COMPONENT_ARRAY(INDEX) := 0;
  899.                   INDEX := INDEX + 1;
  900.                   RESULT.COMPONENT_ARRAY(INDEX) := 
  901.                                   RESULT.COMPONENT_ARRAY(INDEX) + 1;
  902.                   -- If the 'impossible' carry to the most signif bit occurs
  903.                   -- then another normalization must occur
  904.                   if INDEX = RESULT_LAST then
  905.                      if RESULT.COMPONENT_ARRAY(INDEX) > MAX_COMP_VALUE then
  906.                         DIVIDE_ARRAY_BY_TWO(RESULT.COMPONENT_ARRAY);
  907.                         SHIFT_BITS := SHIFT_BITS - 1;
  908.                      end if;
  909.                   end if;
  910.                end loop;
  911.             end if;
  912.             RESULT.BITS_SHIFTED := SHIFT_BITS;
  913.  
  914.          when others =>
  915.             raise MAE_INVALID_OPERATION;
  916.  
  917.       end case;
  918.  
  919.       return RESULT;
  920.  
  921.    exception
  922.      when others =>
  923.         raise MAE_NUMERIC_ERROR;
  924.    end "*";
  925.  
  926. -----------------------------
  927.  
  928.    function "/"    (LEFT,RIGHT : SHORT_COMP_ARRAY) return SHORT_COMP_ARRAY is
  929.       -- The purpose of this function is to divide SHORT_COMP_ARRAYs
  930.       -- returning a SHORT_COMP_ARRAY value.  This requires much
  931.       -- range checking of the individual COMPs.
  932.       RESULT : SHORT_COMP_ARRAY := LEFT;
  933.       C_RESULT : SHORT_COMPONENT_ARRAY := SHORT_ZERO_ARRAY;
  934.       C_LEFT : SHORT_COMPONENT_ARRAY := LEFT.COMPONENT_ARRAY;
  935.       C_RIGHT : SHORT_COMPONENT_ARRAY := RIGHT.COMPONENT_ARRAY;
  936.       SHIFT_BITS : INTEGER := 0;
  937.       RESULT_SHIFT_BITS, LEFT_SHIFT_BITS, RIGHT_SHIFT_BITS : INTEGER := 0;
  938.       LEFT_MSC : constant INTEGER := C_LEFT'last;
  939.       R_COUNT : INTEGER;
  940.       INDEX, INDEX_BIT : INTEGER;
  941.    begin
  942.       -- If the divisor is zero, then there is an error
  943.       if C_RIGHT = SHORT_ZERO_ARRAY then
  944.          RESULT.COMPONENT_ARRAY := C_RESULT;
  945.          raise MAE_DIVIDE_BY_ZERO;
  946.       end if;
  947.  
  948.       -- Initialize variables by normalizing.  This is also done for
  949.       -- INTEGER_CLASS array to allow the same division operation code
  950.       -- for INTEGER_CLASS and SHORT_FLOAT_CLASS.  It works because a 
  951.       -- right shift with truncation is done on the array before returning.
  952.       ARRAY_NORMALIZE(C_LEFT, LEFT_SHIFT_BITS); 
  953.       ARRAY_NORMALIZE(C_RIGHT, RIGHT_SHIFT_BITS);
  954.  
  955.       -- Save shifting values to correct result before exiting
  956.       RESULT_SHIFT_BITS := (RIGHT_SHIFT_BITS - LEFT_SHIFT_BITS) + 1;
  957.  
  958.       -- Make C_RIGHT(RIGHT_MSC) less than the C_LEFT by dividing
  959.       -- C_RIGHT by 2. 
  960.       -- To make available the entire C_RESULT array for accuracy
  961.       -- and instead of updating the RIGHT_SHIFT_BITS variable 
  962.       -- by one, we will view the shift as a shift of the
  963.       -- LEFT_SHIFT_BITS by 1, since this equivalent and
  964.       -- LEFT_SHIFT_BITS is the changing variable in the loop.  
  965.       LEFT_SHIFT_BITS := 1;
  966.       DIVIDE_ARRAY_BY_TWO(C_RIGHT);
  967.  
  968.       -- This is the main loop for the division algorithm
  969.       -- The loop has three exit points.
  970.       loop
  971.          if RESULT.CLASS_OF_ARRAY = INTEGER_CLASS then
  972.             -- Check if the integer portion of the result
  973.             -- has been determined.
  974.             if LEFT_SHIFT_BITS > RESULT_SHIFT_BITS then
  975.                -- EXIT POINT ONE
  976.                   -- Integer divide has been completed
  977.                exit;
  978.             end if;
  979.          end if;
  980.  
  981.          R_COUNT := 0;
  982.          -- Loop over array subtracting the divisor from the
  983.          -- remaining dividend.  Since (divisor*4 > dividend),
  984.          -- the R_COUNT variable can be a maximum of 3
  985.          -- (after adding dividend if subtracted too much).
  986.          while C_LEFT(C_LEFT'last) >= C_RIGHT(C_RIGHT'last) loop
  987.             for J in C_LEFT'range loop
  988.               -- subtract RIGHT COMP from LEFT COMP
  989.               C_LEFT(J) := C_LEFT(J) - C_RIGHT(J);
  990.             end loop;
  991.             R_COUNT := R_COUNT + 1;
  992.             RANGE_CHECK(C_LEFT);
  993.          end loop;
  994.          -- May have subtracted too much
  995.          if C_LEFT(C_LEFT'last) < 0 then
  996.             for J in C_LEFT'range loop
  997.               -- add back the last subtraction
  998.               C_LEFT(J) := C_LEFT(J) + C_RIGHT(J);
  999.             end loop;
  1000.             R_COUNT := R_COUNT - 1;
  1001.             RANGE_CHECK(C_LEFT);
  1002.          end if;
  1003.  
  1004.          -- Locate the bit position to add the count to
  1005.          -- the result array.  Determine which component, INDEX,
  1006.          -- and the bit, INDEX_BIT, within that component.
  1007.          INDEX := C_RESULT'last - (LEFT_SHIFT_BITS / NO_COMP_BITS);
  1008.          INDEX_BIT := (LEFT_SHIFT_BITS rem NO_COMP_BITS) + 1;
  1009.  
  1010.          -- If the bit position is still with the array bounds,
  1011.          -- then add the value, continue,
  1012.          -- else add the value, RANGE_CHECK, exit.
  1013.          if INDEX > 0 then
  1014.             C_RESULT(INDEX) := C_RESULT(INDEX)+(R_COUNT*BIT_VALUE(INDEX_BIT));
  1015.          else
  1016.             if (INDEX = 0) then
  1017.                if ((INDEX_BIT = 1) and (R_COUNT = 3)) then
  1018.                   C_RESULT(C_RESULT'first) := C_RESULT(C_RESULT'first) + 2;
  1019.                elsif ((INDEX_BIT = 1) and (R_COUNT = 2)) or 
  1020.                      ((INDEX_BIT = 2) and (R_COUNT = 3)) then
  1021.                   C_RESULT(C_RESULT'first) := C_RESULT(C_RESULT'first) + 1;
  1022.                end if;
  1023.             end if;
  1024.             -- RANGE_CHECK the result.
  1025.             RANGE_CHECK(C_RESULT);
  1026.  
  1027.             -- EXIT POINT TWO
  1028.                -- The dividend has been shifted beyond significance.
  1029.             exit;
  1030.          end if;
  1031.  
  1032.          -- RANGE_CHECK the result.
  1033.          RANGE_CHECK(C_RESULT);
  1034.          -- NORMALIZE the remaining dividend.
  1035.          if C_LEFT = SHORT_ZERO_ARRAY then
  1036.             -- EXIT POINT THREE
  1037.                -- The dividend has been reduced to zero.
  1038.             exit;
  1039.          else
  1040.             ARRAY_NORMALIZE(C_LEFT, SHIFT_BITS);
  1041.             LEFT_SHIFT_BITS := LEFT_SHIFT_BITS + SHIFT_BITS;
  1042.          end if;
  1043.       end loop;
  1044.  
  1045.       case RESULT.CLASS_OF_ARRAY is
  1046.          when SHORT_FLOAT_CLASS =>
  1047.             -- shift the result back 
  1048.             ARRAY_NORMALIZE(C_RESULT, SHIFT_BITS);
  1049.             RESULT.COMPONENT_ARRAY := C_RESULT;
  1050.             RESULT.BITS_SHIFTED := SHIFT_BITS - RESULT_SHIFT_BITS;
  1051.  
  1052.          when INTEGER_CLASS =>
  1053.             -- if the result is less than one return zero
  1054.             if RESULT_SHIFT_BITS < 1 then
  1055.                RESULT.COMPONENT_ARRAY := SHORT_ZERO_ARRAY;
  1056.             -- else return the integer portion
  1057.             elsif RESULT_SHIFT_BITS <= SHORT_NUM_BITS then
  1058.                ARRAY_TRUNCATION_SHIFT_RIGHT(C_RESULT, 
  1059.                               (SHORT_NUM_BITS - RESULT_SHIFT_BITS));
  1060.             else
  1061.                raise MAE_IMPOSSIBLE;
  1062.             end if;
  1063.             RESULT.COMPONENT_ARRAY := C_RESULT;
  1064.  
  1065.          when others =>
  1066.             raise MAE_INVALID_OPERATION;
  1067.  
  1068.       end case;
  1069.  
  1070.       return RESULT;
  1071.  
  1072.    exception
  1073.       when others =>
  1074.          raise MAE_NUMERIC_ERROR;
  1075.    end "/";
  1076.  
  1077. -----------------------------
  1078.  
  1079.    function "rem"  (LEFT,RIGHT : SHORT_COMP_ARRAY) return SHORT_COMP_ARRAY is
  1080.       -- The purpose of this function is to find the remainder
  1081.       -- of the LEFT from the RIGHT SHORT_COMP_ARRAY
  1082.       -- returning a SHORT_COMP_ARRAY value.
  1083.       RESULT : SHORT_COMP_ARRAY;
  1084.    begin
  1085.       if LEFT.CLASS_OF_ARRAY /= RIGHT.CLASS_OF_ARRAY then
  1086.          raise MAE_INVALID_OPERATION;
  1087.       end if;
  1088.  
  1089.       case LEFT.CLASS_OF_ARRAY is
  1090.  
  1091.          when INTEGER_CLASS =>
  1092.             -- Apply the definition of the remainder
  1093.             RESULT := LEFT - ((LEFT / RIGHT) * RIGHT);            
  1094.  
  1095.          when others =>
  1096.             raise MAE_INVALID_OPERATION;
  1097.  
  1098.       end case;
  1099.  
  1100.       return RESULT;
  1101.  
  1102.    exception
  1103.       when others =>
  1104.          raise MAE_NUMERIC_ERROR;
  1105.  
  1106.    end "rem";
  1107.  
  1108. -------------------------------------------------------------------
  1109.  
  1110.    function "+"    (LEFT,RIGHT : LONG_COMP_ARRAY) return LONG_COMP_ARRAY is
  1111.       -- The purpose of this function is to add LONG_COMP_ARRAYs
  1112.       -- returning a LONG_COMP_ARRAY value.
  1113.       -- For LONG_FLOAT_CLASS the array will be normalized and the BITS_SHIFTED
  1114.       -- variable will be set to a value corresponding to the number
  1115.       -- of bits the result array needed to be shifted to the left to
  1116.       -- be normalized.  It is possible for BITS_SHIFTED to equal -1.
  1117.       RESULT : LONG_COMP_ARRAY := LEFT;
  1118.       C_RESULT : LONG_COMPONENT_ARRAY := LONG_ZERO_ARRAY;
  1119.       C_LEFT : LONG_COMPONENT_ARRAY := LEFT.COMPONENT_ARRAY;
  1120.       C_RIGHT : LONG_COMPONENT_ARRAY := RIGHT.COMPONENT_ARRAY;
  1121.       SHIFT_BITS : INTEGER := 0;
  1122.    begin
  1123.  
  1124.       if LEFT.CLASS_OF_ARRAY /= RIGHT.CLASS_OF_ARRAY then
  1125.          raise MAE_INVALID_OPERATION;
  1126.       end if;
  1127.  
  1128.       -- Loop over the array, adding adjacent components.
  1129.       for I in C_LEFT'range loop
  1130.          C_RESULT(I) := C_LEFT(I) + C_RIGHT(I);
  1131.       end loop;
  1132.       RANGE_CHECK(C_RESULT);
  1133.  
  1134.       case RESULT.CLASS_OF_ARRAY is
  1135.          when LONG_FLOAT_CLASS =>
  1136.             -- If the most signif comp is greater than the  maximum
  1137.             -- value divide the array by two.  This will make the
  1138.             -- array normalized since the add operation would only
  1139.             -- generate a maximum value of (2 * BASE_COMP_VALUE) - 1.
  1140.             if C_RESULT(C_RESULT'last) > MAX_COMP_VALUE then
  1141.                DIVIDE_ARRAY_BY_TWO(C_RESULT);
  1142.                SHIFT_BITS := -1;
  1143.             else
  1144.                -- Otherwise normalize by calling the routine.
  1145.                ARRAY_NORMALIZE(C_RESULT, SHIFT_BITS);
  1146.             end if;
  1147.             RESULT.COMPONENT_ARRAY := C_RESULT;
  1148.             RESULT.BITS_SHIFTED := SHIFT_BITS;
  1149.  
  1150.          when others =>
  1151.             raise MAE_INVALID_OPERATION;
  1152.  
  1153.       end case;
  1154.  
  1155.       return RESULT;
  1156.  
  1157.    exception
  1158.       when others =>
  1159.          raise MAE_NUMERIC_ERROR;
  1160.  
  1161.    end "+";
  1162.  
  1163. -----------------------------
  1164.  
  1165.    function "-"    (LEFT,RIGHT : LONG_COMP_ARRAY) return LONG_COMP_ARRAY is
  1166.       -- The purpose of this function is to subtract LONG_COMP_ARRAYs
  1167.       -- returning a LONG_COMP_ARRAY value.  
  1168.       -- ASSUME : LEFT >= RIGHT
  1169.       RESULT : LONG_COMP_ARRAY := LEFT;
  1170.       C_RESULT : LONG_COMPONENT_ARRAY := LONG_ZERO_ARRAY;
  1171.       C_LEFT : LONG_COMPONENT_ARRAY := LEFT.COMPONENT_ARRAY;
  1172.       C_RIGHT : LONG_COMPONENT_ARRAY := RIGHT.COMPONENT_ARRAY;
  1173.       SHIFT_BITS : INTEGER := 0;
  1174.  
  1175.    begin
  1176.  
  1177.       if LEFT.CLASS_OF_ARRAY /= RIGHT.CLASS_OF_ARRAY then
  1178.          raise MAE_INVALID_OPERATION;
  1179.       end if;
  1180.  
  1181.       -- validate the assumption left >= right
  1182.       if C_LEFT < C_RIGHT then
  1183.          raise MAE_INVALID_OPERATION;
  1184.       end if;
  1185.  
  1186.       -- Loop over the array, subtracting adjacent components.
  1187.       for I in C_LEFT'range loop
  1188.          C_RESULT(I) := C_LEFT(I) - C_RIGHT(I);
  1189.       end loop;
  1190.       RANGE_CHECK(C_RESULT);
  1191.  
  1192.       case RESULT.CLASS_OF_ARRAY is
  1193.          when LONG_FLOAT_CLASS =>
  1194.             -- Normalized by calling the routine
  1195.             ARRAY_NORMALIZE(C_RESULT, SHIFT_BITS);
  1196.             RESULT.COMPONENT_ARRAY := C_RESULT;
  1197.             RESULT.BITS_SHIFTED := SHIFT_BITS;
  1198.  
  1199.          when others =>
  1200.             raise MAE_INVALID_OPERATION;
  1201.  
  1202.       end case;
  1203.  
  1204.       return RESULT;
  1205.  
  1206.    exception
  1207.       when others =>
  1208.          raise MAE_NUMERIC_ERROR;
  1209.    end "-";
  1210.  
  1211. -----------------------------
  1212.  
  1213.    function "*"    (LEFT,RIGHT : LONG_COMP_ARRAY) return LONG_COMP_ARRAY is
  1214.       -- The purpose of this function is to multiply LONG_COMP_ARRAYs
  1215.       -- returning a LONG_COMP_ARRAY value.  This requires much
  1216.       -- range checking of the individual COMPs.
  1217.       RESULT : LONG_COMP_ARRAY := LEFT;
  1218.       RESULT_LAST : constant INTEGER := LONG_NUM_COMPS;
  1219.       C_RESULT : EXTRA_COMPONENT_ARRAY := EXTRA_ZERO_ARRAY;
  1220.       C_LEFT : LONG_COMPONENT_ARRAY := LEFT.COMPONENT_ARRAY;
  1221.       C_RIGHT : LONG_COMPONENT_ARRAY := RIGHT.COMPONENT_ARRAY;
  1222.       SHIFT_BITS : INTEGER := 0;
  1223.       INDEX : INTEGER;
  1224.    begin
  1225.       -- Do the multiply by looping over the arrays
  1226.  
  1227.       -- loop over LEFT array
  1228.       for I in C_LEFT'range loop
  1229.          -- Zero check
  1230.          if C_LEFT(I) /= 0 then
  1231.             -- loop over RIGHT array
  1232.             for J in C_RIGHT'range loop
  1233.                -- Zero check
  1234.                if C_RIGHT(J) /= 0 then
  1235.                   -- Multiply the two COMPs
  1236.                   INDEX := I + J - 1;
  1237.                   C_RESULT(INDEX) := C_RESULT(INDEX) + (C_LEFT(I)*C_RIGHT(J));
  1238.                end if;
  1239.             end loop;
  1240.             -- RANGE_CHECK the intermediate result
  1241.             RANGE_CHECK(C_RESULT);
  1242.          end if;
  1243.       end loop;
  1244.  
  1245.       RESULT.BITS_SHIFTED := 0;
  1246.       case RESULT.CLASS_OF_ARRAY is
  1247.          when LONG_FLOAT_CLASS =>
  1248.             -- Normalize the result.
  1249.             ARRAY_NORMALIZE(C_RESULT, SHIFT_BITS);
  1250.             RESULT.COMPONENT_ARRAY :=
  1251.                C_RESULT((C_RESULT'last-RESULT_LAST)+1 .. C_RESULT'last);
  1252.             -- Check for rounding to even.
  1253.             -- Look beyond the array for the rounding bits.
  1254.             -- Because the rounding technique is
  1255.                -- If round value is (0 <= x < .5), round down (no action)
  1256.                -- If least signif bit is on (1,odd)
  1257.                   -- then round up if round value is (.5 <= x < 1)
  1258.                -- If least signif bit is off (0,even),
  1259.                   -- then round up if round value is (.5 < x < 1),
  1260.                   -- else round down if round value is (x = .5)
  1261.  
  1262.             -- Assume that a round up will occur if round value
  1263.             -- is (.5 <= x < 1), then correct if the one case of a
  1264.             -- round down occurs
  1265.             if C_RESULT(C_RESULT'last-RESULT_LAST) >=
  1266.                                    BIT_VALUE(BIT_VALUE'first) then
  1267.                -- The round value is (.5 <= x < 1), assume round up
  1268.                RESULT.COMPONENT_ARRAY(1) := RESULT.COMPONENT_ARRAY(1) + 1;
  1269.                -- check for the one round down case
  1270.                if C_RESULT(C_RESULT'last-RESULT_LAST) = 
  1271.                                    BIT_VALUE(BIT_VALUE'first) then
  1272.                   -- since we already added 1 to the least signif bit,
  1273.                   -- check if the least signif bit is now 1
  1274.                   -- (therefore it was zero).
  1275.                   if (RESULT.COMPONENT_ARRAY(1) rem 2) = 1 then
  1276.                      INDEX := (C_RESULT'last-RESULT_LAST)-1;
  1277.                      -- Loop over the remaining components, if they are
  1278.                      -- all zero then the round value equaled .5
  1279.                      while C_RESULT(INDEX) = 0 loop
  1280.                         INDEX := INDEX - 1;
  1281.                         if INDEX = 0 then
  1282.                            -- assumption incorrect, subtract 1 to correct
  1283.                            -- the assumption.
  1284.                            RESULT.COMPONENT_ARRAY(1) := 
  1285.                                         RESULT.COMPONENT_ARRAY(1) - 1;
  1286.                            exit;
  1287.                         end if;
  1288.                      end loop;
  1289.                   end if;
  1290.                end if;
  1291.                -- Do an inline RANGE_CHECK.
  1292.                -- next line should be INDEX := RESULT.COMPONENT_ARRAY'first;
  1293.                INDEX := 1;
  1294.                while RESULT.COMPONENT_ARRAY(INDEX) > MAX_COMP_VALUE loop
  1295.                   -- The comp is oversized, the carry value will be positive.
  1296.                   RESULT.COMPONENT_ARRAY(INDEX) := 0;
  1297.                   INDEX := INDEX + 1;
  1298.                   RESULT.COMPONENT_ARRAY(INDEX) := 
  1299.                                      RESULT.COMPONENT_ARRAY(INDEX) + 1;
  1300.                   -- If the 'impossible' carry to the most signif bit occurs
  1301.                   -- then another normalization must occur
  1302.                   if INDEX = RESULT_LAST then
  1303.                      if RESULT.COMPONENT_ARRAY(INDEX) > MAX_COMP_VALUE then
  1304.                         DIVIDE_ARRAY_BY_TWO(RESULT.COMPONENT_ARRAY);
  1305.                         SHIFT_BITS := SHIFT_BITS - 1;
  1306.                      end if;
  1307.                   end if;
  1308.                end loop;
  1309.             end if;
  1310.             RESULT.BITS_SHIFTED := SHIFT_BITS;
  1311.  
  1312.          when others =>
  1313.             raise MAE_INVALID_OPERATION;
  1314.  
  1315.       end case;
  1316.  
  1317.       return RESULT;
  1318.  
  1319.    exception
  1320.       when others =>
  1321.          raise MAE_NUMERIC_ERROR;
  1322.    end "*";
  1323.  
  1324. -----------------------------
  1325.  
  1326.    function "/"    (LEFT,RIGHT : LONG_COMP_ARRAY) return LONG_COMP_ARRAY is
  1327.       -- The purpose of this function is to divide LONG_COMP_ARRAYs
  1328.       -- returning a LONG_COMP_ARRAY value.  This requires much
  1329.       -- range checking of the individual COMPs.
  1330.       RESULT : LONG_COMP_ARRAY := LEFT;
  1331.       C_RESULT : LONG_COMPONENT_ARRAY := LONG_ZERO_ARRAY;
  1332.       C_LEFT : LONG_COMPONENT_ARRAY := LEFT.COMPONENT_ARRAY;
  1333.       C_RIGHT : LONG_COMPONENT_ARRAY := RIGHT.COMPONENT_ARRAY;
  1334.       SHIFT_BITS : INTEGER := 0;
  1335.       RESULT_SHIFT_BITS, LEFT_SHIFT_BITS, RIGHT_SHIFT_BITS : INTEGER := 0;
  1336.       LEFT_MSC : constant INTEGER := C_LEFT'last;
  1337.       R_COUNT : INTEGER;
  1338.       INDEX, INDEX_BIT : INTEGER;
  1339.    begin
  1340.       -- If the divisor is zero, then there is an error.
  1341.       if C_RIGHT = LONG_ZERO_ARRAY then
  1342.          RESULT.COMPONENT_ARRAY := C_RESULT;
  1343.          raise MAE_DIVIDE_BY_ZERO;
  1344.       end if;
  1345.  
  1346.       -- Initialize variables by normalizing.
  1347.       ARRAY_NORMALIZE(C_LEFT, LEFT_SHIFT_BITS); 
  1348.       ARRAY_NORMALIZE(C_RIGHT, RIGHT_SHIFT_BITS);
  1349.  
  1350.       -- Save shifting values to correct result before exiting.
  1351.       RESULT_SHIFT_BITS := (RIGHT_SHIFT_BITS - LEFT_SHIFT_BITS) + 1;
  1352.  
  1353.       -- Make C_RIGHT(RIGHT_MSC) less than the C_LEFT by dividing
  1354.       -- C_RIGHT by 2. 
  1355.       -- To make available the entire C_RESULT array for accuracy
  1356.       -- and instead of updating the RIGHT_SHIFT_BITS variable 
  1357.       -- by one, we will view the shift as a shift of the
  1358.       -- LEFT_SHIFT_BITS by 1, since this equivalent and
  1359.       -- LEFT_SHIFT_BITS is the changing variable in the loop.  
  1360.       LEFT_SHIFT_BITS := 1;
  1361.       DIVIDE_ARRAY_BY_TWO(C_RIGHT);
  1362.  
  1363.       -- This is the main loop for the division algorithm
  1364.       -- The loop has two exit points.
  1365.       loop
  1366.          R_COUNT := 0;
  1367.          -- Loop over array subtracing the divisor from the
  1368.          -- remaining dividend.  Since (divisor*4 > dividend),
  1369.          -- the R_COUNT variable can be a maximum of 3
  1370.          -- (after adding dividend if subtracted too much).
  1371.          while C_LEFT(C_LEFT'last) >= C_RIGHT(C_RIGHT'last) loop
  1372.             for J in C_LEFT'range loop
  1373.               -- subtract RIGHT COMP from LEFT COMP
  1374.               C_LEFT(J) := C_LEFT(J) - C_RIGHT(J);
  1375.             end loop;
  1376.             R_COUNT := R_COUNT + 1;
  1377.             RANGE_CHECK(C_LEFT);
  1378.          end loop;
  1379.          -- May have subtracted too much
  1380.          if C_LEFT(C_LEFT'last) < 0 then
  1381.             for J in C_LEFT'range loop
  1382.               -- add back the last subtraction
  1383.               C_LEFT(J) := C_LEFT(J) + C_RIGHT(J);
  1384.             end loop;
  1385.             R_COUNT := R_COUNT - 1;
  1386.             RANGE_CHECK(C_LEFT);
  1387.          end if;
  1388.  
  1389.          -- Locate bit position to add the count to 
  1390.          -- the result array.  Determine which component, INDEX,
  1391.          -- and the bit, INDEX_BIT, within that component.
  1392.          INDEX := C_RESULT'last - (LEFT_SHIFT_BITS / NO_COMP_BITS);
  1393.          INDEX_BIT := (LEFT_SHIFT_BITS rem NO_COMP_BITS) + 1;
  1394.  
  1395.          -- If the bit position os still within the array bounds,
  1396.          -- then add the value, continue,
  1397.          -- else add the value, RANGE_CHECK, exit.
  1398.          if INDEX > 0 then
  1399.             C_RESULT(INDEX) := C_RESULT(INDEX)+(R_COUNT*BIT_VALUE(INDEX_BIT));
  1400.          else
  1401.             if (INDEX = 0) then
  1402.                if ((INDEX_BIT = 1) and (R_COUNT = 3)) then
  1403.                   C_RESULT(C_RESULT'first) := C_RESULT(C_RESULT'first) + 2;
  1404.                elsif ((INDEX_BIT = 1) and (R_COUNT = 2)) or 
  1405.                      ((INDEX_BIT = 2) and (R_COUNT = 3)) then
  1406.                   C_RESULT(C_RESULT'first) := C_RESULT(C_RESULT'first) + 1;
  1407.                end if;
  1408.             end if;
  1409.             -- RANGE_CHECK the result.
  1410.             RANGE_CHECK(C_RESULT);
  1411.  
  1412.             -- EXIT POINT TWO
  1413.                -- The dividend has been shifted beyond significance.
  1414.             exit;
  1415.          end if;
  1416.  
  1417.          -- RANGE_CHECK the result.
  1418.          RANGE_CHECK(C_RESULT);
  1419.          -- NORMALIZE the remaining dividend.
  1420.          if C_LEFT = LONG_ZERO_ARRAY then
  1421.             -- EXIT POINT THREE
  1422.                -- The dividend has been reduced to zero.
  1423.             exit;
  1424.          else
  1425.             ARRAY_NORMALIZE(C_LEFT, SHIFT_BITS);
  1426.             LEFT_SHIFT_BITS := LEFT_SHIFT_BITS + SHIFT_BITS;
  1427.          end if;
  1428.       end loop;
  1429.  
  1430.       case RESULT.CLASS_OF_ARRAY is
  1431.          when LONG_FLOAT_CLASS =>
  1432.             -- shift the result back 
  1433.             ARRAY_NORMALIZE(C_RESULT, SHIFT_BITS);
  1434.             RESULT.COMPONENT_ARRAY := C_RESULT;
  1435.             RESULT.BITS_SHIFTED := SHIFT_BITS - RESULT_SHIFT_BITS;
  1436.  
  1437.          when others =>
  1438.             raise MAE_INVALID_OPERATION;
  1439.  
  1440.       end case;
  1441.  
  1442.       return RESULT;
  1443.  
  1444.    exception
  1445.       when others =>
  1446.          raise MAE_NUMERIC_ERROR;
  1447.    end "/";
  1448.  
  1449.  
  1450. -------------------------------------------------------------------
  1451. -- The body of the package
  1452. --
  1453. begin
  1454.    -- the initializing of the bit position value array
  1455.    for I in BIT_VALUE'first .. BIT_VALUE'last loop
  1456.       BIT_VALUE(I) := 2**(BIT_VALUE'last - I);
  1457.    end loop;
  1458. end MAE_BASIC_OPERATIONS;
  1459.  
  1460. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  1461. --maeint.txt
  1462. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  1463. -------------------------------------------------------------------------------
  1464. --                                                                           --
  1465. --             Emulation of Machine Arithmetic - a WIS Ada Tool              --
  1466. --                                                                           --
  1467. --                         Ada Technology Group                              --
  1468. --                         SYSCON Corporation                                --
  1469. --                         3990 Sherman Street                               --
  1470. --                         San Diego, CA. 92110                              --
  1471. --                                                                           --
  1472. --                        John Long & John Reddan                            --
  1473. --                                                                           --
  1474. -------------------------------------------------------------------------------
  1475.  
  1476. with MAE_BASIC_OPERATIONS; use MAE_BASIC_OPERATIONS;
  1477.  
  1478. package MAE_INTEGER is
  1479. -------------------------------------------------------------------
  1480.  
  1481. -- The purpose of this package is to emulate target machine
  1482. -- integer arithmetic on host machines with 16-bit or larger 
  1483. -- words.
  1484. --
  1485. -- The range of the supported type is as follows:
  1486. --
  1487. --    TARGET_INTEGER
  1488. --       range of -2**MAE_BASIC_OPERATIONS.TARGET_INTEGER_NUM_BITS
  1489. --                        to 
  1490. --                 2**MAE_BASIC_OPERATIONS.TARGET_INTEGER_NUM_BITS-1
  1491. --
  1492. -- Any errors which occur during use of the arithmetic and
  1493. -- boolean functions defined below will result in the
  1494. -- raising of the exception "MAE_NUMERIC_ERROR".  
  1495.  
  1496. --
  1497. -- Visible operations with MAE_INTEGER_TYPE
  1498. --
  1499.    type MAE_INTEGER_TYPE is private;
  1500.  
  1501.    -- The defined operators for this type are as follows:
  1502.  
  1503.    -- predefined system function "=" and function "/="
  1504.    function "<"    (LEFT, RIGHT : MAE_INTEGER_TYPE) return BOOLEAN;
  1505.    function "<="   (LEFT, RIGHT : MAE_INTEGER_TYPE) return BOOLEAN;
  1506.    function ">"    (LEFT, RIGHT : MAE_INTEGER_TYPE) return BOOLEAN;
  1507.    function ">="   (LEFT, RIGHT : MAE_INTEGER_TYPE) return BOOLEAN;
  1508.  
  1509.    function "+"    (RIGHT : MAE_INTEGER_TYPE) return MAE_INTEGER_TYPE;
  1510.    function "-"    (RIGHT : MAE_INTEGER_TYPE) return MAE_INTEGER_TYPE;
  1511.    function "abs"  (RIGHT : MAE_INTEGER_TYPE) return MAE_INTEGER_TYPE;
  1512.  
  1513.    function "+"    (LEFT,RIGHT : MAE_INTEGER_TYPE) return MAE_INTEGER_TYPE;
  1514.    function "-"    (LEFT,RIGHT : MAE_INTEGER_TYPE) return MAE_INTEGER_TYPE;
  1515.    function "*"    (LEFT,RIGHT : MAE_INTEGER_TYPE) return MAE_INTEGER_TYPE;
  1516.    function "/"    (LEFT,RIGHT : MAE_INTEGER_TYPE) return MAE_INTEGER_TYPE;
  1517.    function "rem"  (LEFT,RIGHT : MAE_INTEGER_TYPE) return MAE_INTEGER_TYPE;
  1518.    function "mod"  (LEFT,RIGHT : MAE_INTEGER_TYPE) return MAE_INTEGER_TYPE;
  1519.  
  1520.    function "**"   (LEFT : MAE_INTEGER_TYPE; RIGHT : INTEGER)
  1521.                        return MAE_INTEGER_TYPE;
  1522.  
  1523.    function MAE_INTEGER_TYPE_VALUE(STRING_PIC : STRING)
  1524.                                       return MAE_INTEGER_TYPE;
  1525.  
  1526.    function MAE_INTEGER_TYPE_IMAGE(STORE_PIC : MAE_INTEGER_TYPE)
  1527.                                       return STRING;
  1528.  
  1529.    procedure GET (FROM : in STRING;
  1530.                   ITEM : out MAE_INTEGER_TYPE;
  1531.                   LAST : out POSITIVE);
  1532.  
  1533.    procedure PUT (TO : out STRING;
  1534.                   ITEM : in MAE_INTEGER_TYPE;
  1535.                   BASE : in NUMBER_BASE := DEFAULT_BASE);
  1536.  
  1537.    function TARGET_INTEGER_FIRST return MAE_INTEGER_TYPE;
  1538.  
  1539.    function TARGET_INTEGER_LAST return MAE_INTEGER_TYPE;
  1540.  
  1541. -------------------------------------------------------------------
  1542. private
  1543.  
  1544. -- The declaration of the next variable is to allow
  1545. -- the record declaration under the Telesoft version 1.5 compiler.
  1546. -- A better declaration would allow the COMP_ARRAY range to be
  1547. -- (1 .. BITS_TO_COMPS(NO_OF_BITS).
  1548.  
  1549.    type MAE_INTEGER_TYPE is
  1550.       record
  1551.          SIGN : SIGN_TYPE := POS_SIGN;
  1552.          COMPS : SHORT_COMP_ARRAY := INTEGER_COMP_ARRAY;
  1553.       end record;
  1554.  
  1555. -------------------------------------------------------------------
  1556. end MAE_INTEGER;
  1557.  
  1558. -------------------------------------------------------------------
  1559. -------------------------------------------------------------------
  1560. with TEXT_IO;
  1561. with MAE_BASIC_OPERATIONS; use MAE_BASIC_OPERATIONS;
  1562.  
  1563. package body MAE_INTEGER is
  1564. -------------------------------------------------------------------
  1565. -- The purpose of this package is to emulate 36 bit machine
  1566. -- arithmetic on a 32 bit host machine for 36 bit integer
  1567. -- numbers.  The range of the supported type is as follows:
  1568. --
  1569. --    Integer
  1570. --       range of -2**35 to 2**35-1
  1571. --
  1572. -- 
  1573. -------------------------------------------------------------------
  1574. -- Local exception names for better tracing
  1575. --
  1576.    MAE_FORMAT_ERROR : EXCEPTION;
  1577.    DATA_ERROR : EXCEPTION;
  1578.    LAYOUT_ERROR : EXCEPTION;
  1579.  
  1580. -------------------------------------------------------------------
  1581. -- Constants for local functions and procedures
  1582. --
  1583. -- Once again the declaration of variables is affect by the
  1584. -- Telesoft 1.5 compiler.  The better declaration would use
  1585. -- the 'range, 'first, and 'last attributes for initialization.
  1586. -- The intialization of the digits ONE .. TEN are in the
  1587. -- body(bottom) of this package.
  1588.  
  1589.    ZERO : SHORT_COMP_ARRAY := INTEGER_COMP_ARRAY;
  1590.    ONE : SHORT_COMP_ARRAY := INTEGER_COMP_ARRAY;
  1591.    TWO : SHORT_COMP_ARRAY := INTEGER_COMP_ARRAY;
  1592.    THREE : SHORT_COMP_ARRAY := INTEGER_COMP_ARRAY;
  1593.    FOUR : SHORT_COMP_ARRAY := INTEGER_COMP_ARRAY;
  1594.    FIVE : SHORT_COMP_ARRAY := INTEGER_COMP_ARRAY;
  1595.    SIX : SHORT_COMP_ARRAY := INTEGER_COMP_ARRAY;
  1596.    SEVEN : SHORT_COMP_ARRAY := INTEGER_COMP_ARRAY;
  1597.    EIGHT : SHORT_COMP_ARRAY := INTEGER_COMP_ARRAY;
  1598.    NINE : SHORT_COMP_ARRAY := INTEGER_COMP_ARRAY;
  1599.    TEN : SHORT_COMP_ARRAY := INTEGER_COMP_ARRAY;
  1600.    THOUSAND : SHORT_COMP_ARRAY := INTEGER_COMP_ARRAY;
  1601.  
  1602.    MAE_INTEGER_ONE : MAE_INTEGER_TYPE;
  1603.    MAE_INTEGER_TWO : MAE_INTEGER_TYPE;
  1604.  
  1605.    MAE_INTEGER_FIRST : MAE_INTEGER_TYPE;
  1606.    MAE_INTEGER_LAST : MAE_INTEGER_TYPE;
  1607.  
  1608.    TWO_THREE : constant INTEGER := 2**3;
  1609.    TWO_THREE_LESS_ONE : constant INTEGER := (2**3)-1;
  1610.    TWO_TWO : constant INTEGER := 2**2;
  1611.    TWO_TWO_LESS_ONE : constant INTEGER := (2**2)-1;
  1612.  
  1613. -------------------------------------------------------------------
  1614. -- Visible operations with MAE_INTEGER_TYPE
  1615. --
  1616.    function TARGET_INTEGER_FIRST return MAE_INTEGER_TYPE is
  1617.    begin
  1618.       return MAE_INTEGER_FIRST;
  1619.    end TARGET_INTEGER_FIRST;
  1620.  
  1621. ------------------------------
  1622.  
  1623.    function TARGET_INTEGER_LAST return MAE_INTEGER_TYPE is
  1624.    begin
  1625.       return MAE_INTEGER_LAST;
  1626.    end TARGET_INTEGER_LAST;
  1627.  
  1628. ------------------------------
  1629.  
  1630.    -- predefined system functions : function "=" and function "/="
  1631.  
  1632. ------------------------------
  1633.  
  1634.    function "<"    (LEFT, RIGHT : MAE_INTEGER_TYPE) return BOOLEAN is
  1635.       -- Resolve the comparision by, first checking the signs, then
  1636.       -- checking the component arrays.
  1637.    begin
  1638.       case LEFT.SIGN is
  1639.          when POS_SIGN =>
  1640.             if RIGHT.SIGN = POS_SIGN then
  1641.                -- both are positive
  1642.                return (LEFT.COMPS.COMPONENT_ARRAY < RIGHT.COMPS.COMPONENT_ARRAY);
  1643.             else
  1644.                -- left is positive, right is negative
  1645.                return FALSE;
  1646.             end if;
  1647.          when NEG_SIGN =>
  1648.             if RIGHT.SIGN = NEG_SIGN then
  1649.                -- both are negative
  1650.                return (LEFT.COMPS.COMPONENT_ARRAY > RIGHT.COMPS.COMPONENT_ARRAY);
  1651.             else
  1652.                -- left is negative, right is positive
  1653.                return TRUE;
  1654.             end if;
  1655.       end case;
  1656.  
  1657.    exception
  1658.       when others =>
  1659.          raise MAE_NUMERIC_ERROR;
  1660.  
  1661.    end "<";
  1662.  
  1663. ------------------------------
  1664.  
  1665.    function "<="   (LEFT, RIGHT : MAE_INTEGER_TYPE) return BOOLEAN is
  1666.       -- Resolve the comparision by, first checking the signs, then
  1667.       -- checking the component arrays.
  1668.    begin
  1669.       case LEFT.SIGN is
  1670.          when POS_SIGN =>
  1671.             if RIGHT.SIGN = POS_SIGN then
  1672.                -- both are positive
  1673.                return (LEFT.COMPS.COMPONENT_ARRAY <= RIGHT.COMPS.COMPONENT_ARRAY);
  1674.             else
  1675.                -- left is positive, right is negative
  1676.                return FALSE;
  1677.             end if;
  1678.          when NEG_SIGN =>
  1679.             if RIGHT.SIGN = NEG_SIGN then
  1680.                -- both are negative
  1681.                return (LEFT.COMPS.COMPONENT_ARRAY >= RIGHT.COMPS.COMPONENT_ARRAY);
  1682.             else
  1683.                -- left is negative, right is positive
  1684.                return TRUE;
  1685.             end if;
  1686.       end case;
  1687.  
  1688.    exception
  1689.       when others =>
  1690.          raise MAE_NUMERIC_ERROR;
  1691.  
  1692.    end "<=";
  1693.  
  1694. ------------------------------
  1695.  
  1696.    function ">"    (LEFT, RIGHT : MAE_INTEGER_TYPE) return BOOLEAN is
  1697.       -- Resolve the comparision by, first checking the signs, then
  1698.       -- checking the component arrays.
  1699.    begin
  1700.       case LEFT.SIGN is
  1701.          when POS_SIGN =>
  1702.             if RIGHT.SIGN = POS_SIGN then
  1703.                -- both are positive
  1704.                return (LEFT.COMPS.COMPONENT_ARRAY > RIGHT.COMPS.COMPONENT_ARRAY);
  1705.             else
  1706.                -- left is positive, right is negative
  1707.                return TRUE;
  1708.             end if;
  1709.          when NEG_SIGN =>
  1710.             if RIGHT.SIGN = NEG_SIGN then
  1711.                -- both are negative
  1712.                return (LEFT.COMPS.COMPONENT_ARRAY < RIGHT.COMPS.COMPONENT_ARRAY);
  1713.             else
  1714.                -- left is negative, right is positive
  1715.                return FALSE;
  1716.             end if;
  1717.       end case;
  1718.  
  1719.    exception
  1720.       when others =>
  1721.          raise MAE_NUMERIC_ERROR;
  1722.  
  1723.    end ">";
  1724.  
  1725. ------------------------------
  1726.  
  1727.    function ">="   (LEFT, RIGHT : MAE_INTEGER_TYPE) return BOOLEAN is
  1728.       -- Resolve the comparision by, first checking the signs, then
  1729.       -- checking the component arrays.
  1730.    begin
  1731.       case LEFT.SIGN is
  1732.          when POS_SIGN =>
  1733.             if RIGHT.SIGN = POS_SIGN then
  1734.                -- both are positive
  1735.                return (LEFT.COMPS.COMPONENT_ARRAY >= RIGHT.COMPS.COMPONENT_ARRAY);
  1736.             else
  1737.                -- left is positive, right is negative
  1738.                return TRUE;
  1739.             end if;
  1740.          when NEG_SIGN =>
  1741.             if RIGHT.SIGN = NEG_SIGN then
  1742.                -- both are negative
  1743.                return (LEFT.COMPS.COMPONENT_ARRAY <= RIGHT.COMPS.COMPONENT_ARRAY);
  1744.             else
  1745.                -- left is negative, right is positive
  1746.                return FALSE;
  1747.             end if;
  1748.       end case;
  1749.  
  1750.    exception
  1751.       when others =>
  1752.          raise MAE_NUMERIC_ERROR;
  1753.  
  1754.    end ">=";
  1755.  
  1756. ------------------------------
  1757.  
  1758.    function "+"    (RIGHT : MAE_INTEGER_TYPE) return MAE_INTEGER_TYPE is
  1759.    begin
  1760.       -- No action needed
  1761.       return RIGHT;
  1762.    end "+";
  1763.  
  1764. ------------------------------
  1765.  
  1766.    function "-"    (RIGHT : MAE_INTEGER_TYPE) return MAE_INTEGER_TYPE is
  1767.       RESULT : MAE_INTEGER_TYPE := RIGHT;
  1768.    begin
  1769.       -- change the sign
  1770.       RESULT.SIGN := CHANGE_SIGN(RIGHT.SIGN);
  1771.  
  1772.       return RESULT;
  1773.    end "-";
  1774.  
  1775. ------------------------------
  1776.  
  1777.    function "abs"  (RIGHT : MAE_INTEGER_TYPE) return MAE_INTEGER_TYPE is
  1778.       RESULT : MAE_INTEGER_TYPE := RIGHT;
  1779.    begin
  1780.       RESULT.SIGN := POS_SIGN;
  1781.       return RESULT;
  1782.    end "abs";
  1783.  
  1784.  
  1785. --------------------------------------------------------------------
  1786.  
  1787.    procedure CHECK_IF_OK_FOR_TARGET (RESULT : in out MAE_INTEGER_TYPE) is
  1788.       -- This routine checks if the computed result from an operation
  1789.       -- has actually overflowed the emulated target.  The size is
  1790.       -- specified by the variable TARGET_INTEGER_NUM_BITS in the 
  1791.       -- basic operations package.  This routine is called when
  1792.       -- just before the result is exported.
  1793.       MSC, MSB : INTEGER;
  1794.    begin
  1795.       -- determine most significant comp and most significant bit
  1796.       MSC := (TARGET_INTEGER_NUM_BITS / NO_COMP_BITS) + 1;
  1797.       MSB := (NO_COMP_BITS - (TARGET_INTEGER_NUM_BITS rem NO_COMP_BITS));
  1798.  
  1799.       -- if non-zero above MSC then it overflowed
  1800.       for I in MSC+1 .. SHORT_NUM_COMPS loop
  1801.          if RESULT.COMPS.COMPONENT_ARRAY(I) /= 0 then
  1802.             raise MAE_NUMERIC_ERROR;
  1803.          end if;
  1804.       end loop;
  1805.  
  1806.       -- if non-zero at MSB or above within MSC then it overflowed,
  1807.       -- unless the number is exactly the negative maximum
  1808.       if RESULT.COMPS.COMPONENT_ARRAY(MSC) >= (BIT_VALUE(MSB)) then
  1809.          if (RESULT.SIGN = NEG_SIGN) and
  1810.               (RESULT.COMPS.COMPONENT_ARRAY(MSC) = (BIT_VALUE(MSB))) then
  1811.             for I in 1 .. MSC-1 loop
  1812.                if RESULT.COMPS.COMPONENT_ARRAY(I) /= 0 then
  1813.                   raise MAE_NUMERIC_ERROR;
  1814.                end if;
  1815.             end loop;
  1816.          else
  1817.             raise MAE_NUMERIC_ERROR;
  1818.          end if;
  1819.       end if;
  1820.  
  1821.    exception
  1822.       when others =>
  1823.          raise MAE_NUMERIC_ERROR;
  1824.  
  1825.    end CHECK_IF_OK_FOR_TARGET;
  1826.  
  1827. --------------------------------------------------------------------
  1828.  
  1829.    function "+"    (LEFT,RIGHT : MAE_INTEGER_TYPE) return MAE_INTEGER_TYPE is
  1830.       -- The purpose of this function is to add two
  1831.       -- MAE_INTEGER_TYPEs.
  1832.       RESULT : MAE_INTEGER_TYPE;
  1833.    begin
  1834.       -- zero check
  1835.       if LEFT.COMPS = ZERO then
  1836.          RESULT := RIGHT;
  1837.          CHECK_IF_OK_FOR_TARGET(RESULT);
  1838.          return RESULT;
  1839.       elsif RIGHT.COMPS = ZERO then
  1840.          RESULT := LEFT;
  1841.          CHECK_IF_OK_FOR_TARGET(RESULT);
  1842.          return RESULT;
  1843.       end if;
  1844.  
  1845.       case (LEFT.SIGN xor RIGHT.SIGN) is
  1846.          -- The signs are different (subtraction)
  1847.          when TRUE =>
  1848.             if LEFT.COMPS.COMPONENT_ARRAY > RIGHT.COMPS.COMPONENT_ARRAY then
  1849.                RESULT.COMPS := LEFT.COMPS - RIGHT.COMPS;
  1850.                RESULT.SIGN := LEFT.SIGN;
  1851.             else
  1852.                RESULT.COMPS := RIGHT.COMPS - LEFT.COMPS;
  1853.                RESULT.SIGN := RIGHT.SIGN;
  1854.             end if;
  1855.  
  1856.          -- The signs are the same
  1857.          when FALSE =>
  1858.             RESULT.COMPS := LEFT.COMPS + RIGHT.COMPS;
  1859.             RESULT.SIGN := LEFT.SIGN;
  1860.  
  1861.       end case;
  1862.       -- if result is zero, set sign positive
  1863.       if RESULT.COMPS = ZERO then
  1864.          RESULT.SIGN := POS_SIGN;
  1865.       end if;
  1866.  
  1867.       CHECK_IF_OK_FOR_TARGET(RESULT);
  1868.       return RESULT;
  1869.  
  1870.    exception
  1871.       when others =>
  1872.          raise MAE_NUMERIC_ERROR;
  1873.  
  1874.    end "+";
  1875.  
  1876. ---------------------------
  1877.  
  1878.    function "-"    (LEFT,RIGHT : MAE_INTEGER_TYPE) return MAE_INTEGER_TYPE is
  1879.       -- The purpose of this function is to subtract two
  1880.       -- MAE_INTEGER_TYPEs.
  1881.       RESULT : MAE_INTEGER_TYPE;
  1882.    begin
  1883.       -- zero check
  1884.       if RIGHT.COMPS = ZERO then
  1885.          RESULT := LEFT;
  1886.          CHECK_IF_OK_FOR_TARGET(RESULT);
  1887.          return RESULT;
  1888.       elsif LEFT.COMPS = ZERO then
  1889.          RESULT := -RIGHT;
  1890.          CHECK_IF_OK_FOR_TARGET(RESULT);
  1891.          return RESULT;
  1892.       end if;
  1893.  
  1894.       case (LEFT.SIGN xor RIGHT.SIGN) is
  1895.          -- The signs are different
  1896.          when TRUE =>
  1897.             RESULT.COMPS := LEFT.COMPS + RIGHT.COMPS;
  1898.             RESULT.SIGN := LEFT.SIGN;
  1899.  
  1900.          -- The sign are the same
  1901.          when FALSE =>
  1902.             if LEFT.COMPS.COMPONENT_ARRAY > RIGHT.COMPS.COMPONENT_ARRAY then
  1903.                RESULT.COMPS := LEFT.COMPS - RIGHT.COMPS;
  1904.                RESULT.SIGN := LEFT.SIGN;
  1905.             else
  1906.                RESULT.COMPS := RIGHT.COMPS - LEFT.COMPS;
  1907.                RESULT.SIGN := not LEFT.SIGN;
  1908.             end if;
  1909.  
  1910.       end case;
  1911.       -- if result is zero, set sign positive
  1912.       if RESULT.COMPS = ZERO then
  1913.          RESULT.SIGN := POS_SIGN;
  1914.       end if;
  1915.  
  1916.       CHECK_IF_OK_FOR_TARGET(RESULT);
  1917.       return RESULT;
  1918.  
  1919.    exception
  1920.       when others =>
  1921.          raise MAE_NUMERIC_ERROR;
  1922.  
  1923.    end "-";
  1924.  
  1925. ------------------------------
  1926.  
  1927.    function "*"    (LEFT,RIGHT : MAE_INTEGER_TYPE) return MAE_INTEGER_TYPE is
  1928.       -- The purpose of this function is to multiply two
  1929.       -- MAE_INTEGER_TYPEs.
  1930.       RESULT : MAE_INTEGER_TYPE;
  1931.    begin
  1932.       -- First set the sign, then the integer portion.
  1933.       RESULT.SIGN := not (LEFT.SIGN xor RIGHT.SIGN);
  1934.       -- zero check
  1935.       if (LEFT.COMPS = ZERO) or (RIGHT.COMPS = ZERO) then
  1936.          RESULT.COMPS := ZERO;
  1937.       -- one check
  1938.       elsif LEFT.COMPS = ONE then
  1939.          RESULT.COMPS := RIGHT.COMPS;
  1940.       elsif RIGHT.COMPS = ONE then
  1941.          RESULT.COMPS := LEFT.COMPS;
  1942.       else
  1943.          RESULT.COMPS := LEFT.COMPS * RIGHT.COMPS;
  1944.       end if;
  1945.  
  1946.       CHECK_IF_OK_FOR_TARGET(RESULT);
  1947.       return RESULT;
  1948.  
  1949.    exception
  1950.       when others =>
  1951.          raise MAE_NUMERIC_ERROR;
  1952.  
  1953.    end "*";
  1954.  
  1955. ---------------------------
  1956.  
  1957.    function "/"    (LEFT,RIGHT : MAE_INTEGER_TYPE) return MAE_INTEGER_TYPE is
  1958.       -- The purpose of this function is to divide two
  1959.       -- MAE_INTEGER_TYPEs.
  1960.       RESULT : MAE_INTEGER_TYPE;
  1961.    begin
  1962.       -- First set the sign, then the integer portion.
  1963.       RESULT.SIGN := not (LEFT.SIGN xor RIGHT.SIGN);
  1964.       -- zero check
  1965.       if (RIGHT.COMPS = ZERO) then
  1966.          raise MAE_NUMERIC_ERROR;
  1967.       elsif (LEFT.COMPS = ZERO) then
  1968.          RESULT.COMPS := ZERO;
  1969.       -- one check
  1970.       elsif RIGHT.COMPS = ONE then
  1971.          RESULT.COMPS := LEFT.COMPS;
  1972.       else
  1973.          RESULT.COMPS := LEFT.COMPS / RIGHT.COMPS;
  1974.       end if;
  1975.  
  1976.       CHECK_IF_OK_FOR_TARGET(RESULT);
  1977.       return RESULT;
  1978.  
  1979.    exception
  1980.       when others =>
  1981.          raise MAE_NUMERIC_ERROR;
  1982.  
  1983.    end "/";
  1984.  
  1985. ---------------------------
  1986.  
  1987.    function "rem"  (LEFT,RIGHT : MAE_INTEGER_TYPE) return MAE_INTEGER_TYPE is
  1988.       -- The purpose of this function is to calculate the remainder
  1989.       -- of MAE_INTEGER_TYPEs.
  1990.       RESULT : MAE_INTEGER_TYPE;
  1991.    begin
  1992.       -- First set the sign, then the integer portion.
  1993.       RESULT.SIGN := LEFT.SIGN;
  1994.       RESULT.COMPS := LEFT.COMPS rem RIGHT.COMPS;
  1995.  
  1996.       CHECK_IF_OK_FOR_TARGET(RESULT);
  1997.       return RESULT;
  1998.  
  1999.    exception
  2000.       when others =>
  2001.          raise MAE_NUMERIC_ERROR;
  2002.  
  2003.    end "rem";
  2004.  
  2005. ---------------------------
  2006.  
  2007.    function "mod"  (LEFT,RIGHT : MAE_INTEGER_TYPE) return MAE_INTEGER_TYPE is
  2008.       -- The purpose of this function is to modulo
  2009.       -- MAE_INTEGER_TYPEs.
  2010.       RESULT : MAE_INTEGER_TYPE;
  2011.    begin
  2012.       -- The sign of the result is the sign of the dividend
  2013.       RESULT.SIGN := RIGHT.SIGN;
  2014.       case (LEFT.SIGN xor RIGHT.SIGN) is
  2015.          -- if the signs are different, the modulo is
  2016.          -- is the complement of the remainder about the dividend.
  2017.          when TRUE =>
  2018.             RESULT.COMPS := LEFT.COMPS rem RIGHT.COMPS;
  2019.             if RESULT.COMPS /= ZERO then
  2020.                RESULT.COMPS := RIGHT.COMPS - RESULT.COMPS;
  2021.             end if;
  2022.          
  2023.          -- if the signs are the same, the modulo is
  2024.          -- is the remainder.
  2025.          when FALSE =>
  2026.             RESULT.COMPS := LEFT.COMPS rem RIGHT.COMPS;
  2027.       end case;
  2028.  
  2029.       CHECK_IF_OK_FOR_TARGET(RESULT);
  2030.       return RESULT;
  2031.  
  2032.    exception
  2033.       when others =>
  2034.          raise MAE_NUMERIC_ERROR;
  2035.  
  2036.    end "mod";
  2037.  
  2038. ---------------------------
  2039.  
  2040.    function "**"   (LEFT : MAE_INTEGER_TYPE; RIGHT : INTEGER)
  2041.                        return MAE_INTEGER_TYPE is
  2042.       -- The purpose of this function is to raise a MAE_INTEGER_TYPE
  2043.       -- to a given power.  A simple loop with a multiplication could
  2044.       -- be done the given count, less one, times.  This method is
  2045.       -- inefficient, therefore a different algorithm is used.
  2046.       -- The use of additional memory to hold intermediate
  2047.       -- calculations will improve performance by reducing
  2048.       -- the number of multiplications.
  2049.       COUNT : constant INTEGER := RIGHT;
  2050.       REM_COUNT : INTEGER := RIGHT;
  2051.       RESULT : MAE_INTEGER_TYPE;
  2052.       POWER_2, POWER_4, POWER_8 : SHORT_COMP_ARRAY := ZERO;
  2053.    begin
  2054.       -- if the power is less than 0, it is an exception
  2055.       if COUNT < 0 then
  2056.          raise CONSTRAINT_ERROR;
  2057.       -- if the power is 0, return 1
  2058.       elsif COUNT = 0 then
  2059.          RESULT.COMPS := ONE;
  2060.          return RESULT;
  2061.       -- if the power is 1 or number is 0 or 1, return the input number
  2062.       elsif (COUNT = 1) or (LEFT.COMPS = ONE) or (LEFT.COMPS = ZERO) then
  2063.          return LEFT;
  2064.       elsif COUNT > TWO_THREE_LESS_ONE then
  2065.          -- compute to POWER_8
  2066.          POWER_2 := LEFT.COMPS * LEFT.COMPS;
  2067.          POWER_4 := POWER_2 * POWER_2;
  2068.          POWER_8 := POWER_4 * POWER_4;
  2069.          RESULT.COMPS := POWER_8;
  2070.          REM_COUNT := REM_COUNT - 8;
  2071.       elsif COUNT > TWO_TWO_LESS_ONE then
  2072.          -- compute to POWER_4
  2073.          POWER_2 := LEFT.COMPS * LEFT.COMPS;
  2074.          POWER_4 := POWER_2 * POWER_2;
  2075.          RESULT.COMPS := POWER_4;
  2076.          REM_COUNT := REM_COUNT - 4;
  2077.       else
  2078.          -- compute to POWER_2
  2079.          POWER_2 := LEFT.COMPS * LEFT.COMPS;
  2080.          RESULT.COMPS := POWER_2;
  2081.          REM_COUNT := REM_COUNT - 2;
  2082.       end if;
  2083.  
  2084.       -- the pre-computed values are now used the build
  2085.       -- to the answer
  2086.  
  2087.       -- loop until the power is reduced to under the
  2088.       -- maximum pre-computed value
  2089.       loop
  2090.          if REM_COUNT < TWO_THREE then 
  2091.            exit;
  2092.          end if;
  2093.          RESULT.COMPS := RESULT.COMPS * POWER_8;
  2094.          REM_COUNT := REM_COUNT - 8;
  2095.       end loop;
  2096.  
  2097.       -- the remaining power may be between 4 .. 7
  2098.       if REM_COUNT > TWO_TWO_LESS_ONE then
  2099.          RESULT.COMPS := RESULT.COMPS * POWER_4;
  2100.          REM_COUNT := REM_COUNT - 4;
  2101.       end if;
  2102.  
  2103.       -- the remaining power may be between 2 .. 3
  2104.       if REM_COUNT > 1 then
  2105.          RESULT.COMPS := RESULT.COMPS * POWER_2;
  2106.          REM_COUNT := REM_COUNT - 2;
  2107.       end if;
  2108.  
  2109.       -- the remaining power may be 1, therefore the sign
  2110.       -- is negative if the input number is negative
  2111.       if REM_COUNT = 1 then
  2112.          RESULT.COMPS := RESULT.COMPS * LEFT.COMPS;
  2113.          RESULT.SIGN := LEFT.SIGN;
  2114.       end if;
  2115.  
  2116.       CHECK_IF_OK_FOR_TARGET(RESULT);
  2117.       return RESULT;
  2118.  
  2119.    exception
  2120.       when others =>
  2121.          raise MAE_NUMERIC_ERROR;
  2122.  
  2123.    end "**";
  2124.  
  2125. ----------------------------
  2126.  
  2127.    function MAE_INTEGER_TYPE_VALUE(STRING_PIC : STRING)
  2128.                                       return MAE_INTEGER_TYPE is
  2129.    -- The purpose of this function is to convert a string
  2130.    -- of characters into the MAE_INTEGER_TYPE structure.
  2131.    -- The string is valid if an only if it contains solely 
  2132.    -- digits and is within the specified range for 
  2133.    -- MAE_INTEGER_TYPEs.
  2134.       INDEX : INTEGER;
  2135.       RESULT : MAE_INTEGER_TYPE;
  2136.    begin
  2137.       -- Strip leading spaces if necessary
  2138.       INDEX := STRING_PIC'first;
  2139.       for I in STRING_PIC'first .. STRING_PIC'last loop
  2140.          if STRING_PIC(I) /= ' ' then
  2141.             exit;
  2142.          end if;
  2143.          INDEX := INDEX + 1;
  2144.          -- if the string is empty
  2145.          if INDEX > STRING_PIC'last then
  2146.             raise MAE_FORMAT_ERROR;
  2147.          end if;
  2148.       end loop;
  2149.  
  2150.       -- Set the sign
  2151.       RESULT.SIGN := POS_SIGN;
  2152.       if STRING_PIC(INDEX) = '-' then
  2153.          RESULT.SIGN := NEG_SIGN;
  2154.          INDEX := INDEX + 1;
  2155.       elsif STRING_PIC(INDEX) = '+' then
  2156.          INDEX := INDEX + 1;
  2157.       end if;
  2158.  
  2159.       -- if the string is empty
  2160.       if INDEX > STRING_PIC'last then
  2161.          raise MAE_FORMAT_ERROR;
  2162.       end if;
  2163.  
  2164.       -- Store the integer portion
  2165.       for I in INDEX .. STRING_PIC'last loop
  2166.          case STRING_PIC(I) is
  2167.             when '0' => RESULT.COMPS := RESULT.COMPS*TEN;
  2168.             when '1' => RESULT.COMPS := RESULT.COMPS*TEN + ONE;
  2169.             when '2' => RESULT.COMPS := RESULT.COMPS*TEN + TWO;
  2170.             when '3' => RESULT.COMPS := RESULT.COMPS*TEN + THREE;
  2171.             when '4' => RESULT.COMPS := RESULT.COMPS*TEN + FOUR;
  2172.             when '5' => RESULT.COMPS := RESULT.COMPS*TEN + FIVE;
  2173.             when '6' => RESULT.COMPS := RESULT.COMPS*TEN + SIX;
  2174.             when '7' => RESULT.COMPS := RESULT.COMPS*TEN + SEVEN;
  2175.             when '8' => RESULT.COMPS := RESULT.COMPS*TEN + EIGHT;
  2176.             when '9' => RESULT.COMPS := RESULT.COMPS*TEN + NINE;
  2177.             when ' ' =>
  2178.                -- if there is a space after the sign - exception 
  2179.                -- else check if it is the end of the number
  2180.                if I /= INDEX then
  2181.                   -- Check trailing spaces if necessary
  2182.                   for J in I+1 .. STRING_PIC'last loop
  2183.                      if STRING_PIC(J) /= ' ' then
  2184.                         raise MAE_FORMAT_ERROR;
  2185.                      end if;
  2186.                   end loop;
  2187.                   exit;
  2188.                else
  2189.                   raise MAE_FORMAT_ERROR;
  2190.                end if;
  2191.             when others => raise MAE_FORMAT_ERROR;
  2192.          end case;
  2193.       end loop;
  2194.  
  2195.       CHECK_IF_OK_FOR_TARGET(RESULT);
  2196.       return RESULT;
  2197.  
  2198.    exception
  2199.       when others =>
  2200.          raise MAE_NUMERIC_ERROR;
  2201.  
  2202.    end MAE_INTEGER_TYPE_VALUE;
  2203.  
  2204. ------------------------------
  2205.  
  2206.    function MAE_INTEGER_TYPE_IMAGE(STORE_PIC : MAE_INTEGER_TYPE)
  2207.                                       return STRING is
  2208.    -- The purpose of this function is to convert a 
  2209.    -- MAE_INTEGER_TYPE into string of characters.
  2210.       INDEX : INTEGER;
  2211.       INTERMEDIATE : MAE_INTEGER_TYPE := STORE_PIC;
  2212.       TEMP : SHORT_COMP_ARRAY;
  2213.       TEMP_INTEGER : INTEGER;
  2214.       STRING_PIC : STRING (1 .. INTEGER_DIGITS+4) :=
  2215.               EMPTY_STRING(1 .. INTEGER_DIGITS+4);
  2216.       TEMP_THREE_CHAR : STRING (1 .. 3);
  2217.    begin
  2218.       INDEX := STRING_PIC'last;
  2219.       -- Store the integer portion
  2220.       -- if it is zero
  2221.       if INTERMEDIATE.COMPS = ZERO then
  2222.          STRING_PIC(INDEX) := '0';
  2223.          INDEX := INDEX - 1;
  2224.       else
  2225.          -- loop over the MAE_NUMBER taking the least significant
  2226.          -- decimal digits and storing them in the array(backwards)
  2227.          while INTERMEDIATE.COMPS /= ZERO loop
  2228.             TEMP := INTERMEDIATE.COMPS rem THOUSAND;
  2229.             INTERMEDIATE.COMPS := INTERMEDIATE.COMPS / THOUSAND;
  2230.             -- assumes 1000 fits into two components
  2231.             TEMP_INTEGER := TEMP.COMPONENT_ARRAY(2)*BASE_COMP_VALUE +
  2232.                                   TEMP.COMPONENT_ARRAY(1);
  2233.             TEXT_IO.INTEGER_IO.PUT(TEMP_THREE_CHAR, TEMP_INTEGER);
  2234.             for I in 1 .. 2 loop
  2235.                 exit when TEMP_THREE_CHAR(I) /= ' ';
  2236.                 TEMP_THREE_CHAR(I) := '0';
  2237.             end loop;
  2238.             STRING_PIC(INDEX-2 .. INDEX) := TEMP_THREE_CHAR;
  2239.             INDEX := INDEX - 3;
  2240.          end loop;
  2241.          INDEX := INDEX + 1;
  2242.  
  2243.          while STRING_PIC(INDEX) = '0' loop
  2244.             STRING_PIC(INDEX) := ' ';
  2245.             INDEX := INDEX + 1;
  2246.          end loop;
  2247.  
  2248.          -- Store the sign
  2249.          INDEX := INDEX - 1;
  2250.          if STORE_PIC.SIGN = NEG_SIGN then
  2251.             STRING_PIC(INDEX) := '-';
  2252.          end if;
  2253.       end if;
  2254.  
  2255.       return STRING_PIC(INDEX .. STRING_PIC'last);
  2256.  
  2257.    exception
  2258.       when others =>
  2259.          raise MAE_NUMERIC_ERROR;
  2260.  
  2261.    end MAE_INTEGER_TYPE_IMAGE;
  2262.  
  2263. ------------------------------
  2264.  
  2265.    procedure GET (FROM : in STRING;
  2266.                   ITEM : out MAE_INTEGER_TYPE;
  2267.                   LAST : out POSITIVE) is
  2268.  
  2269.    begin
  2270.       ITEM := MAE_INTEGER_TYPE_VALUE(FROM);
  2271.       LAST := FROM'last;
  2272.  
  2273.    exception
  2274.       when others =>
  2275.          raise DATA_ERROR;
  2276.  
  2277.    end GET;
  2278.  
  2279. ------------------------------
  2280.  
  2281.    procedure PUT (TO : out STRING;
  2282.                   ITEM : in MAE_INTEGER_TYPE;
  2283.                   BASE : in NUMBER_BASE := DEFAULT_BASE) is
  2284.    -- The purpose of this function is to convert a 
  2285.    -- MAE_INTEGER_TYPE into string of characters.
  2286.       INDEX : INTEGER;
  2287.       INTERMEDIATE : MAE_INTEGER_TYPE := ITEM;
  2288.       TEMP : SHORT_COMP_ARRAY;
  2289.       TEMP_INTEGER : INTEGER;
  2290.       STRING_PIC : STRING (1 .. INTEGER_DIGITS+4);
  2291.       TEMP_THREE_CHAR : STRING (1 .. 3);
  2292.       LAST_DIGIT : INTEGER;
  2293.    begin
  2294.       if BASE /= DEFAULT_BASE then 
  2295.          raise LAYOUT_ERROR;
  2296.       end if;
  2297.  
  2298.       TO := EMPTY_STRING(TO'first .. TO'last);
  2299.       -- Store the integer portion
  2300.       -- if it is zero
  2301.       if INTERMEDIATE.COMPS = ZERO then
  2302.          TO(TO'last) := '0';
  2303.       else
  2304.          INDEX := STRING_PIC'last;
  2305.          -- loop over the MAE_NUMBER taking the least significant
  2306.          -- decimal digits and storing them in the array(backwards)
  2307.          while INTERMEDIATE.COMPS /= ZERO loop
  2308.             TEMP := INTERMEDIATE.COMPS rem THOUSAND;
  2309.             INTERMEDIATE.COMPS := INTERMEDIATE.COMPS / THOUSAND;
  2310.             TEMP_INTEGER := TEMP.COMPONENT_ARRAY(2)*BASE_COMP_VALUE +
  2311.                                   TEMP.COMPONENT_ARRAY(1);
  2312.             -- assumes 1000 fits into two components
  2313.             TEXT_IO.INTEGER_IO.PUT(TEMP_THREE_CHAR, TEMP_INTEGER);
  2314.             for I in 1 .. 2 loop
  2315.                 exit when TEMP_THREE_CHAR(I) /= ' ';
  2316.                 TEMP_THREE_CHAR(I) := '0';
  2317.             end loop;
  2318.             STRING_PIC(INDEX-2 .. INDEX) := TEMP_THREE_CHAR;
  2319.             INDEX := INDEX - 3;
  2320.          end loop;
  2321.          INDEX := INDEX + 1;
  2322.  
  2323.          while STRING_PIC(INDEX) = '0' loop
  2324.             STRING_PIC(INDEX) := ' ';
  2325.             INDEX := INDEX + 1;
  2326.          end loop;
  2327.  
  2328.          -- Store the sign
  2329.          if ITEM.SIGN = NEG_SIGN then
  2330.             INDEX := INDEX - 1;
  2331.             STRING_PIC(INDEX) := '-';
  2332.          end if;
  2333.  
  2334.          TO((TO'last-(STRING_PIC'last-INDEX)) .. TO'last) :=
  2335.                    STRING_PIC(INDEX .. STRING_PIC'last);
  2336.       end if;
  2337.  
  2338.    exception
  2339.       when others =>
  2340.          raise LAYOUT_ERROR;
  2341.  
  2342.    end PUT;
  2343.  
  2344. ------------------------------
  2345.  
  2346. begin
  2347.  
  2348.    -- Initialize the digits ONE .. TEN with the appropriate
  2349.    -- integer value.  This allows for the length of the array
  2350.    -- to change in the basic operations and not caused a coding
  2351.    -- change in this package.
  2352.    -- Notice that these values assume the declaration of the type
  2353.    -- is initially a zero value.  This assumption is justified since
  2354.    -- the declaration of the type is in this package specification.
  2355.    -- ZERO taken care of by the initial value.
  2356.    ONE.COMPONENT_ARRAY(1) := 1;
  2357.    TWO.COMPONENT_ARRAY(1) := 2;
  2358.    THREE.COMPONENT_ARRAY(1) := 3;
  2359.    FOUR.COMPONENT_ARRAY(1) := 4;
  2360.    FIVE.COMPONENT_ARRAY(1) := 5;
  2361.    SIX.COMPONENT_ARRAY(1) := 6;
  2362.    SEVEN.COMPONENT_ARRAY(1) := 7;
  2363.    EIGHT.COMPONENT_ARRAY(1) := 8;
  2364.    NINE.COMPONENT_ARRAY(1) := 9;
  2365.    TEN.COMPONENT_ARRAY(1) := 10;
  2366.    THOUSAND.COMPONENT_ARRAY(2) := 1000 / BASE_COMP_VALUE;
  2367.    THOUSAND.COMPONENT_ARRAY(1) := 1000 rem BASE_COMP_VALUE;
  2368.  
  2369.    MAE_INTEGER_ONE.COMPS := ONE;
  2370.    MAE_INTEGER_TWO.COMPS := TWO;
  2371.  
  2372.    MAE_INTEGER_LAST := ((((MAE_INTEGER_TWO**(TARGET_INTEGER_NUM_BITS-1))
  2373.                      - MAE_INTEGER_ONE) * MAE_INTEGER_TWO) + MAE_INTEGER_ONE);
  2374.    MAE_INTEGER_FIRST := (-(MAE_INTEGER_LAST)) - MAE_INTEGER_ONE;
  2375.  
  2376. end MAE_INTEGER;
  2377. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  2378. --maeshort.txt
  2379. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  2380. -------------------------------------------------------------------------------
  2381. --                                                                           --
  2382. --             Emulation of Machine Arithmetic - a WIS Ada Tool              --
  2383. --                                                                           --
  2384. --                         Ada Technology Group                              --
  2385. --                         SYSCON Corporation                                --
  2386. --                         3990 Sherman Street                               --
  2387. --                         San Diego, CA. 92110                              --
  2388. --                                                                           --
  2389. --                        John Long & John Reddan                            --
  2390. --                                                                           --
  2391. -------------------------------------------------------------------------------
  2392.  
  2393. with MAE_BASIC_OPERATIONS; use MAE_BASIC_OPERATIONS;
  2394.  
  2395. package MAE_SHORT_FLOAT is
  2396. -------------------------------------------------------------------
  2397. -- The purpose of this package is to emulate target machine
  2398. -- floating point arithmetic on host machines with 16-bit or 
  2399. -- larger word size.
  2400. --
  2401. -- The range of the supported type is as follows:
  2402. --
  2403. --     TARGET_SHORT_FLOAT (Real)
  2404. --        approximate range of 10**-38 to 10**38 and 0
  2405. --        mantissa => MAE_BASIC_OPERATIONS.TARGET_SHORT_NUM_BITS
  2406. --                    bit binary fraction
  2407. --        exponent => -128 to 127
  2408. --
  2409. -- Any errors which occur during use of the arithmetic and
  2410. -- boolean functions defined below will result in the
  2411. -- raising of the exception "MAE_NUMERIC_ERROR".  
  2412.  
  2413. --
  2414. -- Visible operations with MAE_SHORT_FLOAT_TYPE
  2415. --
  2416.    type MAE_SHORT_FLOAT_TYPE is private;
  2417.  
  2418.    -- The defined operators for this type are as follows:
  2419.  
  2420.    -- predefined system function "=" and function "/="
  2421.    function "<"    (LEFT, RIGHT : MAE_SHORT_FLOAT_TYPE) return BOOLEAN;
  2422.    function "<="   (LEFT, RIGHT : MAE_SHORT_FLOAT_TYPE) return BOOLEAN;
  2423.    function ">"    (LEFT, RIGHT : MAE_SHORT_FLOAT_TYPE) return BOOLEAN;
  2424.    function ">="   (LEFT, RIGHT : MAE_SHORT_FLOAT_TYPE) return BOOLEAN;
  2425.  
  2426.    function "+"    (RIGHT : MAE_SHORT_FLOAT_TYPE) return MAE_SHORT_FLOAT_TYPE;
  2427.    function "-"    (RIGHT : MAE_SHORT_FLOAT_TYPE) return MAE_SHORT_FLOAT_TYPE;
  2428.    function "abs"  (RIGHT : MAE_SHORT_FLOAT_TYPE) return MAE_SHORT_FLOAT_TYPE;
  2429.  
  2430.    function "+"    (LEFT,RIGHT : MAE_SHORT_FLOAT_TYPE) 
  2431.                        return MAE_SHORT_FLOAT_TYPE;
  2432.    function "-"    (LEFT,RIGHT : MAE_SHORT_FLOAT_TYPE) 
  2433.                        return MAE_SHORT_FLOAT_TYPE;
  2434.    function "*"    (LEFT,RIGHT : MAE_SHORT_FLOAT_TYPE) 
  2435.                        return MAE_SHORT_FLOAT_TYPE;
  2436.    function "/"    (LEFT,RIGHT : MAE_SHORT_FLOAT_TYPE) 
  2437.                        return MAE_SHORT_FLOAT_TYPE;
  2438.  
  2439.    function "**"   (LEFT : MAE_SHORT_FLOAT_TYPE; RIGHT : INTEGER)
  2440.                        return MAE_SHORT_FLOAT_TYPE;
  2441.  
  2442.  
  2443.    procedure GET (FROM : in STRING;
  2444.                   ITEM : out MAE_SHORT_FLOAT_TYPE;
  2445.                   LAST : out POSITIVE);
  2446.  
  2447.    procedure PUT (TO : out STRING;
  2448.                   ITEM : in MAE_SHORT_FLOAT_TYPE;
  2449.                   AFT : in FIELD := SHORT_DEFAULT_AFT;
  2450.                   EXP : in FIELD := SHORT_DEFAULT_EXP);
  2451.  
  2452.    function TARGET_SHORT_FLOAT_EPSILON return MAE_SHORT_FLOAT_TYPE;
  2453.  
  2454.    function TARGET_SHORT_FLOAT_LARGE return MAE_SHORT_FLOAT_TYPE;
  2455.  
  2456.    function TARGET_SHORT_FLOAT_SMALL return MAE_SHORT_FLOAT_TYPE;
  2457.  
  2458.    function TARGET_SHORT_FLOAT_LAST return MAE_SHORT_FLOAT_TYPE;
  2459.  
  2460.    function TARGET_SHORT_FLOAT_FIRST return MAE_SHORT_FLOAT_TYPE;
  2461.  
  2462. -------------------------------------------------------------------
  2463. private
  2464.  
  2465. -- The declaration of the next variable is to allow
  2466. -- the record declaration under the Telesoft version 1.5 compiler.
  2467. -- A better declaration would allow the COMP_ARRAY range to be
  2468. -- (1 .. BITS_TO_COMPS(NO_OF_BITS).
  2469.  
  2470.    type MAE_SHORT_FLOAT_TYPE is
  2471.       record
  2472.          SIGN : SIGN_TYPE := POS_SIGN;
  2473.          COMPS : SHORT_COMP_ARRAY := SHORT_FLOAT_COMP_ARRAY;
  2474.          EXPONENT : EXPONENT_TYPE := 0;
  2475.       end record;
  2476.  
  2477. -------------------------------------------------------------------
  2478. end MAE_SHORT_FLOAT;
  2479.  
  2480. -------------------------------------------------------------------
  2481. -------------------------------------------------------------------
  2482. with MAE_BASIC_OPERATIONS; use MAE_BASIC_OPERATIONS;
  2483.  
  2484. package body MAE_SHORT_FLOAT is
  2485. -------------------------------------------------------------------
  2486. -- Local variables for better tracing
  2487. --
  2488.    MAE_FORMAT_ERROR : EXCEPTION;
  2489.    MAE_SHORT_FLOAT_OVERFLOW : EXCEPTION;
  2490.    DATA_ERROR : EXCEPTION;
  2491.    LAYOUT_ERROR : EXCEPTION;
  2492.  
  2493. -------------------------------------------------------------------
  2494. -- Constants for local functions and procedures
  2495. --
  2496. -- Once again the declaration of variables is affect by the
  2497. -- Telesoft 1.5 compiler.  The better declaration would use
  2498. -- the 'range, 'first, and 'last attributes for initialization.
  2499. -- The initialization of the variables ONE .. TEN are done in
  2500. -- the body(bottom) of this package.
  2501.  
  2502.    ZERO : MAE_SHORT_FLOAT_TYPE;
  2503.    ONE : MAE_SHORT_FLOAT_TYPE;
  2504.    TWO : MAE_SHORT_FLOAT_TYPE;
  2505.    THREE : MAE_SHORT_FLOAT_TYPE;
  2506.    FOUR : MAE_SHORT_FLOAT_TYPE;
  2507.    FIVE : MAE_SHORT_FLOAT_TYPE;
  2508.    SIX : MAE_SHORT_FLOAT_TYPE;
  2509.    SEVEN : MAE_SHORT_FLOAT_TYPE;
  2510.    EIGHT : MAE_SHORT_FLOAT_TYPE;
  2511.    NINE : MAE_SHORT_FLOAT_TYPE;
  2512.    TEN : MAE_SHORT_FLOAT_TYPE;
  2513.  
  2514.    HUNDRED : MAE_SHORT_FLOAT_TYPE;
  2515.    THOUSAND : MAE_SHORT_FLOAT_TYPE;
  2516.    TEN_THOUSAND : MAE_SHORT_FLOAT_TYPE;
  2517.  
  2518.    ONE_TENTH : MAE_SHORT_FLOAT_TYPE;
  2519.    ONE_HUNDREDTH : MAE_SHORT_FLOAT_TYPE;
  2520.    ONE_THOUSANDTH : MAE_SHORT_FLOAT_TYPE;
  2521.    ONE_TEN_THOUSANDTH : MAE_SHORT_FLOAT_TYPE;
  2522.  
  2523.    MAE_SHORT_FLOAT_EPSILON : MAE_SHORT_FLOAT_TYPE;
  2524.    MAE_SHORT_FLOAT_LARGE : MAE_SHORT_FLOAT_TYPE;
  2525.    MAE_SHORT_FLOAT_SMALL : MAE_SHORT_FLOAT_TYPE;
  2526.    MAE_SHORT_FLOAT_LAST : MAE_SHORT_FLOAT_TYPE;
  2527.    MAE_SHORT_FLOAT_FIRST : MAE_SHORT_FLOAT_TYPE;
  2528.  
  2529.    TWO_THREE : constant INTEGER := 2**3;
  2530.    TWO_THREE_LESS_ONE : constant INTEGER := (2**3)-1;
  2531.    TWO_TWO : constant INTEGER := 2**2;
  2532.    TWO_TWO_LESS_ONE : constant INTEGER := (2**2)-1;
  2533.  
  2534. -------------------------------------------------------------------
  2535. -- Visible operations with MAE_SHORT_FLOAT_TYPE
  2536. --
  2537.    function TARGET_SHORT_FLOAT_EPSILON return MAE_SHORT_FLOAT_TYPE is
  2538.    begin
  2539.       return MAE_SHORT_FLOAT_EPSILON;
  2540.    end TARGET_SHORT_FLOAT_EPSILON; 
  2541.  
  2542. ------------------------------
  2543.  
  2544.    function TARGET_SHORT_FLOAT_LARGE return MAE_SHORT_FLOAT_TYPE is
  2545.    begin
  2546.       return MAE_SHORT_FLOAT_LARGE;
  2547.    end TARGET_SHORT_FLOAT_LARGE;
  2548.  
  2549. ------------------------------
  2550.  
  2551.    function TARGET_SHORT_FLOAT_SMALL return MAE_SHORT_FLOAT_TYPE is
  2552.    begin
  2553.       return MAE_SHORT_FLOAT_SMALL;
  2554.    end TARGET_SHORT_FLOAT_SMALL;
  2555.  
  2556. ------------------------------
  2557.  
  2558.    function TARGET_SHORT_FLOAT_LAST return MAE_SHORT_FLOAT_TYPE is
  2559.    begin
  2560.       return MAE_SHORT_FLOAT_LAST;
  2561.    end TARGET_SHORT_FLOAT_LAST;
  2562.  
  2563. ------------------------------
  2564.  
  2565.    function TARGET_SHORT_FLOAT_FIRST return MAE_SHORT_FLOAT_TYPE is
  2566.    begin
  2567.       return MAE_SHORT_FLOAT_FIRST;
  2568.    end TARGET_SHORT_FLOAT_FIRST;
  2569.  
  2570. ------------------------------
  2571.  
  2572.  
  2573.    -- predefined system functions : function "=" and function "/="
  2574.  
  2575.    function "<"    (LEFT, RIGHT : MAE_SHORT_FLOAT_TYPE) return BOOLEAN is
  2576.       -- Resolve the comparision by, first checking the signs, then
  2577.       -- checking the exponent, and finally the component arrays.
  2578.    begin
  2579.       if LEFT.COMPS.COMPONENT_ARRAY = ZERO.COMPS.COMPONENT_ARRAY then
  2580.          if RIGHT.COMPS.COMPONENT_ARRAY = ZERO.COMPS.COMPONENT_ARRAY then
  2581.             return FALSE;
  2582.          else
  2583.             return RIGHT.SIGN;
  2584.          end if;
  2585.       elsif RIGHT.COMPS.COMPONENT_ARRAY = ZERO.COMPS.COMPONENT_ARRAY then
  2586.          return not LEFT.SIGN;
  2587.       end if;
  2588.  
  2589.       case LEFT.SIGN is
  2590.          when POS_SIGN =>
  2591.             if RIGHT.SIGN = POS_SIGN then
  2592.                -- both are positive
  2593.                if LEFT.EXPONENT < RIGHT.EXPONENT then 
  2594.                   return TRUE;
  2595.                elsif LEFT.EXPONENT > RIGHT.EXPONENT then
  2596.                   return FALSE;
  2597.                else
  2598.                   return
  2599.                    (LEFT.COMPS.COMPONENT_ARRAY < RIGHT.COMPS.COMPONENT_ARRAY);
  2600.                end if;
  2601.             else
  2602.                -- left is positive, right is negative
  2603.                return FALSE;
  2604.             end if;
  2605.          when NEG_SIGN =>
  2606.             if RIGHT.SIGN = NEG_SIGN then
  2607.                -- both are negative
  2608.                if LEFT.EXPONENT > RIGHT.EXPONENT then 
  2609.                   return TRUE;
  2610.                elsif LEFT.EXPONENT < RIGHT.EXPONENT then
  2611.                   return FALSE;
  2612.                else
  2613.                   return 
  2614.                    (LEFT.COMPS.COMPONENT_ARRAY > RIGHT.COMPS.COMPONENT_ARRAY);
  2615.                end if;
  2616.             else
  2617.                -- left is negative, right is positive
  2618.                return TRUE;
  2619.             end if;
  2620.       end case;
  2621.  
  2622.    exception
  2623.       when others =>
  2624.          raise MAE_NUMERIC_ERROR;
  2625.  
  2626.    end "<";
  2627.  
  2628. ------------------------------
  2629.  
  2630.    function "<="   (LEFT, RIGHT : MAE_SHORT_FLOAT_TYPE) return BOOLEAN is
  2631.       -- Resolve the comparision by, first checking the signs, then
  2632.       -- checking the exponent, and finally the component arrays.
  2633.    begin
  2634.       if LEFT.COMPS.COMPONENT_ARRAY = ZERO.COMPS.COMPONENT_ARRAY then
  2635.          return RIGHT.SIGN;
  2636.       elsif RIGHT.COMPS.COMPONENT_ARRAY = ZERO.COMPS.COMPONENT_ARRAY then
  2637.          return not LEFT.SIGN;
  2638.       end if;
  2639.  
  2640.       case LEFT.SIGN is
  2641.          when POS_SIGN =>
  2642.             if RIGHT.SIGN = POS_SIGN then
  2643.                -- both are positive
  2644.                if LEFT.EXPONENT < RIGHT.EXPONENT then 
  2645.                   return TRUE;
  2646.                elsif LEFT.EXPONENT > RIGHT.EXPONENT then
  2647.                   return FALSE;
  2648.                else
  2649.                   return 
  2650.                    (LEFT.COMPS.COMPONENT_ARRAY <= RIGHT.COMPS.COMPONENT_ARRAY);
  2651.                end if;
  2652.             else
  2653.                -- left is positive, right is negative
  2654.                return FALSE;
  2655.             end if;
  2656.          when NEG_SIGN =>
  2657.             if RIGHT.SIGN = NEG_SIGN then
  2658.                -- both are negative
  2659.                if LEFT.EXPONENT > RIGHT.EXPONENT then 
  2660.                   return TRUE;
  2661.                elsif LEFT.EXPONENT < RIGHT.EXPONENT then
  2662.                   return FALSE;
  2663.                else
  2664.                   return
  2665.                    (LEFT.COMPS.COMPONENT_ARRAY >= RIGHT.COMPS.COMPONENT_ARRAY);
  2666.                end if;
  2667.             else
  2668.                -- left is negative, right is positive
  2669.                return TRUE;
  2670.             end if;
  2671.       end case;
  2672.  
  2673.    exception
  2674.       when others =>
  2675.          raise MAE_NUMERIC_ERROR;
  2676.  
  2677.    end "<=";
  2678.  
  2679. ------------------------------
  2680.  
  2681.    function ">"    (LEFT, RIGHT : MAE_SHORT_FLOAT_TYPE) return BOOLEAN is
  2682.       -- Resolve the comparision by, first checking the signs, then
  2683.       -- checking the exponent, and finally the component arrays.
  2684.    begin
  2685.       if LEFT.COMPS.COMPONENT_ARRAY = ZERO.COMPS.COMPONENT_ARRAY then
  2686.          return not RIGHT.SIGN;
  2687.       elsif RIGHT.COMPS.COMPONENT_ARRAY = ZERO.COMPS.COMPONENT_ARRAY then
  2688.          return LEFT.SIGN;
  2689.       end if;
  2690.  
  2691.       case LEFT.SIGN is
  2692.          when POS_SIGN =>
  2693.             if RIGHT.SIGN = POS_SIGN then
  2694.                -- both are positive
  2695.                if LEFT.EXPONENT > RIGHT.EXPONENT then 
  2696.                   return TRUE;
  2697.                elsif LEFT.EXPONENT < RIGHT.EXPONENT then
  2698.                   return FALSE;
  2699.                else
  2700.                   return 
  2701.                    (LEFT.COMPS.COMPONENT_ARRAY > RIGHT.COMPS.COMPONENT_ARRAY);
  2702.                end if;
  2703.             else
  2704.                -- left is positive, right is negative
  2705.                return TRUE;
  2706.             end if;
  2707.          when NEG_SIGN =>
  2708.             if RIGHT.SIGN = NEG_SIGN then
  2709.                -- both are negative
  2710.                if LEFT.EXPONENT < RIGHT.EXPONENT then 
  2711.                   return TRUE;
  2712.                elsif LEFT.EXPONENT > RIGHT.EXPONENT then
  2713.                   return FALSE;
  2714.                else
  2715.                   return 
  2716.                    (LEFT.COMPS.COMPONENT_ARRAY < RIGHT.COMPS.COMPONENT_ARRAY);
  2717.                end if;
  2718.             else
  2719.                -- left is negative, right is positive
  2720.                return FALSE;
  2721.             end if;
  2722.       end case;
  2723.  
  2724.    exception
  2725.       when others =>
  2726.          raise MAE_NUMERIC_ERROR;
  2727.  
  2728.    end ">";
  2729.  
  2730. ------------------------------
  2731.  
  2732.    function ">="   (LEFT, RIGHT : MAE_SHORT_FLOAT_TYPE) return BOOLEAN is
  2733.       -- Resolve the comparision by, first checking the signs, then
  2734.       -- checking the exponent, and finally the component arrays.
  2735.    begin
  2736.       if LEFT.COMPS.COMPONENT_ARRAY = ZERO.COMPS.COMPONENT_ARRAY then
  2737.          if RIGHT.COMPS.COMPONENT_ARRAY = ZERO.COMPS.COMPONENT_ARRAY then
  2738.             return TRUE;
  2739.          else
  2740.             return not RIGHT.SIGN;
  2741.          end if;
  2742.       elsif RIGHT.COMPS.COMPONENT_ARRAY = ZERO.COMPS.COMPONENT_ARRAY then
  2743.          return LEFT.SIGN;
  2744.       end if;
  2745.  
  2746.       case LEFT.SIGN is
  2747.          when POS_SIGN =>
  2748.             if RIGHT.SIGN = POS_SIGN then
  2749.                -- both are positive
  2750.                if LEFT.EXPONENT > RIGHT.EXPONENT then 
  2751.                   return TRUE;
  2752.                elsif LEFT.EXPONENT < RIGHT.EXPONENT then
  2753.                   return FALSE;
  2754.                else
  2755.                   return 
  2756.                    (LEFT.COMPS.COMPONENT_ARRAY >= RIGHT.COMPS.COMPONENT_ARRAY);
  2757.                end if;
  2758.             else
  2759.                -- left is positive, right is negative
  2760.                return TRUE;
  2761.             end if;
  2762.          when NEG_SIGN =>
  2763.             if RIGHT.SIGN = NEG_SIGN then
  2764.                -- both are negative
  2765.                if LEFT.EXPONENT < RIGHT.EXPONENT then 
  2766.                   return TRUE;
  2767.                elsif LEFT.EXPONENT > RIGHT.EXPONENT then
  2768.                   return FALSE;
  2769.                else
  2770.                   return 
  2771.                    (LEFT.COMPS.COMPONENT_ARRAY <= RIGHT.COMPS.COMPONENT_ARRAY);
  2772.                end if;
  2773.             else
  2774.                -- left is negative, right is positive
  2775.                return FALSE;
  2776.             end if;
  2777.       end case;
  2778.  
  2779.    exception
  2780.       when others =>
  2781.          raise MAE_NUMERIC_ERROR;
  2782.  
  2783.    end ">=";
  2784.  
  2785. ------------------------------
  2786.  
  2787.    function "+"    (RIGHT : MAE_SHORT_FLOAT_TYPE) 
  2788.                        return MAE_SHORT_FLOAT_TYPE is
  2789.    begin
  2790.       -- No action needed
  2791.       return RIGHT;
  2792.    end "+";
  2793.  
  2794. ------------------------------
  2795.  
  2796.    function "-"    (RIGHT : MAE_SHORT_FLOAT_TYPE) 
  2797.                        return MAE_SHORT_FLOAT_TYPE is
  2798.       RESULT : MAE_SHORT_FLOAT_TYPE := RIGHT;
  2799.    begin
  2800.       RESULT.SIGN := CHANGE_SIGN(RIGHT.SIGN);
  2801.       return RESULT;
  2802.    end "-";
  2803.  
  2804. ------------------------------
  2805.  
  2806.    function "abs"  (RIGHT : MAE_SHORT_FLOAT_TYPE) 
  2807.                        return MAE_SHORT_FLOAT_TYPE is
  2808.       RESULT : MAE_SHORT_FLOAT_TYPE := RIGHT;
  2809.    begin
  2810.       RESULT.SIGN := POS_SIGN;
  2811.       return RESULT;
  2812.    end "abs";
  2813.  
  2814. -------------------------------------------------------------------
  2815.  
  2816.    procedure ROUND_TO_TARGET (RESULT : in out MAE_SHORT_FLOAT_TYPE) is
  2817.       -- The purpose of this function is perform an underflow
  2818.       -- check (if true set result to zero), and overflow check
  2819.       -- (raise constraint error), then to round the float type
  2820.       -- so as to match the emulated target.
  2821.       -- The input array must be normalized.
  2822. -- --------------------------------------------------------------
  2823. --
  2824. --               Rounding Technique Summary
  2825. --
  2826. -- --------------------------------------------------------------
  2827. --
  2828. --      LSB    : the least significant bit
  2829. --      GUARD  : the guard bit, first bit beyond LSB
  2830. --      STICKY : the logical "or" of all bits beyond GUARD
  2831. --
  2832. --
  2833. --              BEFORE ROUNDING             AFTER ROUNDING
  2834. --   
  2835. --      LSB   |  GUARD  | STICKY  ||   LSB   | HOW ROUNDED ?
  2836. --   --------------------------------------------------------
  2837. --       0    |    0    |    0    ||    0    | exact
  2838. --       0    |    0    |    1    ||    0    | down (0<x<.5)
  2839. --       0    |    1    |    0    ||    0    | down (.5)
  2840. --       0    |    1    |    1    ||    1    | up (.5<x<1)
  2841. --       1    |    0    |    0    ||    1    | exact
  2842. --       1    |    0    |    1    ||    1    | down (0<x<.5)
  2843. --       1    |    1    |    0    ||    0*   | up (.5)
  2844. --       1    |    1    |    1    ||    0*   | up (.5<x<1)
  2845. --
  2846. --       * note that a carry to the bit above the LSB occurs
  2847. --
  2848. --    The references to 0, .5, and 1, are with respect to the
  2849. --    least significant bit in the binary representation. 
  2850. --    For example, the representative value of the guard bit 
  2851. --    is one-half the representative value of the least 
  2852. --    significant bit, and the maximum value that can be 
  2853. --    represented by the sticky bit is (.499999 ...) times
  2854. --    the representative value of the least significant bit.
  2855. --     
  2856. -- --------------------------------------------------------------
  2857.       C_RESULT : SHORT_COMPONENT_ARRAY := RESULT.COMPS.COMPONENT_ARRAY;
  2858.       LSC, LSB, LSB_FLAG : INTEGER;
  2859.       GUARD, GUARD_FLAG, GUARD_COMP : INTEGER;
  2860.       STICKY, STICKY_FLAG : INTEGER;
  2861.       CARRY, INDEX : INTEGER;
  2862.    begin
  2863.       -- Check for overflow.
  2864.       if (RESULT.EXPONENT < MIN_EXPONENT_VALUE) then
  2865.          RESULT := ZERO;
  2866.       elsif (RESULT.EXPONENT > MAX_EXPONENT_VALUE) then
  2867.          raise MAE_SHORT_FLOAT_OVERFLOW;
  2868.       else
  2869.          -- Determine the position of the least signif bit (lsb)
  2870.          -- (which is inside of the least signif comp, lsc)
  2871.          -- in the array. The next bit is the guard bit.  The next
  2872.          -- is the sticky bit which is the logical or of all the
  2873.          -- bits after guard.
  2874.          LSC := ((SHORT_NUM_BITS - TARGET_SHORT_NUM_BITS) / NO_COMP_BITS) + 1;
  2875.          LSB := ((TARGET_SHORT_NUM_BITS-1) rem NO_COMP_BITS) + 1;
  2876.  
  2877.          if SHORT_FLOAT_MACHINE_ROUNDS then
  2878.             -- Get the value (0 or 1) of the lsb
  2879.             LSB_FLAG := ((C_RESULT(LSC) / BIT_VALUE(LSB)) rem 2);
  2880.  
  2881.             -- The guard bit is one bit after lsb.
  2882.             if LSB /= NO_COMP_BITS then
  2883.                GUARD := LSB + 1;
  2884.                GUARD_COMP := LSC;
  2885.             else
  2886.                GUARD := 1;
  2887.                GUARD_COMP := LSC - 1;
  2888.             end if;
  2889.             -- Get the guard bit value.
  2890.             GUARD_FLAG := ((C_RESULT(GUARD_COMP) / BIT_VALUE(GUARD)) rem 2);
  2891.  
  2892.             -- If guard bit equaled 0, then no rounding necessary.
  2893.             if GUARD_FLAG /= 0 then
  2894.                -- Otherwise determine the sticky bit
  2895.                if GUARD /= NO_COMP_BITS then
  2896.                   STICKY := GUARD + 1;
  2897.                else 
  2898.                   STICKY := 1;
  2899.                end if;
  2900.  
  2901.                -- Initial sticky bit value is 0.
  2902.                STICKY_FLAG := 0;
  2903.                -- First check the remaining bits in the comp where
  2904.                -- the sticky bit is located.
  2905.                if (C_RESULT(GUARD_COMP) rem BIT_VALUE(GUARD)) /= 0 then
  2906.                   STICKY_FLAG := 1;
  2907.                else
  2908.                   -- Now check the remaining bits in the array
  2909.                   for I in GUARD_COMP+1 .. SHORT_NUM_COMPS loop
  2910.                      if C_RESULT(I) /= 0 then
  2911.                         STICKY_FLAG := 1;
  2912.                         exit;
  2913.                      end if;
  2914.                   end loop;
  2915.                end if;
  2916.  
  2917.                -- Check for round for (.5 <= x < 1), recall the guard bit=1.
  2918.                if (STICKY_FLAG = 1) or (LSB_FLAG = 1) then
  2919.                   C_RESULT(LSC) := C_RESULT(LSC) + BIT_VALUE(LSB);
  2920.                   -- Do an inline RANGE_CHECK
  2921.                   INDEX := LSC;
  2922.                   while C_RESULT(INDEX) > MAX_COMP_VALUE loop
  2923.                      CARRY := C_RESULT(INDEX) / BASE_COMP_VALUE;
  2924.                      C_RESULT(INDEX) := C_RESULT(INDEX) mod BASE_COMP_VALUE;
  2925.                      INDEX := INDEX + 1;
  2926.                      C_RESULT(INDEX) := C_RESULT(INDEX) + CARRY;
  2927.                      -- If it carries all the way up to the most
  2928.                      -- signif bit, divide the array by two and
  2929.                      -- bump the exponent. 
  2930.                      if INDEX = SHORT_NUM_COMPS then
  2931.                         if C_RESULT(INDEX) > MAX_COMP_VALUE then
  2932.                            DIVIDE_ARRAY_BY_TWO(C_RESULT);
  2933.                            RESULT.EXPONENT := RESULT.EXPONENT + 1;
  2934.                         end if;
  2935.                      end if;
  2936.                   end loop;
  2937.                end if;
  2938.             end if;
  2939.          end if;
  2940.  
  2941.          -- Zero out the lower portion of the array
  2942.          C_RESULT(LSC) := (C_RESULT(LSC) / BIT_VALUE(LSB)) * BIT_VALUE(LSB);
  2943.          for I in 1 .. LSC-1 loop
  2944.             C_RESULT(I) := 0;
  2945.          end loop;
  2946.  
  2947.          RESULT.COMPS.COMPONENT_ARRAY := C_RESULT;
  2948.       end if;
  2949.  
  2950.    exception
  2951.       when others =>
  2952.          raise MAE_NUMERIC_ERROR;
  2953.  
  2954.    end ROUND_TO_TARGET;
  2955.  
  2956. ------------------------------
  2957.  
  2958.    procedure NORMALIZE_SHORT_FLOAT (RESULT : in out MAE_SHORT_FLOAT_TYPE) is
  2959.       -- The purpose of this function is to normalize the
  2960.       -- the float type so as to maintain accuracy during
  2961.       -- computations.
  2962.       SHIFT_BITS : INTEGER := 0;
  2963.    begin
  2964.       ARRAY_NORMALIZE(RESULT.COMPS.COMPONENT_ARRAY, SHIFT_BITS);
  2965.       RESULT.EXPONENT := RESULT.EXPONENT - SHIFT_BITS;
  2966.    end NORMALIZE_SHORT_FLOAT;
  2967.  
  2968. ------------------------------
  2969.  
  2970.    function ALIGN (ADD_VALUE : MAE_SHORT_FLOAT_TYPE; MATCH_EXP : INTEGER)
  2971.                                         return MAE_SHORT_FLOAT_TYPE is
  2972.       -- The purpose of this function is to shift the intermediate,
  2973.       -- to be used in an add/subtract operation, so that the 
  2974.       -- exponent equals the MATCH_EXP.
  2975.       INTERMEDIATE : MAE_SHORT_FLOAT_TYPE := ADD_VALUE;
  2976.       SHIFT_BITS : INTEGER;
  2977.    begin
  2978.       -- determine the number of bits to be shifted
  2979.       SHIFT_BITS := MATCH_EXP - INTERMEDIATE.EXPONENT;
  2980.       -- check if the number is shifted beyond significance
  2981.       if SHIFT_BITS >= SHORT_NUM_BITS then
  2982.          return ZERO;
  2983.       elsif SHIFT_BITS < 1 then
  2984.          raise MAE_NUMERIC_ERROR;
  2985.       else
  2986.  
  2987.          -- rounding may be needed here
  2988.  
  2989.          ARRAY_TRUNCATION_SHIFT_RIGHT(INTERMEDIATE.COMPS.COMPONENT_ARRAY,
  2990.                                           SHIFT_BITS);
  2991.          INTERMEDIATE.EXPONENT := MATCH_EXP;
  2992.          return INTERMEDIATE;
  2993.       end if;
  2994.  
  2995.    exception
  2996.       when others =>
  2997.          raise MAE_NUMERIC_ERROR;
  2998.  
  2999.    end ALIGN;
  3000.  
  3001. -------------------------------------------------------------------
  3002.  
  3003.    function "+"    (LEFT,RIGHT : MAE_SHORT_FLOAT_TYPE) 
  3004.                        return MAE_SHORT_FLOAT_TYPE is
  3005.       -- The purpose of this function is to add two
  3006.       -- MAE_SHORT_FLOAT_TYPEs.
  3007.       RESULT, TEMP : MAE_SHORT_FLOAT_TYPE;
  3008.    begin
  3009.       -- zero check
  3010.       if RIGHT.COMPS.COMPONENT_ARRAY = ZERO.COMPS.COMPONENT_ARRAY then
  3011.          RESULT := LEFT;
  3012.          NORMALIZE_SHORT_FLOAT(RESULT);
  3013.          ROUND_TO_TARGET(RESULT);
  3014.          return RESULT;
  3015.       elsif LEFT.COMPS.COMPONENT_ARRAY = ZERO.COMPS.COMPONENT_ARRAY then
  3016.          RESULT := RIGHT;
  3017.          NORMALIZE_SHORT_FLOAT(RESULT);
  3018.          ROUND_TO_TARGET(RESULT);
  3019.          return RESULT;
  3020.       end if;
  3021.  
  3022.       case (LEFT.SIGN xor RIGHT.SIGN) is
  3023.          -- The signs are different (subtraction)
  3024.          when TRUE =>
  3025.             if LEFT.EXPONENT > RIGHT.EXPONENT then
  3026.                TEMP := ALIGN(RIGHT, LEFT.EXPONENT);
  3027.                RESULT.COMPS := LEFT.COMPS - TEMP.COMPS;
  3028.                RESULT.EXPONENT := LEFT.EXPONENT - RESULT.COMPS.BITS_SHIFTED;
  3029.                RESULT.SIGN := LEFT.SIGN;
  3030.             elsif LEFT.EXPONENT < RIGHT.EXPONENT then
  3031.                TEMP := ALIGN(LEFT, RIGHT.EXPONENT);
  3032.                RESULT.COMPS := RIGHT.COMPS - TEMP.COMPS;
  3033.                RESULT.EXPONENT := RIGHT.EXPONENT - RESULT.COMPS.BITS_SHIFTED;
  3034.                RESULT.SIGN := RIGHT.SIGN;
  3035.             else
  3036.                if LEFT.COMPS.COMPONENT_ARRAY > RIGHT.COMPS.COMPONENT_ARRAY then
  3037.                   RESULT.COMPS := LEFT.COMPS - RIGHT.COMPS;
  3038.                   RESULT.EXPONENT := LEFT.EXPONENT - RESULT.COMPS.BITS_SHIFTED;
  3039.                   RESULT.SIGN := LEFT.SIGN;
  3040.                else
  3041.                   RESULT.COMPS := RIGHT.COMPS - LEFT.COMPS;
  3042.                   RESULT.EXPONENT := RIGHT.EXPONENT - RESULT.COMPS.BITS_SHIFTED;
  3043.                   RESULT.SIGN := RIGHT.SIGN;
  3044.                end if;
  3045.             end if;
  3046.          -- The signs are the same
  3047.          when FALSE =>
  3048.             if LEFT.EXPONENT > RIGHT.EXPONENT then
  3049.                TEMP := ALIGN(RIGHT, LEFT.EXPONENT);
  3050.                RESULT.COMPS := LEFT.COMPS + TEMP.COMPS;
  3051.                RESULT.EXPONENT := LEFT.EXPONENT - RESULT.COMPS.BITS_SHIFTED;
  3052.                RESULT.SIGN := LEFT.SIGN;
  3053.             elsif LEFT.EXPONENT < RIGHT.EXPONENT then
  3054.                TEMP := ALIGN(LEFT, RIGHT.EXPONENT);
  3055.                RESULT.COMPS := RIGHT.COMPS + TEMP.COMPS;
  3056.                RESULT.EXPONENT := RIGHT.EXPONENT - RESULT.COMPS.BITS_SHIFTED;
  3057.                RESULT.SIGN := RIGHT.SIGN;
  3058.             else
  3059.                RESULT.COMPS := LEFT.COMPS + RIGHT.COMPS;
  3060.                RESULT.EXPONENT := LEFT.EXPONENT - RESULT.COMPS.BITS_SHIFTED;
  3061.                RESULT.SIGN := RIGHT.SIGN;
  3062.             end if;
  3063.  
  3064.       end case;
  3065.  
  3066.       RESULT.COMPS.BITS_SHIFTED := 0;
  3067.       if RESULT.COMPS = ZERO.COMPS then
  3068.          RESULT.EXPONENT := 0;
  3069.          RESULT.SIGN := POS_SIGN;
  3070.       end if;
  3071.  
  3072.       ROUND_TO_TARGET(RESULT);
  3073.       return RESULT;
  3074.  
  3075.    exception
  3076.       when others =>
  3077.          raise MAE_NUMERIC_ERROR;
  3078.  
  3079.    end "+";
  3080.  
  3081. ------------------------------
  3082.  
  3083.    function "-"    (LEFT,RIGHT : MAE_SHORT_FLOAT_TYPE) 
  3084.                        return MAE_SHORT_FLOAT_TYPE is
  3085.       -- The purpose of this function is to subtract two
  3086.       -- MAE_SHORT_FLOAT_TYPEs.
  3087.       RESULT : MAE_SHORT_FLOAT_TYPE;
  3088.    begin
  3089.       -- subtract is the same as add negative
  3090.       RESULT := LEFT + (-RIGHT);
  3091.  
  3092.       return RESULT;
  3093.  
  3094.    exception
  3095.       when others =>
  3096.          raise MAE_NUMERIC_ERROR;
  3097.  
  3098.    end "-";
  3099.  
  3100. ------------------------------
  3101.  
  3102.    function "*"    (LEFT,RIGHT : MAE_SHORT_FLOAT_TYPE) 
  3103.                        return MAE_SHORT_FLOAT_TYPE is
  3104.       -- The purpose of this function is to multiply two
  3105.       -- MAE_SHORT_FLOAT_TYPEs.
  3106.       RESULT : MAE_SHORT_FLOAT_TYPE;
  3107.    begin
  3108.       RESULT.SIGN := not (LEFT.SIGN xor RIGHT.SIGN);
  3109.       -- zero check
  3110.       if (LEFT.COMPS.COMPONENT_ARRAY = ZERO.COMPS.COMPONENT_ARRAY) or
  3111.            (RIGHT.COMPS.COMPONENT_ARRAY = ZERO.COMPS.COMPONENT_ARRAY) then
  3112.          return ZERO;
  3113.       -- one check
  3114.       elsif (LEFT = ONE) or (LEFT = -ONE) then
  3115.          RESULT.COMPS := RIGHT.COMPS;
  3116.          RESULT.EXPONENT := RIGHT.EXPONENT;
  3117.          NORMALIZE_SHORT_FLOAT(RESULT);
  3118.          ROUND_TO_TARGET(RESULT);
  3119.          return RESULT;
  3120.       elsif (RIGHT = ONE) or (RIGHT = -ONE) then
  3121.          RESULT.COMPS := LEFT.COMPS;
  3122.          RESULT.EXPONENT := LEFT.EXPONENT;
  3123.          NORMALIZE_SHORT_FLOAT(RESULT);
  3124.          ROUND_TO_TARGET(RESULT);
  3125.          return RESULT;
  3126.       end if;
  3127.  
  3128.       RESULT.COMPS := LEFT.COMPS * RIGHT.COMPS;
  3129.       if RESULT.COMPS.COMPONENT_ARRAY = ZERO.COMPS.COMPONENT_ARRAY then
  3130.          RESULT.EXPONENT := 0;
  3131.          RESULT.SIGN := POS_SIGN;
  3132.       else
  3133.          RESULT.EXPONENT := (LEFT.EXPONENT + RIGHT.EXPONENT)
  3134.                              - RESULT.COMPS.BITS_SHIFTED;
  3135.       end if;
  3136.       RESULT.COMPS.BITS_SHIFTED := 0;
  3137.  
  3138.       ROUND_TO_TARGET(RESULT);
  3139.       return RESULT;
  3140.  
  3141.    exception
  3142.       when others =>
  3143.          raise MAE_NUMERIC_ERROR;
  3144.  
  3145.    end "*";
  3146.  
  3147. ------------------------------
  3148.  
  3149.    function "/"    (LEFT,RIGHT : MAE_SHORT_FLOAT_TYPE) 
  3150.                        return MAE_SHORT_FLOAT_TYPE is
  3151.       -- The purpose of this function is to divide two
  3152.       -- MAE_SHORT_FLOAT_TYPEs.
  3153.       RESULT : MAE_SHORT_FLOAT_TYPE;
  3154.    begin
  3155.       RESULT.SIGN := not (LEFT.SIGN xor RIGHT.SIGN);
  3156.       -- zero check
  3157.       if (RIGHT.COMPS.COMPONENT_ARRAY = ZERO.COMPS.COMPONENT_ARRAY) then
  3158.          raise MAE_NUMERIC_ERROR;
  3159.       elsif (LEFT.COMPS.COMPONENT_ARRAY = ZERO.COMPS.COMPONENT_ARRAY) then
  3160.          return ZERO;
  3161.       -- one check
  3162.       elsif (RIGHT = ONE) or (RIGHT = -ONE) then
  3163.          RESULT.COMPS := LEFT.COMPS;
  3164.          RESULT.EXPONENT := LEFT.EXPONENT;
  3165.          NORMALIZE_SHORT_FLOAT(RESULT);
  3166.          ROUND_TO_TARGET(RESULT);
  3167.          return RESULT;
  3168.       end if;
  3169.  
  3170.       RESULT.COMPS := LEFT.COMPS / RIGHT.COMPS;
  3171.       if RESULT.COMPS.COMPONENT_ARRAY = ZERO.COMPS.COMPONENT_ARRAY then
  3172.          RESULT.EXPONENT := 0;
  3173.          RESULT.SIGN := POS_SIGN;
  3174.       else
  3175.          RESULT.EXPONENT := (LEFT.EXPONENT - RIGHT.EXPONENT)
  3176.                             - RESULT.COMPS.BITS_SHIFTED;
  3177.       end if;
  3178.       RESULT.COMPS.BITS_SHIFTED := 0;
  3179.  
  3180.       ROUND_TO_TARGET(RESULT);
  3181.       return RESULT;
  3182.  
  3183.    exception
  3184.       when others =>
  3185.          raise MAE_NUMERIC_ERROR;
  3186.  
  3187.    end "/";
  3188.  
  3189. ------------------------------
  3190.  
  3191.    function MULT (LEFT,RIGHT : MAE_SHORT_FLOAT_TYPE) 
  3192.                        return MAE_SHORT_FLOAT_TYPE is
  3193.       -- The purpose of this function is to multiply two
  3194.       -- MAE_SHORT_FLOAT_TYPEs without rounding to the target
  3195.       -- precision.  This allows the exponentiation and
  3196.       -- string conversion routines to maintain accuracy.
  3197.       RESULT : MAE_SHORT_FLOAT_TYPE;
  3198.    begin
  3199.       RESULT.SIGN := not (LEFT.SIGN xor RIGHT.SIGN);
  3200.       RESULT.COMPS := LEFT.COMPS * RIGHT.COMPS;
  3201.       if RESULT.COMPS.COMPONENT_ARRAY = ZERO.COMPS.COMPONENT_ARRAY then
  3202.          RESULT.EXPONENT := 0;
  3203.          RESULT.SIGN := POS_SIGN;
  3204.       else
  3205.          RESULT.EXPONENT := (LEFT.EXPONENT + RIGHT.EXPONENT)
  3206.                              - RESULT.COMPS.BITS_SHIFTED;
  3207.       end if;
  3208.       RESULT.COMPS.BITS_SHIFTED := 0;
  3209.  
  3210.       return RESULT;
  3211.  
  3212.    exception
  3213.       when others =>
  3214.          raise MAE_NUMERIC_ERROR;
  3215.  
  3216.    end MULT;
  3217.  
  3218. ------------------------------
  3219.  
  3220.    function ADD (LEFT,RIGHT : MAE_SHORT_FLOAT_TYPE) 
  3221.                        return MAE_SHORT_FLOAT_TYPE is
  3222.       -- The purpose of this function is to add two
  3223.       -- MAE_SHORT_FLOAT_TYPEs without rounding to the target
  3224.       -- precision.  This allows the exponentiation and
  3225.       -- string conversion routines to maintain accuracy.
  3226.       -- Since it has a specialized operation, both operator
  3227.       -- signs are assumed positive.
  3228.       RESULT, TEMP : MAE_SHORT_FLOAT_TYPE;
  3229.    begin
  3230.       -- The signs are the same
  3231.       if LEFT.EXPONENT > RIGHT.EXPONENT then
  3232.          TEMP := ALIGN(RIGHT, LEFT.EXPONENT);
  3233.          RESULT.COMPS := LEFT.COMPS + TEMP.COMPS;
  3234.          RESULT.EXPONENT := LEFT.EXPONENT - RESULT.COMPS.BITS_SHIFTED;
  3235.       elsif LEFT.EXPONENT < RIGHT.EXPONENT then
  3236.          TEMP := ALIGN(LEFT, RIGHT.EXPONENT);
  3237.          RESULT.COMPS := RIGHT.COMPS + TEMP.COMPS;
  3238.          RESULT.EXPONENT := RIGHT.EXPONENT - RESULT.COMPS.BITS_SHIFTED;
  3239.       else
  3240.          RESULT.COMPS := LEFT.COMPS + RIGHT.COMPS;
  3241.          RESULT.EXPONENT := LEFT.EXPONENT - RESULT.COMPS.BITS_SHIFTED;
  3242.       end if;
  3243.  
  3244.       RESULT.SIGN := POS_SIGN;
  3245.       RESULT.COMPS.BITS_SHIFTED := 0;
  3246.       if RESULT.COMPS = ZERO.COMPS then
  3247.          RESULT.EXPONENT := 0;
  3248.          RESULT.SIGN := POS_SIGN;
  3249.       end if;
  3250.  
  3251.       return RESULT;
  3252.  
  3253.    exception
  3254.       when others =>
  3255.          raise MAE_NUMERIC_ERROR;
  3256.  
  3257.    end ADD;
  3258.  
  3259. ------------------------------
  3260.  
  3261.    function "**"   (LEFT : MAE_SHORT_FLOAT_TYPE; RIGHT : INTEGER)
  3262.                        return MAE_SHORT_FLOAT_TYPE is
  3263.    -- The purpose of this function is to raise a MAE_SHORT_FLOAT_TYPE
  3264.    -- to a given power.  A simple loop with a multiplication could
  3265.    -- be done the given number, less one, times.  This method is
  3266.    -- inefficient, therefore a different algorithm is used.
  3267.    -- The use of additional memory to hold intermediate
  3268.    -- calculations will improve performance by reducing
  3269.    -- the number of multiplications.
  3270.       COUNT : INTEGER := RIGHT;
  3271.       REM_COUNT : INTEGER := RIGHT;
  3272.       RESULT : MAE_SHORT_FLOAT_TYPE;
  3273.       POWER_2, POWER_4, POWER_8 : MAE_SHORT_FLOAT_TYPE := ZERO;
  3274.       NEG_SIGN_EXP_FLAG : BOOLEAN := FALSE;
  3275.    begin
  3276.       -- If the power is less than 0, set a flag that will determine
  3277.       -- if the result is to be inverted.
  3278.       if (COUNT < 0) then
  3279.          if LEFT = ZERO then
  3280.             raise MAE_NUMERIC_ERROR;
  3281.          end if;
  3282.          if COUNT = -1 then
  3283.             RESULT := ONE / LEFT;
  3284.             return RESULT;
  3285.          end if;
  3286.          NEG_SIGN_EXP_FLAG := TRUE;
  3287.          COUNT := abs(COUNT);
  3288.          REM_COUNT := COUNT;
  3289.       end if;
  3290.       -- if the power is 0, return 1
  3291.       if COUNT = 0 then return ONE;
  3292.       -- if the power is 1 or the number is 0 or 1, return the input number
  3293.       elsif (COUNT = 1) or (LEFT = ONE) or (LEFT = ZERO) then return LEFT;
  3294.       elsif COUNT > TWO_THREE_LESS_ONE then
  3295.          -- compute to POWER_8
  3296.          POWER_2 := MULT(LEFT, LEFT);
  3297.          POWER_4 := MULT(POWER_2, POWER_2);
  3298.          POWER_8 := MULT(POWER_4, POWER_4);
  3299.          RESULT := POWER_8;
  3300.          REM_COUNT := REM_COUNT - 8;
  3301.       elsif COUNT > TWO_TWO_LESS_ONE then
  3302.          -- compute to POWER_4
  3303.          POWER_2 := MULT(LEFT, LEFT);
  3304.          POWER_4 := MULT(POWER_2, POWER_2);
  3305.          RESULT := POWER_4;
  3306.          REM_COUNT := REM_COUNT - 4;
  3307.       else
  3308.          -- compute to POWER_2
  3309.          POWER_2 := MULT(LEFT, LEFT);
  3310.          RESULT := POWER_2;
  3311.          REM_COUNT := REM_COUNT - 2;
  3312.       end if;
  3313.  
  3314.       -- the pre-computed values are now used to build
  3315.       -- to the answer
  3316.  
  3317.       -- loop until the power is reduced to under the
  3318.       -- maximum pre-computed value
  3319.       loop
  3320.          if REM_COUNT < TWO_THREE then 
  3321.            exit;
  3322.          end if;
  3323.          RESULT := MULT(RESULT, POWER_8);
  3324.          REM_COUNT := REM_COUNT - 8;
  3325.       end loop;
  3326.  
  3327.       -- the remaining power may be between 4 .. 7
  3328.       if REM_COUNT > TWO_TWO_LESS_ONE then
  3329.          RESULT := MULT(RESULT, POWER_4);
  3330.          REM_COUNT := REM_COUNT - 4;
  3331.       end if;
  3332.  
  3333.       -- the remaining power may be between 2 .. 3
  3334.       if REM_COUNT > 1 then
  3335.          RESULT := MULT(RESULT, POWER_2);
  3336.          REM_COUNT := REM_COUNT - 2;
  3337.       end if;
  3338.  
  3339.       -- The remaining power may be 1, therefore the sign
  3340.       -- is negative if the input number is negative
  3341.       if REM_COUNT = 1 then
  3342.          RESULT := MULT(RESULT, LEFT);
  3343.       end if;
  3344.  
  3345.       -- If exponent was negative, the result is inverted
  3346.       if NEG_SIGN_EXP_FLAG then
  3347.          RESULT := ONE / RESULT;
  3348.       end if;
  3349.  
  3350.       ROUND_TO_TARGET(RESULT);
  3351.       return RESULT;
  3352.  
  3353.    exception
  3354.       when others =>
  3355.          raise MAE_NUMERIC_ERROR;
  3356.  
  3357.    end "**";
  3358.  
  3359. ------------------------------
  3360.  
  3361.    procedure GET(FROM : in STRING;
  3362.                  ITEM : out MAE_SHORT_FLOAT_TYPE;
  3363.                  LAST : out POSITIVE) is
  3364.    -- The purpose of this function is to convert a string
  3365.    -- of characters into the MAE_SHORT_FLOAT_TYPE structure.
  3366.    -- The string is valid if an only if it conforms to the
  3367.    -- format specified by the LRM
  3368.    --
  3369.    -- FORE . AFT
  3370.    -- FORE . AFT E EXP
  3371.    -- where 
  3372.    --    FORE : decimal digits, optional leading spaces,
  3373.    --            and a minus sign for negative values
  3374.    --    "."  : the decimal point
  3375.    --    AFT  : decimal digits
  3376.    --    EXP  : sign (plus or minus) and exponent
  3377.    --
  3378.    -- and is within the specified range for 
  3379.    -- MAE_SHORT_FLOAT_TYPEs.
  3380.       INDEX : INTEGER;
  3381.       RESULT, TEMP, MULTIPLIER : MAE_SHORT_FLOAT_TYPE;
  3382.       NEG_SIGN_FLAG : BOOLEAN := FALSE;
  3383.       FRACTION_FLAG, EXPONENT_FLAG, NEG_SIGN_EXP_FLAG : BOOLEAN := FALSE;
  3384.       EMPTY_FLAG : BOOLEAN := TRUE;
  3385.       S_PTR, POWER_OF_TEN, BASE_TEN_EXP : INTEGER := 0;
  3386.  
  3387.    begin
  3388.       -- Strip leading spaces if necessary
  3389.       INDEX := FROM'first;
  3390.       for I in FROM'first .. FROM'last loop
  3391.          if FROM(I) /= ' ' then
  3392.             exit;
  3393.          else
  3394.             INDEX := INDEX + 1;
  3395.          end if;
  3396.          -- if the string is empty
  3397.          if INDEX > FROM'last then
  3398.             raise MAE_FORMAT_ERROR;
  3399.          end if;
  3400.       end loop;
  3401.  
  3402.       -- Set the sign flag(assigned to the result sign before exiting).
  3403.       if FROM(INDEX) = '-' then
  3404.          NEG_SIGN_FLAG := TRUE;
  3405.          INDEX := INDEX + 1;
  3406.       elsif FROM(INDEX) = '+' then
  3407.          INDEX := INDEX + 1;
  3408.       end if;
  3409.  
  3410.       -- if the string is empty
  3411.       if INDEX > FROM'last then
  3412.          raise MAE_FORMAT_ERROR;
  3413.       end if;
  3414.  
  3415.       -- Store the integer portion
  3416.  
  3417.       for I in INDEX .. FROM'last loop
  3418.          S_PTR := I;
  3419.  
  3420.          case FROM(I) is
  3421.             when '0' .. '9' =>
  3422.                -- Multiply old result by ten and add in the digit
  3423.                -- (recall that MULT is multiply, ADD is add)
  3424.  
  3425.                RESULT := MULT(RESULT, TEN);
  3426.                case FROM(I) is
  3427.  
  3428.                   when '0' => null;
  3429.                   when '1' => RESULT := ADD(RESULT, ONE);
  3430.                   when '2' => RESULT := ADD(RESULT, TWO);
  3431.                   when '3' => RESULT := ADD(RESULT, THREE);
  3432.                   when '4' => RESULT := ADD(RESULT, FOUR);
  3433.                   when '5' => RESULT := ADD(RESULT, FIVE);
  3434.                   when '6' => RESULT := ADD(RESULT, SIX);
  3435.                   when '7' => RESULT := ADD(RESULT, SEVEN);
  3436.                   when '8' => RESULT := ADD(RESULT, EIGHT);
  3437.                   when '9' => RESULT := ADD(RESULT, NINE);
  3438.                   when others => raise MAE_FORMAT_ERROR;
  3439.                end case;
  3440.                -- Once a digit is encountered set empty false
  3441.                EMPTY_FLAG := FALSE;
  3442.                -- If the digit followed the decimal point increase
  3443.                -- the exponent counter
  3444.                if FRACTION_FLAG then
  3445.                   POWER_OF_TEN := POWER_OF_TEN + 1;
  3446.                end if;
  3447.  
  3448.             when ' ' =>
  3449.                -- If there is a space, before a digit, after the sign 
  3450.                -- exception, else check if it is the end of the number
  3451.                if EMPTY_FLAG then
  3452.                   -- spaces after the sign
  3453.                   raise MAE_FORMAT_ERROR;
  3454.                else
  3455.                   for J in I+1 .. FROM'last loop
  3456.                      if FROM(J) /= ' ' then
  3457.                         raise MAE_FORMAT_ERROR;
  3458.                      end if;
  3459.                   end loop;
  3460.                   exit;
  3461.                end if;
  3462.  
  3463.             when '.' => 
  3464.                if FRACTION_FLAG or EMPTY_FLAG then
  3465.                   -- two decimal points, or leading point
  3466.                   raise MAE_FORMAT_ERROR;
  3467.                else
  3468.                   FRACTION_FLAG := TRUE;
  3469.                end if;
  3470.  
  3471.             when 'e' | 'E' => 
  3472.                if EMPTY_FLAG then
  3473.                   -- no decimal number
  3474.                   raise MAE_FORMAT_ERROR;
  3475.                else
  3476.                   -- Set the exponent flag on
  3477.                   EXPONENT_FLAG := TRUE;
  3478.                   exit;
  3479.                end if;
  3480.  
  3481.             when others => raise MAE_FORMAT_ERROR;
  3482.          end case;
  3483.       end loop;
  3484.  
  3485.       -- Set the sign
  3486.       if NEG_SIGN_FLAG then
  3487.          RESULT.SIGN := NEG_SIGN;
  3488.       else
  3489.          RESULT.SIGN := POS_SIGN;
  3490.       end if;
  3491.  
  3492.  
  3493.       -- If the string contained the 'E' determine the exponent
  3494.       if EXPONENT_FLAG then
  3495.          EMPTY_FLAG := TRUE;
  3496.  
  3497.          -- Check the sign 
  3498.          S_PTR := S_PTR + 1;
  3499.          if FROM(S_PTR) = '-' then
  3500.             NEG_SIGN_EXP_FLAG := TRUE;
  3501.             INDEX := INDEX + 1;
  3502.          elsif FROM(S_PTR) = '+' then
  3503.             INDEX := INDEX + 1;
  3504.          else
  3505.             raise MAE_NUMERIC_ERROR;
  3506.          end if;
  3507.  
  3508.  
  3509.          for I in S_PTR+1 .. FROM'last loop
  3510.  
  3511.             case FROM(I) is
  3512.                when '0' .. '9' =>
  3513.                   case FROM(I) is
  3514.  
  3515.                      when '0' => BASE_TEN_EXP := BASE_TEN_EXP*10;
  3516.                      when '1' => BASE_TEN_EXP := BASE_TEN_EXP*10 + 1;
  3517.                      when '2' => BASE_TEN_EXP := BASE_TEN_EXP*10 + 2;
  3518.                      when '3' => BASE_TEN_EXP := BASE_TEN_EXP*10 + 3;
  3519.                      when '4' => BASE_TEN_EXP := BASE_TEN_EXP*10 + 4;
  3520.                      when '5' => BASE_TEN_EXP := BASE_TEN_EXP*10 + 5;
  3521.                      when '6' => BASE_TEN_EXP := BASE_TEN_EXP*10 + 6;
  3522.                      when '7' => BASE_TEN_EXP := BASE_TEN_EXP*10 + 7;
  3523.                      when '8' => BASE_TEN_EXP := BASE_TEN_EXP*10 + 8;
  3524.                      when '9' => BASE_TEN_EXP := BASE_TEN_EXP*10 + 9;
  3525.                      when others => raise MAE_FORMAT_ERROR;
  3526.                   end case;
  3527.                   EMPTY_FLAG := FALSE;
  3528.  
  3529.                when ' ' => 
  3530.                   if EMPTY_FLAG then
  3531.                      -- no exponent number
  3532.                     raise MAE_FORMAT_ERROR;
  3533.                   else
  3534.                      for J in I+1 .. FROM'last loop
  3535.                         if FROM(J) /= ' ' then
  3536.                            raise MAE_FORMAT_ERROR;
  3537.                         end if;
  3538.                      end loop;
  3539.                      exit;
  3540.                   end if;
  3541.  
  3542.                when others => raise MAE_FORMAT_ERROR;
  3543.  
  3544.             end case;
  3545.          end loop;
  3546.       end if;
  3547.  
  3548.       if EMPTY_FLAG or (POWER_OF_TEN = 0) then
  3549.          -- either (no number) or (no exponent) or (no fraction)
  3550.          raise MAE_FORMAT_ERROR;
  3551.       end if;
  3552.  
  3553.       if RESULT.COMPS = ZERO.COMPS then
  3554.          ITEM := ZERO;
  3555.       else
  3556.          -- If the base ten exponent was negative.
  3557.          if NEG_SIGN_EXP_FLAG then
  3558.             BASE_TEN_EXP := -BASE_TEN_EXP;
  3559.          end if;
  3560.  
  3561.          -- Now we must adjust the base ten exponent by the number of
  3562.          -- digits that follow the decimal point in the string.
  3563.          BASE_TEN_EXP := BASE_TEN_EXP - POWER_OF_TEN;
  3564.  
  3565.          -- If the input base ten exponent needs to be translated
  3566.          -- into a base two exponent, use the "and" routine to
  3567.          -- multiply but round after the final multiply.
  3568.          if BASE_TEN_EXP /= 0 then
  3569.            if BASE_TEN_EXP > 0 then
  3570.                while BASE_TEN_EXP >= 4 loop
  3571.                   RESULT := MULT(RESULT, TEN_THOUSAND);
  3572.                   BASE_TEN_EXP := BASE_TEN_EXP - 4;
  3573.                end loop;
  3574.                if BASE_TEN_EXP = 3 then
  3575.                   RESULT := MULT(RESULT, THOUSAND);
  3576.                end if;
  3577.                if BASE_TEN_EXP = 2 then
  3578.                   RESULT := MULT(RESULT, HUNDRED);
  3579.                end if;
  3580.                if BASE_TEN_EXP = 1 then
  3581.                   RESULT := MULT(RESULT, TEN);
  3582.                end if;
  3583.             else
  3584.                while BASE_TEN_EXP <= -4 loop
  3585.                   RESULT := MULT(RESULT, ONE_TEN_THOUSANDTH);
  3586.                   BASE_TEN_EXP := BASE_TEN_EXP + 4;
  3587.                end loop;
  3588.                if BASE_TEN_EXP = -3 then
  3589.                   RESULT := MULT(RESULT, ONE_THOUSANDTH);
  3590.                end if;
  3591.                if BASE_TEN_EXP = -2 then
  3592.                   RESULT := MULT(RESULT, ONE_HUNDREDTH);
  3593.                end if;
  3594.                if BASE_TEN_EXP = -1 then
  3595.                   RESULT := MULT(RESULT, ONE_TENTH);
  3596.                end if;
  3597.             end if;
  3598.          end if;
  3599.  
  3600.          ROUND_TO_TARGET(RESULT);
  3601.  
  3602.          ITEM := RESULT;
  3603.       end if;
  3604.  
  3605.       LAST := FROM'last;
  3606.  
  3607.  
  3608.    exception
  3609.       when others =>
  3610.          raise DATA_ERROR;
  3611.  
  3612.    end GET;
  3613.  
  3614. ------------------------------
  3615.  
  3616.    procedure MULT_BY_TEN (RESULT : in out COMPONENT_ARRAY_TYPE) is
  3617.       -- This routine is used by the binary to ASCII conversion
  3618.       -- (PUT) to extract the next digit by multiplying the
  3619.       -- array by ten, thus the digit is the most signif
  3620.       -- comp of the array "integer divided" by ten.
  3621.    begin
  3622.       for I in RESULT'first .. RESULT'last loop
  3623.          RESULT(I) := RESULT(I) * 10;
  3624.       end loop;
  3625.       RANGE_CHECK(RESULT);
  3626.  
  3627.    end MULT_BY_TEN;
  3628.  
  3629. ------------------------------
  3630.    procedure PUT(TO : out STRING;
  3631.                  ITEM : in MAE_SHORT_FLOAT_TYPE;
  3632.                  AFT : in FIELD := SHORT_DEFAULT_AFT;
  3633.                  EXP : in FIELD := SHORT_DEFAULT_EXP) is
  3634.       -- The purpose of this function is to convert a 
  3635.       -- MAE_SHORT_FLOAT_TYPE into string of characters.
  3636.       COMP_PTR, INDEX : INTEGER;
  3637.       RESULT : MAE_SHORT_FLOAT_TYPE := ITEM;
  3638.       WORK_ARRAY : SHORT_COMPONENT_ARRAY;
  3639.       TEMP_CHAR : STRING (1 .. 1);
  3640.       TEMP_VALUE : INTEGER;
  3641.       STRING_PIC : STRING (1 .. SHORT_FLOAT_DIGITS+1) :=
  3642.                       EMPTY_STRING(1 .. SHORT_FLOAT_DIGITS+1);
  3643.       DECIMAL_VALUE, OFFSET, OFFSET_BITS, POWER_OF_TEN : INTEGER := 0;
  3644.  
  3645.       LSB : INTEGER := (NO_COMP_BITS + 1 + (2*(SHORT_FLOAT_DIGITS)));
  3646.       LSC, BIT_IN_LSC : INTEGER;
  3647.  
  3648.       NEG_SIGN_FLAG, NEG_SIGN_EXP_FLAG : BOOLEAN := FALSE;
  3649.       DISPLAY_DIGITS : INTEGER := 0;
  3650.       FIRST_DIGIT : BOOLEAN := TRUE;
  3651.  
  3652.       TO_INDEX : INTEGER := 0;
  3653.       EXPONENT_STRING : STRING (1 .. 4) := "   0";
  3654.       EXPONENT_INDEX : INTEGER := 0;
  3655.       EXPONENT_LENGTH : INTEGER := 1;
  3656.  
  3657.       ALMOST_ZERO : MAE_SHORT_FLOAT_TYPE := ZERO;
  3658.  
  3659.       ACTUAL_FORE : INTEGER := 1;
  3660.       ACTUAL_AFT : INTEGER := AFT;
  3661.       ACTUAL_EXP : INTEGER := EXP;
  3662.  
  3663.       FORE_FIELD_ZERO_FLAG : BOOLEAN := FALSE;
  3664.       FORE_WIDTH_DIGITS_BEYOND_PRECISION : INTEGER := 0;
  3665.       AFT_WIDTH_DIGITS_BEYOND_PRECISION : INTEGER := 0;
  3666.       AFT_LEADING_ZERO_DIGITS : INTEGER := 0;
  3667.       SIGNIFICANT_AFT : INTEGER := 0;
  3668.  
  3669.    begin
  3670.       TO(TO'first .. TO'last) := EMPTY_STRING(1 .. TO'length);
  3671.  
  3672.       -- The variable INDEX is the pointer into the string.
  3673.       INDEX := STRING_PIC'first;
  3674.  
  3675.       -- Check for zero.
  3676.       if RESULT.COMPS /= ZERO.COMPS then
  3677.  
  3678.          -- Store the sign
  3679.          if RESULT.SIGN = NEG_SIGN then
  3680.             NEG_SIGN_FLAG := TRUE;
  3681.             RESULT.SIGN := POS_SIGN;
  3682.          end if;
  3683.    
  3684.          -- Determine the base ten exponent by forcing the result
  3685.          -- into the range .1 <= x < 1., and tracking the count.
  3686.          POWER_OF_TEN := -1;
  3687.          if RESULT < ONE then
  3688.             while RESULT < ONE_TEN_THOUSANDTH loop
  3689.                RESULT := MULT(RESULT, TEN_THOUSAND);
  3690.                POWER_OF_TEN := POWER_OF_TEN - 4;
  3691.             end loop;
  3692.             if RESULT < ONE_THOUSANDTH then
  3693.                RESULT := MULT(RESULT, THOUSAND);
  3694.                POWER_OF_TEN := POWER_OF_TEN - 3;
  3695.             end if;
  3696.             if RESULT < ONE_HUNDREDTH then
  3697.                RESULT := MULT(RESULT, HUNDRED);
  3698.                POWER_OF_TEN := POWER_OF_TEN - 2;
  3699.             end if;
  3700.             if RESULT < ONE_TENTH then
  3701.                RESULT := MULT(RESULT, TEN);
  3702.                POWER_OF_TEN := POWER_OF_TEN - 1;
  3703.             end if;
  3704.          else
  3705.             while RESULT >= THOUSAND loop
  3706.                RESULT := MULT(RESULT, ONE_TEN_THOUSANDTH);
  3707.                POWER_OF_TEN := POWER_OF_TEN + 4;
  3708.             end loop;
  3709.             if RESULT >= HUNDRED then
  3710.                RESULT := MULT(RESULT, ONE_THOUSANDTH);
  3711.                POWER_OF_TEN := POWER_OF_TEN + 3;
  3712.             end if;
  3713.             if RESULT >= TEN then
  3714.                RESULT := MULT(RESULT, ONE_HUNDREDTH);
  3715.                POWER_OF_TEN := POWER_OF_TEN + 2;
  3716.             end if;
  3717.             if RESULT >= ONE then
  3718.                RESULT := MULT(RESULT, ONE_TENTH);
  3719.                POWER_OF_TEN := POWER_OF_TEN + 1;
  3720.             end if;
  3721.          end if;
  3722.  
  3723.          -- Store the integer portion
  3724.          -- The OFFSET corrects the decimal value with respect to the
  3725.          -- RESULT.EXPONENT which must equal (0 | -1 | -2 | -3)
  3726.          OFFSET_BITS := -RESULT.EXPONENT;
  3727.          OFFSET := BASE_COMP_VALUE * (2**(OFFSET_BITS));
  3728.  
  3729.          -- Loop over the MAE_NUMBER taking the most significant
  3730.          -- decimal digit and storing it in the array(forewards)
  3731.          WORK_ARRAY := RESULT.COMPS.COMPONENT_ARRAY;
  3732.          -- The variable ALMOST_ZERO is zero thru all significant bits
  3733.          while (WORK_ARRAY > ALMOST_ZERO.COMPS.COMPONENT_ARRAY) loop
  3734.             -- Determine where the scaled least signif bit is located
  3735.             LSC := ((SHORT_NUM_BITS - LSB) / NO_COMP_BITS) + 1;
  3736.             BIT_IN_LSC := ((LSB-1) rem NO_COMP_BITS) + 1;
  3737.             -- The least signif bit is scaled down by two bits
  3738.             -- instead of the true inverse log(2) which is approx 3.322
  3739.             -- since the original LSB is less than TARGET_SHORT_NUM_BITS.
  3740.             LSB := LSB - 2;
  3741.             ALMOST_ZERO.COMPS.COMPONENT_ARRAY(LSC) := BIT_VALUE(BIT_IN_LSC);
  3742.             ALMOST_ZERO.COMPS.COMPONENT_ARRAY(LSC-1) := 0;
  3743.  
  3744.             MULT_BY_TEN(WORK_ARRAY);
  3745.  
  3746.             -- If the rest of the number(significant) is all nines, round up.
  3747.             if (WORK_ARRAY(WORK_ARRAY'last) rem BASE_COMP_VALUE) = 
  3748.                                  MAX_COMP_VALUE then
  3749.                COMP_PTR := WORK_ARRAY'last - 1;
  3750.                while WORK_ARRAY(COMP_PTR) = MAX_COMP_VALUE loop
  3751.                   COMP_PTR := COMP_PTR - 1;
  3752.                   if COMP_PTR <= LSC then
  3753.                      if (WORK_ARRAY(LSC) / BIT_VALUE(BIT_IN_LSC)) =
  3754.                             (MAX_COMP_VALUE / BIT_VALUE(BIT_IN_LSC)) then
  3755.                         -- Instead of adding a rounding value just set to
  3756.                         -- BASE_COMP_VALUE since either case will produce
  3757.                         -- a remaining number less than ALMOST_ZERO
  3758.                         WORK_ARRAY(LSC) := BASE_COMP_VALUE;
  3759.                         RANGE_CHECK(WORK_ARRAY);
  3760.                      end if;
  3761.                      exit;
  3762.                   end if;
  3763.                end loop;
  3764.             end if;
  3765.  
  3766.             -- Extract the decimal value from the array.
  3767.             DECIMAL_VALUE := WORK_ARRAY(WORK_ARRAY'last) / OFFSET;
  3768.             WORK_ARRAY(WORK_ARRAY'last) := WORK_ARRAY(WORK_ARRAY'last) -
  3769.                                               (DECIMAL_VALUE * OFFSET);
  3770.  
  3771.             -- The next check is valid the first time thru the loop
  3772.             -- and remedies the .99999999999 ...    case.
  3773.             if FIRST_DIGIT then
  3774.                FIRST_DIGIT := FALSE;
  3775.                if DECIMAL_VALUE = 10 then
  3776.                   STRING_PIC(INDEX) := '1';
  3777.                   INDEX := INDEX + 1;
  3778.                   POWER_OF_TEN := POWER_OF_TEN + 1;
  3779.                   exit;
  3780.                end if;
  3781.             end if;
  3782.  
  3783.             -- Get the ASCII value of the decimal value
  3784.             -- and store it in the string
  3785.             TEMP_CHAR := INTEGER'image(DECIMAL_VALUE);
  3786.             STRING_PIC(INDEX) := TEMP_CHAR(1);
  3787.             INDEX := INDEX + 1;
  3788.  
  3789.             -- If the (display number+1) decimal digits are in the string.
  3790.             if (INDEX=STRING_PIC'last+1) or (LSB<=NO_COMP_BITS) then
  3791.                exit;
  3792.             end if;
  3793.          end loop;
  3794.       end if;
  3795.  
  3796.       for I in INDEX .. STRING_PIC'last loop
  3797.          STRING_PIC(I) := '0';
  3798.       end loop;
  3799.  
  3800.       if AFT = 0 then
  3801.          ACTUAL_AFT := 1;
  3802.       end if;
  3803.       if EXP = 1 then
  3804.          ACTUAL_EXP := 2;
  3805.       end if;
  3806.  
  3807.       -- determine the number of digits to produce
  3808.       if ACTUAL_EXP /= 0 then
  3809.          -- ACTUAL_FORE must equal one
  3810.          if (ACTUAL_FORE + ACTUAL_AFT) <= SHORT_FLOAT_DIGITS then
  3811.             DISPLAY_DIGITS := ACTUAL_FORE + ACTUAL_AFT;
  3812.          else
  3813.             DISPLAY_DIGITS := SHORT_FLOAT_DIGITS;
  3814.             AFT_WIDTH_DIGITS_BEYOND_PRECISION :=
  3815.                     ACTUAL_AFT - (SHORT_FLOAT_DIGITS - ACTUAL_FORE);
  3816.             ACTUAL_AFT := (SHORT_FLOAT_DIGITS - ACTUAL_FORE);
  3817.          end if;
  3818.       else
  3819.          if POWER_OF_TEN >= 0 then
  3820.             ACTUAL_FORE := POWER_OF_TEN + 1;
  3821.             if (ACTUAL_FORE + ACTUAL_AFT) <= SHORT_FLOAT_DIGITS then
  3822.                DISPLAY_DIGITS := ACTUAL_FORE + ACTUAL_AFT;
  3823.             else
  3824.                DISPLAY_DIGITS := SHORT_FLOAT_DIGITS;
  3825.                AFT_WIDTH_DIGITS_BEYOND_PRECISION :=
  3826.                     ACTUAL_AFT - (SHORT_FLOAT_DIGITS - ACTUAL_FORE);
  3827.                if AFT_WIDTH_DIGITS_BEYOND_PRECISION >= ACTUAL_AFT then
  3828.                   AFT_WIDTH_DIGITS_BEYOND_PRECISION := ACTUAL_AFT;
  3829.                   ACTUAL_AFT := 0;
  3830.                   FORE_WIDTH_DIGITS_BEYOND_PRECISION := 
  3831.                        ACTUAL_FORE - SHORT_FLOAT_DIGITS;
  3832.                   ACTUAL_FORE := SHORT_FLOAT_DIGITS;
  3833.                else
  3834.                   ACTUAL_AFT := (SHORT_FLOAT_DIGITS - ACTUAL_FORE);
  3835.                end if;
  3836.             end if;
  3837.          else
  3838.             -- ACTUAL_FORE must equal one, with a value of zero
  3839.             FORE_FIELD_ZERO_FLAG := TRUE;
  3840.             AFT_LEADING_ZERO_DIGITS := abs(POWER_OF_TEN+1);
  3841.             SIGNIFICANT_AFT := ACTUAL_AFT - AFT_LEADING_ZERO_DIGITS;
  3842.             if SIGNIFICANT_AFT <= SHORT_FLOAT_DIGITS then
  3843.                DISPLAY_DIGITS := SIGNIFICANT_AFT;
  3844.                if SIGNIFICANT_AFT <= 0 then
  3845.                   AFT_LEADING_ZERO_DIGITS := ACTUAL_AFT;
  3846.                   ACTUAL_AFT := 0;
  3847.                elsif SIGNIFICANT_AFT > 0 then
  3848.                   ACTUAL_AFT := SIGNIFICANT_AFT;
  3849.                end if;
  3850.             else
  3851.                DISPLAY_DIGITS := SHORT_FLOAT_DIGITS;
  3852.                AFT_WIDTH_DIGITS_BEYOND_PRECISION := 
  3853.                   SIGNIFICANT_AFT - SHORT_FLOAT_DIGITS;
  3854.                ACTUAL_AFT := SHORT_FLOAT_DIGITS;
  3855.             end if;
  3856.          end if;
  3857.       end if;
  3858.  
  3859.       if DISPLAY_DIGITS > 0 then
  3860.          -- Round the digit in the last-1 position using the last digit.
  3861.          INDEX := DISPLAY_DIGITS + 1;
  3862.          if STRING_PIC(INDEX) >= '5' then
  3863.             STRING_PIC(INDEX) := '0';
  3864.             INDEX := INDEX - 1;
  3865.             STRING_PIC(INDEX) := CHARACTER'succ(STRING_PIC(INDEX));
  3866.             while STRING_PIC(INDEX) > '9' loop
  3867.                if INDEX = STRING_PIC'first then
  3868.                   -- rounding to outside array can only occur if
  3869.                   -- with FORE=1, value=0
  3870.                   STRING_PIC(INDEX) := '1';
  3871.                   POWER_OF_TEN := POWER_OF_TEN + 1;
  3872.                   if POWER_OF_TEN = 0 then
  3873.                      FORE_FIELD_ZERO_FLAG := FALSE;
  3874.                   elsif AFT_LEADING_ZERO_DIGITS > 0 then
  3875.                      AFT_LEADING_ZERO_DIGITS := AFT_LEADING_ZERO_DIGITS - 1;
  3876.                      AFT_WIDTH_DIGITS_BEYOND_PRECISION :=
  3877.                                AFT_WIDTH_DIGITS_BEYOND_PRECISION + 1;
  3878.                   end if;
  3879.                   exit;
  3880.                end if;
  3881.                      
  3882.                STRING_PIC(INDEX) := '0';
  3883.                INDEX := INDEX - 1;
  3884.                STRING_PIC(INDEX) := CHARACTER'succ(STRING_PIC(INDEX));
  3885.             end loop;      
  3886.             INDEX := INDEX + 1;
  3887.          else
  3888.             STRING_PIC(INDEX) := '0';
  3889.          end if;
  3890.       elsif DISPLAY_DIGITS = 0 then
  3891.          if STRING_PIC(STRING_PIC'first) >= '5' then
  3892.             STRING_PIC(STRING_PIC'first) := '1';
  3893.             POWER_OF_TEN := POWER_OF_TEN + 1;
  3894.             if POWER_OF_TEN = 0 then
  3895.                FORE_FIELD_ZERO_FLAG := FALSE;
  3896.             else
  3897.                AFT_LEADING_ZERO_DIGITS := AFT_LEADING_ZERO_DIGITS - 1;
  3898.                ACTUAL_AFT := 1;
  3899.             end if;
  3900.          end if;
  3901.       end if;      
  3902.  
  3903.       if (ACTUAL_EXP = 0) then
  3904.          -- fill the string in reverse
  3905.          TO_INDEX := TO'last;
  3906.          if FORE_FIELD_ZERO_FLAG then
  3907.             -- fore field is zero
  3908.             -- store the aft field
  3909.             for I in 1 .. AFT_WIDTH_DIGITS_BEYOND_PRECISION loop
  3910.                TO(TO_INDEX) := '0';
  3911.                TO_INDEX := TO_INDEX - 1;
  3912.             end loop;
  3913.             for I in reverse 1 .. ACTUAL_AFT loop
  3914.                TO(TO_INDEX) := STRING_PIC(I);
  3915.                TO_INDEX := TO_INDEX - 1;
  3916.             end loop;
  3917.             for I in 1 .. AFT_LEADING_ZERO_DIGITS loop
  3918.                TO(TO_INDEX) := '0';
  3919.                TO_INDEX := TO_INDEX - 1;
  3920.             end loop;
  3921.             TO(TO_INDEX) := '.';
  3922.             TO_INDEX := TO_INDEX - 1;
  3923.             TO(TO_INDEX) := '0';
  3924.             TO_INDEX := TO_INDEX - 1;
  3925.             if NEG_SIGN_FLAG then
  3926.                TO(TO_INDEX) := '-';
  3927.                TO_INDEX := TO_INDEX - 1;
  3928.             end if;
  3929.          else
  3930.             -- non-zero fore field
  3931.             for I in 1 .. AFT_WIDTH_DIGITS_BEYOND_PRECISION loop
  3932.                TO(TO_INDEX) := '0';
  3933.                TO_INDEX := TO_INDEX - 1;
  3934.             end loop;
  3935.             for I in reverse 1 .. ACTUAL_AFT loop
  3936.                TO(TO_INDEX) := STRING_PIC(ACTUAL_FORE+I);
  3937.                TO_INDEX := TO_INDEX - 1;
  3938.             end loop;
  3939.             TO(TO_INDEX) := '.';
  3940.             TO_INDEX := TO_INDEX - 1;
  3941.             for I in 1 .. FORE_WIDTH_DIGITS_BEYOND_PRECISION loop
  3942.                TO(TO_INDEX) := '0';
  3943.                TO_INDEX := TO_INDEX - 1;
  3944.             end loop;
  3945.             for I in reverse 1 .. ACTUAL_FORE loop
  3946.                TO(TO_INDEX) := STRING_PIC(I);
  3947.                TO_INDEX := TO_INDEX - 1;
  3948.             end loop;
  3949.             if NEG_SIGN_FLAG then
  3950.                TO(TO_INDEX) := '-';
  3951.                TO_INDEX := TO_INDEX - 1;
  3952.             end if;
  3953.          end if;
  3954.       else
  3955.          if STRING_PIC(STRING_PIC'first) = '0' then
  3956.             -- zero string, the length includes leading zero,
  3957.             -- '.', AFT, 'E', EXP 
  3958.             TO_INDEX := TO'last - (2 + ACTUAL_AFT + ACTUAL_EXP);
  3959.             TO(TO_INDEX) := '0';
  3960.             TO_INDEX := TO_INDEX + 1;
  3961.             TO(TO_INDEX) := '.';
  3962.             TO_INDEX := TO_INDEX + 1;
  3963.             -- fill out the aft field
  3964.             for I in 1 .. ACTUAL_AFT loop
  3965.                TO(TO_INDEX) := '0';
  3966.                TO_INDEX := TO_INDEX + 1;
  3967.             end loop;
  3968.             TO(TO_INDEX) := 'E';
  3969.             TO_INDEX := TO_INDEX + 1;
  3970.             TO(TO_INDEX) := '+';
  3971.             TO_INDEX := TO_INDEX + 1;
  3972.             -- fill out the exponent field
  3973.             for I in 1 .. ACTUAL_EXP-1 loop
  3974.                TO(TO_INDEX) := '0';
  3975.                TO_INDEX := TO_INDEX + 1;
  3976.             end loop;
  3977.          else
  3978.             -- If there is an exponent, store it in the string.
  3979.             if POWER_OF_TEN /= 0 then
  3980.                if POWER_OF_TEN < 0 then
  3981.                   NEG_SIGN_EXP_FLAG := TRUE;
  3982.                   POWER_OF_TEN := abs(POWER_OF_TEN);
  3983.                end if;
  3984.  
  3985.                -- determine the base ten exponent
  3986.                -- fill the string in reverse
  3987.                EXPONENT_INDEX := EXPONENT_STRING'last;
  3988.                while POWER_OF_TEN /= 0 loop
  3989.                   TEMP_VALUE := POWER_OF_TEN rem 10;
  3990.                   POWER_OF_TEN := POWER_OF_TEN / 10;
  3991.                   TEMP_CHAR := INTEGER'image(TEMP_VALUE);
  3992.                   EXPONENT_STRING(EXPONENT_INDEX) := TEMP_CHAR(1);
  3993.                   EXPONENT_INDEX := EXPONENT_INDEX - 1;
  3994.                end loop;
  3995.                EXPONENT_LENGTH := EXPONENT_STRING'last - EXPONENT_INDEX;
  3996.             end if;
  3997.  
  3998.             -- fill the string in reverse
  3999.             TO_INDEX := TO'last;
  4000.             -- store the exponent field
  4001.             for I in 1 .. EXPONENT_LENGTH loop
  4002.                TO(TO_INDEX) := EXPONENT_STRING((EXPONENT_STRING'last+1)-I);
  4003.                TO_INDEX := TO_INDEX - 1;
  4004.             end loop;
  4005.             -- fill out the exponent field
  4006.             for I in EXPONENT_LENGTH+1 .. ACTUAL_EXP-1 loop
  4007.                TO(TO_INDEX) := '0';
  4008.                TO_INDEX := TO_INDEX - 1;
  4009.             end loop;
  4010.             if NEG_SIGN_EXP_FLAG then
  4011.                TO(TO_INDEX) := '-';
  4012.             else
  4013.                TO(TO_INDEX) := '+';
  4014.             end if;
  4015.             TO_INDEX := TO_INDEX - 1;
  4016.             TO(TO_INDEX) := 'E';
  4017.             TO_INDEX := TO_INDEX - 1;
  4018.             -- store the aft field
  4019.             for I in 1 .. AFT_WIDTH_DIGITS_BEYOND_PRECISION loop
  4020.                TO(TO_INDEX) := '0';
  4021.                TO_INDEX := TO_INDEX - 1;
  4022.             end loop;
  4023.             for I in reverse 1 .. ACTUAL_AFT loop
  4024.                TO(TO_INDEX) := STRING_PIC(I+1);
  4025.                TO_INDEX := TO_INDEX - 1;
  4026.             end loop;
  4027.             TO(TO_INDEX) := '.';
  4028.             TO_INDEX := TO_INDEX - 1;
  4029.             TO(TO_INDEX) := STRING_PIC(STRING_PIC'first);
  4030.             TO_INDEX := TO_INDEX - 1;
  4031.             if NEG_SIGN_FLAG then
  4032.                TO(TO_INDEX) := '-';
  4033.                TO_INDEX := TO_INDEX - 1;
  4034.             end if;
  4035.          end if;
  4036.       end if;
  4037.                
  4038.    exception
  4039.       when others =>
  4040.          raise LAYOUT_ERROR;
  4041.  
  4042.    end PUT;
  4043.  
  4044. -------------------------------
  4045. -- The body of the package
  4046. --
  4047. begin
  4048.    -- Initialize the digits ONE .. TEN with the DIGIT_PICTURE 
  4049.    -- and DIGIT_BINARY_EXPONENT arrays, and initialize ONE_TENTH 
  4050.    -- with an array specified in MAE_BASIC_OPERATIONS.  This allows
  4051.    -- for the length of the array to change in the basic operations
  4052.    -- and not caused a coding change in this package.
  4053.    -- Notice that these values assume the declaration of the type
  4054.    -- is initially a zero value.  This assumption is justified since
  4055.    -- the declaration of the type is in this package specification.
  4056.    -- ZERO taken care of by the initial value.
  4057.    ONE.COMPS.COMPONENT_ARRAY(SHORT_NUM_COMPS) := DIGIT_PICTURE(1);
  4058.    ONE.EXPONENT := DIGIT_BINARY_EXPONENT(1);
  4059.    TWO.COMPS.COMPONENT_ARRAY(SHORT_NUM_COMPS) := DIGIT_PICTURE(2);
  4060.    TWO.EXPONENT := DIGIT_BINARY_EXPONENT(2);
  4061.    THREE.COMPS.COMPONENT_ARRAY(SHORT_NUM_COMPS) := DIGIT_PICTURE(3);
  4062.    THREE.EXPONENT := DIGIT_BINARY_EXPONENT(3);
  4063.    FOUR.COMPS.COMPONENT_ARRAY(SHORT_NUM_COMPS) := DIGIT_PICTURE(4);
  4064.    FOUR.EXPONENT := DIGIT_BINARY_EXPONENT(4);
  4065.    FIVE.COMPS.COMPONENT_ARRAY(SHORT_NUM_COMPS) := DIGIT_PICTURE(5);
  4066.    FIVE.EXPONENT := DIGIT_BINARY_EXPONENT(5);
  4067.    SIX.COMPS.COMPONENT_ARRAY(SHORT_NUM_COMPS) := DIGIT_PICTURE(6);
  4068.    SIX.EXPONENT := DIGIT_BINARY_EXPONENT(6);
  4069.    SEVEN.COMPS.COMPONENT_ARRAY(SHORT_NUM_COMPS) := DIGIT_PICTURE(7);
  4070.    SEVEN.EXPONENT := DIGIT_BINARY_EXPONENT(7);
  4071.    EIGHT.COMPS.COMPONENT_ARRAY(SHORT_NUM_COMPS) := DIGIT_PICTURE(8);
  4072.    EIGHT.EXPONENT := DIGIT_BINARY_EXPONENT(8);
  4073.    NINE.COMPS.COMPONENT_ARRAY(SHORT_NUM_COMPS) := DIGIT_PICTURE(9);
  4074.    NINE.EXPONENT := DIGIT_BINARY_EXPONENT(9);
  4075.    TEN.COMPS.COMPONENT_ARRAY(SHORT_NUM_COMPS) := DIGIT_PICTURE(10);
  4076.    TEN.EXPONENT := DIGIT_BINARY_EXPONENT(10);
  4077.  
  4078.  
  4079.    HUNDRED.COMPS := TEN.COMPS * TEN.COMPS;
  4080.    HUNDRED.EXPONENT := (TEN.EXPONENT + TEN.EXPONENT)
  4081.                             - HUNDRED.COMPS.BITS_SHIFTED;
  4082.    HUNDRED.COMPS.BITS_SHIFTED := 0;
  4083.  
  4084.    THOUSAND.COMPS := HUNDRED.COMPS * TEN.COMPS;
  4085.    THOUSAND.EXPONENT := (HUNDRED.EXPONENT + TEN.EXPONENT)
  4086.                             - THOUSAND.COMPS.BITS_SHIFTED;
  4087.    THOUSAND.COMPS.BITS_SHIFTED := 0;
  4088.  
  4089.    TEN_THOUSAND.COMPS := THOUSAND.COMPS * TEN.COMPS;
  4090.    TEN_THOUSAND.EXPONENT := (THOUSAND.EXPONENT + TEN.EXPONENT)
  4091.                             - TEN_THOUSAND.COMPS.BITS_SHIFTED;
  4092.    TEN_THOUSAND.COMPS.BITS_SHIFTED := 0;
  4093.  
  4094.  
  4095.    ONE_TENTH.COMPS := ONE.COMPS / TEN.COMPS;
  4096.    ONE_TENTH.EXPONENT := (ONE.EXPONENT - TEN.EXPONENT)
  4097.                             - ONE_TENTH.COMPS.BITS_SHIFTED;
  4098.    ONE_TENTH.COMPS.BITS_SHIFTED := 0;
  4099.  
  4100.    ONE_HUNDREDTH.COMPS := ONE_TENTH.COMPS / TEN.COMPS;
  4101.    ONE_HUNDREDTH.EXPONENT := (ONE_TENTH.EXPONENT - TEN.EXPONENT)
  4102.                             - ONE_HUNDREDTH.COMPS.BITS_SHIFTED;
  4103.    ONE_HUNDREDTH.COMPS.BITS_SHIFTED := 0;
  4104.  
  4105.    ONE_THOUSANDTH.COMPS := ONE_HUNDREDTH.COMPS / TEN.COMPS;
  4106.    ONE_THOUSANDTH.EXPONENT := (ONE_HUNDREDTH.EXPONENT - TEN.EXPONENT)
  4107.                             - ONE_THOUSANDTH.COMPS.BITS_SHIFTED;
  4108.    ONE_THOUSANDTH.COMPS.BITS_SHIFTED := 0;
  4109.  
  4110.    ONE_TEN_THOUSANDTH.COMPS := ONE_THOUSANDTH.COMPS / TEN.COMPS;
  4111.    ONE_TEN_THOUSANDTH.EXPONENT := (ONE_THOUSANDTH.EXPONENT - TEN.EXPONENT)
  4112.                             - ONE_TEN_THOUSANDTH.COMPS.BITS_SHIFTED;
  4113.    ONE_TEN_THOUSANDTH.COMPS.BITS_SHIFTED := 0;
  4114.  
  4115.  
  4116.    MAE_SHORT_FLOAT_EPSILON := (TWO**(-(TARGET_SHORT_NUM_BITS-1)));
  4117.    MAE_SHORT_FLOAT_LARGE := ((TWO**(MAX_EXPONENT_VALUE-1)) -
  4118.                (TWO**(MAX_EXPONENT_VALUE-(TARGET_SHORT_NUM_BITS))))
  4119.                *TWO;
  4120.    MAE_SHORT_FLOAT_SMALL := (TWO**(MIN_EXPONENT_VALUE-1));
  4121.    MAE_SHORT_FLOAT_LAST := MAE_SHORT_FLOAT_LARGE;
  4122.    MAE_SHORT_FLOAT_FIRST := -MAE_SHORT_FLOAT_LARGE;
  4123.  
  4124. end MAE_SHORT_FLOAT;
  4125. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  4126. --maelong.txt
  4127. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  4128. -------------------------------------------------------------------------------
  4129. --                                                                           --
  4130. --             Emulation of Machine Arithmetic - a WIS Ada Tool              --
  4131. --                                                                           --
  4132. --                         Ada Technology Group                              --
  4133. --                         SYSCON Corporation                                --
  4134. --                         3990 Sherman Street                               --
  4135. --                         San Diego, CA. 92110                              --
  4136. --                                                                           --
  4137. --                        John Long & John Reddan                            --
  4138. --                                                                           --
  4139. -------------------------------------------------------------------------------
  4140.  
  4141. with MAE_BASIC_OPERATIONS; use MAE_BASIC_OPERATIONS;
  4142.  
  4143. package MAE_LONG_FLOAT is
  4144. -------------------------------------------------------------------
  4145. -- The purpose of this package is to emulate target machine
  4146. -- double precision floating point arithmetic on host machines
  4147. -- with 16-bit or larger words.
  4148. --
  4149. -- The range of the supported type is as follows:
  4150. --
  4151. --     TARGET_LONG_FLOAT (Double Precision Real)
  4152. --        approximate range of 10**-38 to 10**38 and 0
  4153. --        mantissa => MAE_BASIC_OPERATIONS.TARGET_LONG_NUM_BITS
  4154. --                    bit binary fraction
  4155. --        exponent => -128 to 127
  4156. --
  4157. --
  4158. -- Any errors which occur during use of the arithmetic and
  4159. -- boolean functions defined below will result in the
  4160. -- raising of the exception "MAE_NUMERIC_ERROR". 
  4161.  
  4162. -----------------------------------------------------------------
  4163. -- Visible operations with MAE_LONG_FLOAT_TYPE
  4164. --
  4165.    type MAE_LONG_FLOAT_TYPE is private;
  4166.  
  4167.    -- The defined operators for this type are as follows:
  4168.  
  4169.    -- predefined system function "=" and function "/="
  4170.    function "<"    (LEFT, RIGHT : MAE_LONG_FLOAT_TYPE) return BOOLEAN;
  4171.    function "<="   (LEFT, RIGHT : MAE_LONG_FLOAT_TYPE) return BOOLEAN;
  4172.    function ">"    (LEFT, RIGHT : MAE_LONG_FLOAT_TYPE) return BOOLEAN;
  4173.    function ">="   (LEFT, RIGHT : MAE_LONG_FLOAT_TYPE) return BOOLEAN;
  4174.  
  4175.    function "+"    (RIGHT : MAE_LONG_FLOAT_TYPE) return MAE_LONG_FLOAT_TYPE;
  4176.    function "-"    (RIGHT : MAE_LONG_FLOAT_TYPE) return MAE_LONG_FLOAT_TYPE;
  4177.    function "abs"  (RIGHT : MAE_LONG_FLOAT_TYPE) return MAE_LONG_FLOAT_TYPE;
  4178.  
  4179.    function "+"    (LEFT,RIGHT : MAE_LONG_FLOAT_TYPE) 
  4180.                        return MAE_LONG_FLOAT_TYPE;
  4181.    function "-"    (LEFT,RIGHT : MAE_LONG_FLOAT_TYPE) 
  4182.                        return MAE_LONG_FLOAT_TYPE;
  4183.    function "*"    (LEFT,RIGHT : MAE_LONG_FLOAT_TYPE) 
  4184.                        return MAE_LONG_FLOAT_TYPE;
  4185.    function "/"    (LEFT,RIGHT : MAE_LONG_FLOAT_TYPE) 
  4186.                        return MAE_LONG_FLOAT_TYPE;
  4187.  
  4188.    function "**"   (LEFT : MAE_LONG_FLOAT_TYPE; RIGHT : INTEGER)
  4189.                        return MAE_LONG_FLOAT_TYPE;
  4190.  
  4191.  
  4192.    procedure GET (FROM : in STRING;
  4193.                   ITEM : out MAE_LONG_FLOAT_TYPE;
  4194.                   LAST : out POSITIVE);
  4195.  
  4196.    procedure PUT (TO : out STRING;
  4197.                   ITEM : in MAE_LONG_FLOAT_TYPE;
  4198.                   AFT : in FIELD := LONG_DEFAULT_AFT;
  4199.                   EXP : in FIELD := LONG_DEFAULT_EXP);
  4200.  
  4201.    function TARGET_LONG_FLOAT_EPSILON return MAE_LONG_FLOAT_TYPE;
  4202.  
  4203.    function TARGET_LONG_FLOAT_LARGE return MAE_LONG_FLOAT_TYPE;
  4204.  
  4205.    function TARGET_LONG_FLOAT_SMALL return MAE_LONG_FLOAT_TYPE;
  4206.  
  4207.    function TARGET_LONG_FLOAT_LAST return MAE_LONG_FLOAT_TYPE;
  4208.  
  4209.    function TARGET_LONG_FLOAT_FIRST return MAE_LONG_FLOAT_TYPE;
  4210.  
  4211.  
  4212. -------------------------------------------------------------------
  4213. private
  4214.  
  4215. -- The declaration of the next variable is to allow
  4216. -- the record declaration under the Telesoft version 1.5 compiler.
  4217. -- A better declaration would allow the COMP_ARRAY range to be
  4218. -- (1 .. BITS_TO_COMPS(NO_OF_BITS).
  4219.  
  4220.    type MAE_LONG_FLOAT_TYPE is
  4221.       record
  4222.          SIGN : SIGN_TYPE := POS_SIGN;
  4223.          COMPS : LONG_COMP_ARRAY := LONG_FLOAT_COMP_ARRAY;
  4224.          EXPONENT : EXPONENT_TYPE := 0;
  4225.       end record;
  4226.  
  4227. -------------------------------------------------------------------
  4228. end MAE_LONG_FLOAT;
  4229.  
  4230. -------------------------------------------------------------------
  4231. -------------------------------------------------------------------
  4232.  
  4233. with MAE_BASIC_OPERATIONS; use MAE_BASIC_OPERATIONS;
  4234.  
  4235. package body MAE_LONG_FLOAT is
  4236. -------------------------------------------------------------------
  4237. -- Local variables for better tracing
  4238. --
  4239.    MAE_FORMAT_ERROR : EXCEPTION;
  4240.    MAE_LONG_FLOAT_OVERFLOW : EXCEPTION;
  4241.    DATA_ERROR : EXCEPTION;
  4242.    LAYOUT_ERROR : EXCEPTION;
  4243.  
  4244. -------------------------------------------------------------------
  4245. -- Constants for local functions and procedures
  4246. --
  4247. -- Once again the declaration of variables is affect by the
  4248. -- Telesoft 1.5 compiler.  The better declaration would use
  4249. -- the 'range, 'first, and 'last attributes for initialization.
  4250. -- The intialization of the digits ONE .. TEN and ONE_TENTH
  4251. -- are in the body(bottom) of this package.
  4252.  
  4253.    ZERO : MAE_LONG_FLOAT_TYPE;
  4254.    ONE : MAE_LONG_FLOAT_TYPE;
  4255.    TWO : MAE_LONG_FLOAT_TYPE;
  4256.    THREE : MAE_LONG_FLOAT_TYPE;
  4257.    FOUR : MAE_LONG_FLOAT_TYPE;
  4258.    FIVE : MAE_LONG_FLOAT_TYPE;
  4259.    SIX : MAE_LONG_FLOAT_TYPE;
  4260.    SEVEN : MAE_LONG_FLOAT_TYPE;
  4261.    EIGHT : MAE_LONG_FLOAT_TYPE;
  4262.    NINE : MAE_LONG_FLOAT_TYPE;
  4263.    TEN : MAE_LONG_FLOAT_TYPE;
  4264.  
  4265.    HUNDRED : MAE_LONG_FLOAT_TYPE;
  4266.    THOUSAND : MAE_LONG_FLOAT_TYPE;
  4267.    TEN_THOUSAND : MAE_LONG_FLOAT_TYPE;
  4268.  
  4269.    ONE_TENTH : MAE_LONG_FLOAT_TYPE;
  4270.    ONE_HUNDREDTH : MAE_LONG_FLOAT_TYPE;
  4271.    ONE_THOUSANDTH : MAE_LONG_FLOAT_TYPE;
  4272.    ONE_TEN_THOUSANDTH : MAE_LONG_FLOAT_TYPE;
  4273.  
  4274.    MAE_LONG_FLOAT_EPSILON : MAE_LONG_FLOAT_TYPE;
  4275.    MAE_LONG_FLOAT_LARGE : MAE_LONG_FLOAT_TYPE;
  4276.    MAE_LONG_FLOAT_SMALL : MAE_LONG_FLOAT_TYPE;
  4277.    MAE_LONG_FLOAT_LAST : MAE_LONG_FLOAT_TYPE;
  4278.    MAE_LONG_FLOAT_FIRST : MAE_LONG_FLOAT_TYPE;
  4279.  
  4280.    TWO_THREE : constant INTEGER := 2**3;
  4281.    TWO_THREE_LESS_ONE : constant INTEGER := (2**3)-1;
  4282.    TWO_TWO : constant INTEGER := 2**2;
  4283.    TWO_TWO_LESS_ONE : constant INTEGER := (2**2)-1;
  4284.  
  4285. -------------------------------------------------------------------
  4286. -- Visible operations with MAE_LONG_FLOAT_TYPE
  4287. --
  4288. --
  4289.    function TARGET_LONG_FLOAT_EPSILON return MAE_LONG_FLOAT_TYPE is
  4290.    begin
  4291.       return MAE_LONG_FLOAT_EPSILON;
  4292.    end TARGET_LONG_FLOAT_EPSILON; 
  4293.  
  4294. ------------------------------
  4295.  
  4296.    function TARGET_LONG_FLOAT_LARGE return MAE_LONG_FLOAT_TYPE is
  4297.    begin
  4298.       return MAE_LONG_FLOAT_LARGE;
  4299.    end TARGET_LONG_FLOAT_LARGE;
  4300.  
  4301. ------------------------------
  4302.  
  4303.    function TARGET_LONG_FLOAT_SMALL return MAE_LONG_FLOAT_TYPE is
  4304.    begin
  4305.       return MAE_LONG_FLOAT_SMALL;
  4306.    end TARGET_LONG_FLOAT_SMALL;
  4307.  
  4308. ------------------------------
  4309.  
  4310.    function TARGET_LONG_FLOAT_LAST return MAE_LONG_FLOAT_TYPE is
  4311.    begin
  4312.       return MAE_LONG_FLOAT_LAST;
  4313.    end TARGET_LONG_FLOAT_LAST;
  4314.  
  4315. ------------------------------
  4316.  
  4317.    function TARGET_LONG_FLOAT_FIRST return MAE_LONG_FLOAT_TYPE is
  4318.    begin
  4319.       return MAE_LONG_FLOAT_FIRST;
  4320.    end TARGET_LONG_FLOAT_FIRST;
  4321.  
  4322. ------------------------------
  4323.  
  4324.    -- predefined system functions : function "=" and function "/="
  4325.  
  4326. ------------------------------
  4327.  
  4328.    function "<"    (LEFT, RIGHT : MAE_LONG_FLOAT_TYPE) return BOOLEAN is
  4329.       -- Resolve the comparision by, first checking the signs, then
  4330.       -- checking the exponent, and finally the component arrays.
  4331.    begin
  4332.       if LEFT.COMPS.COMPONENT_ARRAY = ZERO.COMPS.COMPONENT_ARRAY then
  4333.          if RIGHT.COMPS.COMPONENT_ARRAY = ZERO.COMPS.COMPONENT_ARRAY then
  4334.             return FALSE;
  4335.          else
  4336.             return RIGHT.SIGN;
  4337.          end if;
  4338.       elsif RIGHT.COMPS.COMPONENT_ARRAY = ZERO.COMPS.COMPONENT_ARRAY then
  4339.          return not LEFT.SIGN;
  4340.       end if;
  4341.  
  4342.       case LEFT.SIGN is
  4343.          when POS_SIGN =>
  4344.             if RIGHT.SIGN = POS_SIGN then
  4345.                -- both are positive
  4346.                if LEFT.EXPONENT < RIGHT.EXPONENT then 
  4347.                   return TRUE;
  4348.                elsif LEFT.EXPONENT > RIGHT.EXPONENT then
  4349.                   return FALSE;
  4350.                else
  4351.                   return
  4352.                    (LEFT.COMPS.COMPONENT_ARRAY < RIGHT.COMPS.COMPONENT_ARRAY);
  4353.                end if;
  4354.             else
  4355.                -- left is positive, right is negative
  4356.                return FALSE;
  4357.             end if;
  4358.          when NEG_SIGN =>
  4359.             if RIGHT.SIGN = NEG_SIGN then
  4360.                -- both are negative
  4361.                if LEFT.EXPONENT > RIGHT.EXPONENT then 
  4362.                   return TRUE;
  4363.                elsif LEFT.EXPONENT < RIGHT.EXPONENT then
  4364.                   return FALSE;
  4365.                else
  4366.                   return 
  4367.                    (LEFT.COMPS.COMPONENT_ARRAY > RIGHT.COMPS.COMPONENT_ARRAY);
  4368.                end if;
  4369.             else
  4370.                -- left is negative, right is positive
  4371.                return TRUE;
  4372.             end if;
  4373.       end case;
  4374.  
  4375.    exception
  4376.       when others =>
  4377.          raise MAE_NUMERIC_ERROR;
  4378.  
  4379.    end "<";
  4380.  
  4381. ------------------------------
  4382.  
  4383.    function "<="   (LEFT, RIGHT : MAE_LONG_FLOAT_TYPE) return BOOLEAN is
  4384.       -- Resolve the comparision by, first checking the signs, then
  4385.       -- checking the exponent, and finally the component arrays.
  4386.    begin
  4387.       if LEFT.COMPS.COMPONENT_ARRAY = ZERO.COMPS.COMPONENT_ARRAY then
  4388.          return RIGHT.SIGN;
  4389.       elsif RIGHT.COMPS.COMPONENT_ARRAY = ZERO.COMPS.COMPONENT_ARRAY then
  4390.          return not LEFT.SIGN;
  4391.       end if;
  4392.  
  4393.       case LEFT.SIGN is
  4394.          when POS_SIGN =>
  4395.             if RIGHT.SIGN = POS_SIGN then
  4396.                -- both are positive
  4397.                if LEFT.EXPONENT < RIGHT.EXPONENT then 
  4398.                   return TRUE;
  4399.                elsif LEFT.EXPONENT > RIGHT.EXPONENT then
  4400.                   return FALSE;
  4401.                else
  4402.                   return 
  4403.                    (LEFT.COMPS.COMPONENT_ARRAY <= RIGHT.COMPS.COMPONENT_ARRAY);
  4404.                end if;
  4405.             else
  4406.                -- left is positive, right is negative
  4407.                return FALSE;
  4408.             end if;
  4409.          when NEG_SIGN =>
  4410.             if RIGHT.SIGN = NEG_SIGN then
  4411.                -- both are negative
  4412.                if LEFT.EXPONENT > RIGHT.EXPONENT then 
  4413.                   return TRUE;
  4414.                elsif LEFT.EXPONENT < RIGHT.EXPONENT then
  4415.                   return FALSE;
  4416.                else
  4417.                   return
  4418.                    (LEFT.COMPS.COMPONENT_ARRAY >= RIGHT.COMPS.COMPONENT_ARRAY);
  4419.                end if;
  4420.             else
  4421.                -- left is negative, right is positive
  4422.                return TRUE;
  4423.             end if;
  4424.       end case;
  4425.  
  4426.    exception
  4427.       when others =>
  4428.          raise MAE_NUMERIC_ERROR;
  4429.  
  4430.    end "<=";
  4431.  
  4432. ------------------------------
  4433.  
  4434.    function ">"    (LEFT, RIGHT : MAE_LONG_FLOAT_TYPE) return BOOLEAN is
  4435.       -- Resolve the comparision by, first checking the signs, then
  4436.       -- checking the exponent, and finally the component arrays.
  4437.    begin
  4438.       if LEFT.COMPS.COMPONENT_ARRAY = ZERO.COMPS.COMPONENT_ARRAY then
  4439.          return not RIGHT.SIGN;
  4440.       elsif RIGHT.COMPS.COMPONENT_ARRAY = ZERO.COMPS.COMPONENT_ARRAY then
  4441.          return LEFT.SIGN;
  4442.       end if;
  4443.  
  4444.       case LEFT.SIGN is
  4445.          when POS_SIGN =>
  4446.             if RIGHT.SIGN = POS_SIGN then
  4447.                -- both are positive
  4448.                if LEFT.EXPONENT > RIGHT.EXPONENT then 
  4449.                   return TRUE;
  4450.                elsif LEFT.EXPONENT < RIGHT.EXPONENT then
  4451.                   return FALSE;
  4452.                else
  4453.                   return 
  4454.                    (LEFT.COMPS.COMPONENT_ARRAY > RIGHT.COMPS.COMPONENT_ARRAY);
  4455.                end if;
  4456.             else
  4457.                -- left is positive, right is negative
  4458.                return TRUE;
  4459.             end if;
  4460.          when NEG_SIGN =>
  4461.             if RIGHT.SIGN = NEG_SIGN then
  4462.                -- both are negative
  4463.                if LEFT.EXPONENT < RIGHT.EXPONENT then 
  4464.                   return TRUE;
  4465.                elsif LEFT.EXPONENT > RIGHT.EXPONENT then
  4466.                   return FALSE;
  4467.                else
  4468.                   return 
  4469.                    (LEFT.COMPS.COMPONENT_ARRAY < RIGHT.COMPS.COMPONENT_ARRAY);
  4470.                end if;
  4471.             else
  4472.                -- left is negative, right is positive
  4473.                return FALSE;
  4474.             end if;
  4475.       end case;
  4476.  
  4477.    exception
  4478.       when others =>
  4479.          raise MAE_NUMERIC_ERROR;
  4480.  
  4481.    end ">";
  4482.  
  4483. ------------------------------
  4484.  
  4485.    function ">="   (LEFT, RIGHT : MAE_LONG_FLOAT_TYPE) return BOOLEAN is
  4486.       -- Resolve the comparision by, first checking the signs, then
  4487.       -- checking the exponent, and finally the component arrays.
  4488.    begin
  4489.       if LEFT.COMPS.COMPONENT_ARRAY = ZERO.COMPS.COMPONENT_ARRAY then
  4490.          if RIGHT.COMPS.COMPONENT_ARRAY = ZERO.COMPS.COMPONENT_ARRAY then
  4491.             return TRUE;
  4492.          else
  4493.             return not RIGHT.SIGN;
  4494.          end if;
  4495.       elsif RIGHT.COMPS.COMPONENT_ARRAY = ZERO.COMPS.COMPONENT_ARRAY then
  4496.          return LEFT.SIGN;
  4497.       end if;
  4498.  
  4499.       case LEFT.SIGN is
  4500.          when POS_SIGN =>
  4501.             if RIGHT.SIGN = POS_SIGN then
  4502.                -- both are positive
  4503.                if LEFT.EXPONENT > RIGHT.EXPONENT then 
  4504.                   return TRUE;
  4505.                elsif LEFT.EXPONENT < RIGHT.EXPONENT then
  4506.                   return FALSE;
  4507.                else
  4508.                   return 
  4509.                    (LEFT.COMPS.COMPONENT_ARRAY >= RIGHT.COMPS.COMPONENT_ARRAY);
  4510.                end if;
  4511.             else
  4512.                -- left is positive, right is negative
  4513.                return TRUE;
  4514.             end if;
  4515.          when NEG_SIGN =>
  4516.             if RIGHT.SIGN = NEG_SIGN then
  4517.                -- both are negative
  4518.                if LEFT.EXPONENT < RIGHT.EXPONENT then 
  4519.                   return TRUE;
  4520.                elsif LEFT.EXPONENT > RIGHT.EXPONENT then
  4521.                   return FALSE;
  4522.                else
  4523.                   return 
  4524.                    (LEFT.COMPS.COMPONENT_ARRAY <= RIGHT.COMPS.COMPONENT_ARRAY);
  4525.                end if;
  4526.             else
  4527.                -- left is negative, right is positive
  4528.                return FALSE;
  4529.             end if;
  4530.       end case;
  4531.  
  4532.    exception
  4533.       when others =>
  4534.          raise MAE_NUMERIC_ERROR;
  4535.  
  4536.    end ">=";
  4537.  
  4538. ---------------------------
  4539.  
  4540.    function "+"    (RIGHT : MAE_LONG_FLOAT_TYPE) 
  4541.                        return MAE_LONG_FLOAT_TYPE is
  4542.    begin
  4543.       -- No action needed
  4544.       return RIGHT;
  4545.    end "+";
  4546.  
  4547. ---------------------------
  4548.  
  4549.    function "-"    (RIGHT : MAE_LONG_FLOAT_TYPE) 
  4550.                        return MAE_LONG_FLOAT_TYPE is
  4551.       RESULT : MAE_LONG_FLOAT_TYPE := RIGHT;
  4552.    begin
  4553.       RESULT.SIGN := CHANGE_SIGN(RIGHT.SIGN);
  4554.       return RESULT;
  4555.    end "-";
  4556.  
  4557. ---------------------------
  4558.  
  4559.    function "abs"  (RIGHT : MAE_LONG_FLOAT_TYPE) 
  4560.                        return MAE_LONG_FLOAT_TYPE is
  4561.       RESULT : MAE_LONG_FLOAT_TYPE := RIGHT;
  4562.    begin
  4563.       RESULT.SIGN := POS_SIGN;
  4564.       return RESULT;
  4565.    end "abs";
  4566.  
  4567. -------------------------------------------------------------------
  4568.  
  4569.    procedure ROUND_TO_TARGET (RESULT : in out MAE_LONG_FLOAT_TYPE) is
  4570.       -- The purpose of this function is perform an underflow
  4571.       -- check (if true set result to zero), and overflow check
  4572.       -- (raise constraint error), then to round the float type
  4573.       -- so as to match the emulated target.
  4574.       -- The input array must be normalized.
  4575. -- --------------------------------------------------------------
  4576. --
  4577. --               Rounding Technique Summary
  4578. --
  4579. -- --------------------------------------------------------------
  4580. --
  4581. --      LSB    : the least significant bit
  4582. --      GUARD  : the guard bit, first bit beyond LSB
  4583. --      STICKY : the logical "or" of all bits beyond GUARD
  4584. --
  4585. --
  4586. --              BEFORE ROUNDING             AFTER ROUNDING
  4587. --   
  4588. --      LSB   |  GUARD  | STICKY  ||   LSB   | HOW ROUNDED ?
  4589. --   --------------------------------------------------------
  4590. --       0    |    0    |    0    ||    0    | exact
  4591. --       0    |    0    |    1    ||    0    | down (0<x<.5)
  4592. --       0    |    1    |    0    ||    0    | down (.5)
  4593. --       0    |    1    |    1    ||    1    | up (.5<x<1)
  4594. --       1    |    0    |    0    ||    1    | exact
  4595. --       1    |    0    |    1    ||    1    | down (0<x<.5)
  4596. --       1    |    1    |    0    ||    0*   | up (.5)
  4597. --       1    |    1    |    1    ||    0*   | up (.5<x<1)
  4598. --
  4599. --       * note that a carry to the bit above the LSB occurs
  4600. --
  4601. --    The references to 0, .5, and 1, are with respect to the
  4602. --    least significant bit in the binary representation. 
  4603. --    For example, the representative value of the guard bit 
  4604. --    is one-half the representative value of the least 
  4605. --    significant bit, and the maximum value that can be 
  4606. --    represented by the sticky bit is (.499999 ...) times
  4607. --    the representative value of the least significant bit.
  4608. --     
  4609. -- --------------------------------------------------------------
  4610.       C_RESULT : LONG_COMPONENT_ARRAY := RESULT.COMPS.COMPONENT_ARRAY;
  4611.       LSC, LSB, LSB_FLAG : INTEGER;
  4612.       GUARD, GUARD_FLAG, GUARD_COMP : INTEGER;
  4613.       STICKY, STICKY_FLAG : INTEGER;
  4614.       CARRY, INDEX : INTEGER;
  4615.    begin
  4616.       if (RESULT.EXPONENT < MIN_EXPONENT_VALUE) then
  4617.          RESULT := ZERO;
  4618.       elsif (RESULT.EXPONENT > MAX_EXPONENT_VALUE) then
  4619.          raise MAE_LONG_FLOAT_OVERFLOW;
  4620.       else
  4621.          -- Determine the position of the least signif bit (lsb)
  4622.          -- (which is inside of the least signif comp, lsc)
  4623.          -- in the array. The next bit is the guard bit.  The next
  4624.          -- is the sticky bit which is the logical or of all the
  4625.          -- bits after guard.
  4626.          LSC := ((LONG_NUM_BITS - TARGET_LONG_NUM_BITS) / NO_COMP_BITS) + 1;
  4627.          LSB := ((TARGET_LONG_NUM_BITS-1) rem NO_COMP_BITS) + 1;
  4628.          LSB_FLAG := ((C_RESULT(LSC) / BIT_VALUE(LSB)) rem 2);
  4629.  
  4630.          if LONG_FLOAT_MACHINE_ROUNDS then
  4631.             -- The guard bit is one bit after lsb.
  4632.             if LSB /= NO_COMP_BITS then
  4633.                GUARD := LSB + 1;
  4634.                GUARD_COMP := LSC;
  4635.             else
  4636.                GUARD := 1;
  4637.                GUARD_COMP := LSC - 1;
  4638.             end if;
  4639.             -- Get the guard bit value.
  4640.             GUARD_FLAG := ((C_RESULT(GUARD_COMP) / BIT_VALUE(GUARD)) rem 2);
  4641.             -- if guard=0 then no rounding necessary
  4642.             if (GUARD_FLAG /= 0) then
  4643.  
  4644.                -- Otherwise determine the sticky bit
  4645.                -- Initial sticky bit value is 0.
  4646.                if GUARD /= NO_COMP_BITS then
  4647.                   STICKY := GUARD + 1;
  4648.                else 
  4649.                   STICKY := 1;
  4650.                end if;
  4651.                STICKY_FLAG := 0;
  4652.                -- First check the remaining bits in the comp where
  4653.                -- the sticky bit is located.
  4654.                if (C_RESULT(GUARD_COMP) rem BIT_VALUE(GUARD)) /= 0 then
  4655.                   STICKY_FLAG := 1;
  4656.                else
  4657.                   -- Now check the remaining bits in the array
  4658.                   for I in GUARD_COMP+1 .. LONG_NUM_COMPS loop
  4659.                      if C_RESULT(I) /= 0 then
  4660.                         STICKY_FLAG := 1;
  4661.                         exit;
  4662.                      end if;
  4663.                   end loop;
  4664.                end if;
  4665.                -- Check for round for (.5 <= x < 1), recall the guard bit=1.
  4666.                if (STICKY_FLAG = 1) or (LSB_FLAG = 1) then
  4667.                   C_RESULT(LSC) := C_RESULT(LSC) + BIT_VALUE(LSB);
  4668.                   -- Do an inline RANGE_CHECK
  4669.                   INDEX := LSC;
  4670.                   while C_RESULT(INDEX) > MAX_COMP_VALUE loop
  4671.                      CARRY := C_RESULT(INDEX) / BASE_COMP_VALUE;
  4672.                      C_RESULT(INDEX) := C_RESULT(INDEX) mod BASE_COMP_VALUE;
  4673.                      INDEX := INDEX + 1;
  4674.                      C_RESULT(INDEX) := C_RESULT(INDEX) + CARRY;
  4675.                      -- If it carries all the way up to the most
  4676.                      -- signif bit, divide the array by two and
  4677.                      -- bump the exponent. 
  4678.                      if INDEX = LONG_NUM_COMPS then
  4679.                         if C_RESULT(INDEX) > MAX_COMP_VALUE then
  4680.                            DIVIDE_ARRAY_BY_TWO(C_RESULT);
  4681.                            RESULT.EXPONENT := RESULT.EXPONENT + 1;
  4682.                         end if;
  4683.                      end if;
  4684.                   end loop;
  4685.                end if;
  4686.             end if;
  4687.          end if;
  4688.  
  4689.          -- Zero out the lower portion of the array
  4690.          C_RESULT(LSC) := (C_RESULT(LSC) / BIT_VALUE(LSB)) * BIT_VALUE(LSB);
  4691.          for I in 1 .. LSC-1 loop
  4692.             C_RESULT(I) := 0;
  4693.          end loop;
  4694.  
  4695.          RESULT.COMPS.COMPONENT_ARRAY := C_RESULT;
  4696.       end if;
  4697.  
  4698.    exception
  4699.       when others =>
  4700.          raise MAE_NUMERIC_ERROR;
  4701.  
  4702.    end ROUND_TO_TARGET;
  4703.  
  4704. ------------------------------
  4705.  
  4706.    procedure NORMALIZE_LONG_FLOAT (RESULT : in out MAE_LONG_FLOAT_TYPE) is
  4707.       -- The purpose of this function is to normalize the
  4708.       -- the float type so as to maintain accuracy during
  4709.       -- computations.
  4710.       SHIFT_BITS : INTEGER := 0;
  4711.    begin
  4712.       ARRAY_NORMALIZE(RESULT.COMPS.COMPONENT_ARRAY, SHIFT_BITS);
  4713.       RESULT.EXPONENT := RESULT.EXPONENT - SHIFT_BITS;
  4714.  
  4715.    exception
  4716.       when others =>
  4717.          raise MAE_NUMERIC_ERROR;
  4718.  
  4719.    end NORMALIZE_LONG_FLOAT;
  4720.  
  4721. ------------------------------
  4722.  
  4723.    function ALIGN (ADD_VALUE : MAE_LONG_FLOAT_TYPE; MATCH_EXP : INTEGER)
  4724.                                         return MAE_LONG_FLOAT_TYPE is
  4725.       -- The purpose of this function is to shift the intermediate,
  4726.       -- to be used in an add/subtract operation, so that the 
  4727.       -- exponent equals the MATCH_EXP.
  4728.       INTERMEDIATE : MAE_LONG_FLOAT_TYPE := ADD_VALUE;
  4729.       SHIFT_BITS : INTEGER;
  4730.    begin
  4731.       -- determine the number of bits to be shifted
  4732.       SHIFT_BITS := MATCH_EXP - INTERMEDIATE.EXPONENT;
  4733.       -- check if the number is shifted beyond significance
  4734.       if SHIFT_BITS >= LONG_NUM_BITS then
  4735.          return ZERO;
  4736.       elsif SHIFT_BITS < 1 then
  4737.          raise MAE_NUMERIC_ERROR;
  4738.       else
  4739.  
  4740.          -- rounding may be needed here
  4741.  
  4742.          ARRAY_TRUNCATION_SHIFT_RIGHT(INTERMEDIATE.COMPS.COMPONENT_ARRAY,
  4743.                                           SHIFT_BITS);
  4744.          INTERMEDIATE.EXPONENT := MATCH_EXP;
  4745.          return INTERMEDIATE;
  4746.       end if;
  4747.  
  4748.    exception
  4749.       when others =>
  4750.          raise MAE_NUMERIC_ERROR;
  4751.  
  4752.    end ALIGN;
  4753.  
  4754. -------------------------------------------------------------------
  4755.  
  4756.    function "+"    (LEFT,RIGHT : MAE_LONG_FLOAT_TYPE) 
  4757.                        return MAE_LONG_FLOAT_TYPE is
  4758.       -- The purpose of this function is to add two
  4759.       -- MAE_LONG_FLOAT_TYPEs.
  4760.       RESULT, TEMP : MAE_LONG_FLOAT_TYPE;
  4761.    begin
  4762.       -- zero check
  4763.       if RIGHT.COMPS.COMPONENT_ARRAY = ZERO.COMPS.COMPONENT_ARRAY then
  4764.          RESULT := LEFT;
  4765.          NORMALIZE_LONG_FLOAT(RESULT);
  4766.          ROUND_TO_TARGET(RESULT);
  4767.          return RESULT;
  4768.       elsif LEFT.COMPS.COMPONENT_ARRAY = ZERO.COMPS.COMPONENT_ARRAY then
  4769.          RESULT := RIGHT;
  4770.          NORMALIZE_LONG_FLOAT(RESULT);
  4771.          ROUND_TO_TARGET(RESULT);
  4772.          return RESULT;
  4773.       end if;
  4774.  
  4775.       case (LEFT.SIGN xor RIGHT.SIGN) is
  4776.          -- The signs are different (subtraction)
  4777.          when TRUE =>
  4778.             if LEFT.EXPONENT > RIGHT.EXPONENT then
  4779.                TEMP := ALIGN(RIGHT, LEFT.EXPONENT);
  4780.                RESULT.COMPS := LEFT.COMPS - TEMP.COMPS;
  4781.                RESULT.EXPONENT := LEFT.EXPONENT - RESULT.COMPS.BITS_SHIFTED;
  4782.                RESULT.SIGN := LEFT.SIGN;
  4783.             elsif LEFT.EXPONENT < RIGHT.EXPONENT then
  4784.                TEMP := ALIGN(LEFT, RIGHT.EXPONENT);
  4785.                RESULT.COMPS := RIGHT.COMPS - TEMP.COMPS;
  4786.                RESULT.EXPONENT := RIGHT.EXPONENT - RESULT.COMPS.BITS_SHIFTED;
  4787.                RESULT.SIGN := RIGHT.SIGN;
  4788.             else
  4789.                if LEFT.COMPS.COMPONENT_ARRAY > RIGHT.COMPS.COMPONENT_ARRAY then
  4790.                   RESULT.COMPS := LEFT.COMPS - RIGHT.COMPS;
  4791.                   RESULT.EXPONENT := LEFT.EXPONENT - RESULT.COMPS.BITS_SHIFTED;
  4792.                   RESULT.SIGN := LEFT.SIGN;
  4793.                else
  4794.                   RESULT.COMPS := RIGHT.COMPS - LEFT.COMPS;
  4795.                   RESULT.EXPONENT := RIGHT.EXPONENT - RESULT.COMPS.BITS_SHIFTED;
  4796.                   RESULT.SIGN := RIGHT.SIGN;
  4797.                end if;
  4798.             end if;
  4799.          -- The signs are the same
  4800.          when FALSE =>
  4801.             if LEFT.EXPONENT > RIGHT.EXPONENT then
  4802.                TEMP := ALIGN(RIGHT, LEFT.EXPONENT);
  4803.                RESULT.COMPS := LEFT.COMPS + TEMP.COMPS;
  4804.                RESULT.EXPONENT := LEFT.EXPONENT - RESULT.COMPS.BITS_SHIFTED;
  4805.                RESULT.SIGN := LEFT.SIGN;
  4806.             elsif LEFT.EXPONENT < RIGHT.EXPONENT then
  4807.                TEMP := ALIGN(LEFT, RIGHT.EXPONENT);
  4808.                RESULT.COMPS := RIGHT.COMPS + TEMP.COMPS;
  4809.                RESULT.EXPONENT := RIGHT.EXPONENT - RESULT.COMPS.BITS_SHIFTED;
  4810.                RESULT.SIGN := RIGHT.SIGN;
  4811.             else
  4812.                RESULT.COMPS := LEFT.COMPS + RIGHT.COMPS;
  4813.                RESULT.EXPONENT := LEFT.EXPONENT - RESULT.COMPS.BITS_SHIFTED;
  4814.                RESULT.SIGN := RIGHT.SIGN;
  4815.             end if;
  4816.  
  4817.       end case;
  4818.  
  4819.       RESULT.COMPS.BITS_SHIFTED := 0;
  4820.       if RESULT.COMPS = ZERO.COMPS then
  4821.          RESULT.EXPONENT := 0;
  4822.          RESULT.SIGN := POS_SIGN;
  4823.       end if;
  4824.  
  4825.       ROUND_TO_TARGET(RESULT);
  4826.       return RESULT;
  4827.  
  4828.    exception
  4829.       when others =>
  4830.          raise MAE_NUMERIC_ERROR;
  4831.  
  4832.    end "+";
  4833.  
  4834. ------------------------------
  4835.  
  4836.    function "-"    (LEFT,RIGHT : MAE_LONG_FLOAT_TYPE) 
  4837.                        return MAE_LONG_FLOAT_TYPE is
  4838.       -- The purpose of this function is to subtract two
  4839.       -- MAE_LONG_FLOAT_TYPEs.
  4840.       RESULT : MAE_LONG_FLOAT_TYPE;
  4841.    begin
  4842.       -- subtract is same as add negative
  4843.          -- takin' the easy way
  4844.       RESULT := LEFT + (-RIGHT);
  4845.  
  4846.       return RESULT;
  4847.  
  4848.  
  4849.    exception
  4850.       when others =>
  4851.          raise MAE_NUMERIC_ERROR;
  4852.  
  4853.    end "-";
  4854.  
  4855. ------------------------------
  4856.  
  4857.    function "*"    (LEFT,RIGHT : MAE_LONG_FLOAT_TYPE) 
  4858.                        return MAE_LONG_FLOAT_TYPE is
  4859.       -- The purpose of this function is to multiply two
  4860.       -- MAE_LONG_FLOAT_TYPEs.
  4861.       RESULT : MAE_LONG_FLOAT_TYPE;
  4862.    begin
  4863.       RESULT.SIGN := not (LEFT.SIGN xor RIGHT.SIGN);
  4864.       -- zero check
  4865.       if (LEFT.COMPS.COMPONENT_ARRAY = ZERO.COMPS.COMPONENT_ARRAY) or
  4866.            (RIGHT.COMPS.COMPONENT_ARRAY = ZERO.COMPS.COMPONENT_ARRAY) then
  4867.          RESULT.COMPS := ZERO.COMPS;
  4868.          RESULT.EXPONENT := ZERO.EXPONENT;
  4869.          NORMALIZE_LONG_FLOAT(RESULT);
  4870.          ROUND_TO_TARGET(RESULT);
  4871.          return RESULT;
  4872.       -- one check
  4873.       elsif (LEFT = ONE) or (LEFT = -ONE) then
  4874.          RESULT.COMPS := RIGHT.COMPS;
  4875.          RESULT.EXPONENT := RIGHT.EXPONENT;
  4876.          NORMALIZE_LONG_FLOAT(RESULT);
  4877.          ROUND_TO_TARGET(RESULT);
  4878.          return RESULT;
  4879.       elsif (RIGHT = ONE) or (RIGHT = -ONE) then
  4880.          RESULT.COMPS := LEFT.COMPS;
  4881.          RESULT.EXPONENT := LEFT.EXPONENT;
  4882.          NORMALIZE_LONG_FLOAT(RESULT);
  4883.          ROUND_TO_TARGET(RESULT);
  4884.          return RESULT;
  4885.       end if;
  4886.  
  4887.       RESULT.COMPS := LEFT.COMPS * RIGHT.COMPS;
  4888.       if RESULT.COMPS.COMPONENT_ARRAY = ZERO.COMPS.COMPONENT_ARRAY then
  4889.          RESULT.EXPONENT := 0;
  4890.       else
  4891.          RESULT.EXPONENT := (LEFT.EXPONENT + RIGHT.EXPONENT)
  4892.                              - RESULT.COMPS.BITS_SHIFTED;
  4893.       end if;
  4894.       RESULT.COMPS.BITS_SHIFTED := 0;
  4895.  
  4896.       ROUND_TO_TARGET(RESULT);
  4897.       return RESULT;
  4898.  
  4899.    exception
  4900.       when others =>
  4901.          raise MAE_NUMERIC_ERROR;
  4902.  
  4903.    end "*";
  4904.  
  4905. ------------------------------
  4906.  
  4907.    function "/"    (LEFT,RIGHT : MAE_LONG_FLOAT_TYPE) 
  4908.                        return MAE_LONG_FLOAT_TYPE is
  4909.       -- The purpose of this function is to divide two
  4910.       -- MAE_LONG_FLOAT_TYPEs.
  4911.       RESULT : MAE_LONG_FLOAT_TYPE;
  4912.    begin
  4913.       RESULT.SIGN := not (LEFT.SIGN xor RIGHT.SIGN);
  4914.       -- zero check
  4915.       if (RIGHT.COMPS.COMPONENT_ARRAY = ZERO.COMPS.COMPONENT_ARRAY) then
  4916.          raise MAE_NUMERIC_ERROR;
  4917.       elsif (LEFT.COMPS.COMPONENT_ARRAY = ZERO.COMPS.COMPONENT_ARRAY) then
  4918.          RESULT.COMPS := ZERO.COMPS;
  4919.          RESULT.EXPONENT := ZERO.EXPONENT;
  4920.          NORMALIZE_LONG_FLOAT(RESULT);
  4921.          ROUND_TO_TARGET(RESULT);
  4922.          return RESULT;
  4923.       -- one check
  4924.       elsif (RIGHT = ONE) or (RIGHT = -ONE) then
  4925.          RESULT.COMPS := LEFT.COMPS;
  4926.          RESULT.EXPONENT := LEFT.EXPONENT;
  4927.          NORMALIZE_LONG_FLOAT(RESULT);
  4928.          ROUND_TO_TARGET(RESULT);
  4929.          return RESULT;
  4930.       end if;
  4931.  
  4932.       RESULT.COMPS := LEFT.COMPS / RIGHT.COMPS;
  4933.       if RESULT.COMPS.COMPONENT_ARRAY = ZERO.COMPS.COMPONENT_ARRAY then
  4934.          RESULT.EXPONENT := 0;
  4935.       else
  4936.          RESULT.EXPONENT := (LEFT.EXPONENT - RIGHT.EXPONENT)
  4937.                             - RESULT.COMPS.BITS_SHIFTED;
  4938.       end if;
  4939.       RESULT.COMPS.BITS_SHIFTED := 0;
  4940.  
  4941.       ROUND_TO_TARGET(RESULT);
  4942.       return RESULT;
  4943.  
  4944.    exception
  4945.       when others =>
  4946.          raise MAE_NUMERIC_ERROR;
  4947.  
  4948.    end "/";
  4949.  
  4950. ------------------------------
  4951.  
  4952.    function MULT (LEFT,RIGHT : MAE_LONG_FLOAT_TYPE) 
  4953.                        return MAE_LONG_FLOAT_TYPE is
  4954.       -- The purpose of this function is to multiply two
  4955.       -- MAE_LONG_FLOAT_TYPEs without rounding the result
  4956.       -- to the target precision.  This allows the exponentiation
  4957.       -- and string operation to maintain precision.
  4958.       RESULT : MAE_LONG_FLOAT_TYPE;
  4959.    begin
  4960.       RESULT.COMPS := LEFT.COMPS * RIGHT.COMPS;
  4961.       if RESULT.COMPS.COMPONENT_ARRAY = ZERO.COMPS.COMPONENT_ARRAY then
  4962.          RESULT.EXPONENT := 0;
  4963.       else
  4964.          RESULT.EXPONENT := (LEFT.EXPONENT + RIGHT.EXPONENT)
  4965.                              - RESULT.COMPS.BITS_SHIFTED;
  4966.       end if;
  4967.       RESULT.COMPS.BITS_SHIFTED := 0;
  4968.       RESULT.SIGN := not (LEFT.SIGN xor RIGHT.SIGN);
  4969.  
  4970.       return RESULT;
  4971.  
  4972.    exception
  4973.       when others =>
  4974.          raise MAE_NUMERIC_ERROR;
  4975.  
  4976.    end MULT;
  4977.  
  4978. ------------------------------
  4979.  
  4980.    function ADD (LEFT,RIGHT : MAE_LONG_FLOAT_TYPE) 
  4981.                        return MAE_LONG_FLOAT_TYPE is
  4982.       -- The purpose of this function is to add two
  4983.       -- MAE_LONG_FLOAT_TYPEs without rounding to the target
  4984.       -- precision.  This allows the exponentiation and
  4985.       -- string conversion routines to maintain accuracy.
  4986.       -- Since it has a specialized operation, both operator
  4987.       -- signs are assumed positive.
  4988.       RESULT, TEMP : MAE_LONG_FLOAT_TYPE;
  4989.    begin
  4990.       -- The signs are the same
  4991.       if LEFT.EXPONENT > RIGHT.EXPONENT then
  4992.          TEMP := ALIGN(RIGHT, LEFT.EXPONENT);
  4993.          RESULT.COMPS := LEFT.COMPS + TEMP.COMPS;
  4994.          RESULT.EXPONENT := LEFT.EXPONENT - RESULT.COMPS.BITS_SHIFTED;
  4995.       elsif LEFT.EXPONENT < RIGHT.EXPONENT then
  4996.          TEMP := ALIGN(LEFT, RIGHT.EXPONENT);
  4997.          RESULT.COMPS := RIGHT.COMPS + TEMP.COMPS;
  4998.          RESULT.EXPONENT := RIGHT.EXPONENT - RESULT.COMPS.BITS_SHIFTED;
  4999.       else
  5000.          RESULT.COMPS := LEFT.COMPS + RIGHT.COMPS;
  5001.          RESULT.EXPONENT := LEFT.EXPONENT - RESULT.COMPS.BITS_SHIFTED;
  5002.       end if;
  5003.  
  5004.       RESULT.SIGN := POS_SIGN;
  5005.       RESULT.COMPS.BITS_SHIFTED := 0;
  5006.       if RESULT.COMPS = ZERO.COMPS then
  5007.          RESULT.EXPONENT := 0;
  5008.          RESULT.SIGN := POS_SIGN;
  5009.       end if;
  5010.  
  5011.       return RESULT;
  5012.  
  5013.    exception
  5014.       when others =>
  5015.          raise MAE_NUMERIC_ERROR;
  5016.  
  5017.    end ADD;
  5018.  
  5019. ------------------------------
  5020.  
  5021.    function "**"   (LEFT : MAE_LONG_FLOAT_TYPE; RIGHT : INTEGER)
  5022.                        return MAE_LONG_FLOAT_TYPE is
  5023.    -- The purpose of this function is to raise a MAE_LONG_FLOAT_TYPE
  5024.    -- to a given power.  A simple loop with a multiplication could
  5025.    -- be done the given number, less one, times.  This method is
  5026.    -- inefficient, therefore a different algorithm is used.
  5027.    -- The use of additional memory to hold intermediate
  5028.    -- calculations will improve performance by reducing
  5029.    -- the number of multiplications.
  5030.       COUNT : INTEGER := RIGHT;
  5031.       REM_COUNT : INTEGER := RIGHT;
  5032.       RESULT : MAE_LONG_FLOAT_TYPE;
  5033.       POWER_2, POWER_4, POWER_8 : MAE_LONG_FLOAT_TYPE := ZERO;
  5034.       NEG_SIGN_EXP_FLAG : BOOLEAN := FALSE;
  5035.    begin
  5036.       -- if the power is less than 0, invert number, then continue
  5037.       if (COUNT < 0) then
  5038.          if LEFT = ZERO then
  5039.             raise MAE_NUMERIC_ERROR;
  5040.          end if;
  5041.          if COUNT = -1 then
  5042.             RESULT := ONE / LEFT;
  5043.             ROUND_TO_TARGET(RESULT);
  5044.             return RESULT;
  5045.          end if;
  5046.          NEG_SIGN_EXP_FLAG := TRUE;
  5047.          COUNT := abs(COUNT);
  5048.          REM_COUNT := COUNT;
  5049.       end if;
  5050.       -- if the power is 0, return 1
  5051.       if COUNT = 0 then return ONE;
  5052.       -- if the power is 1 or the number is 0 or 1, return the input number
  5053.       elsif (COUNT = 1) or (LEFT = ONE) or (LEFT = ZERO) then return LEFT;
  5054.       elsif COUNT > TWO_THREE_LESS_ONE then
  5055.          -- compute to POWER_8
  5056.          POWER_2 := MULT(LEFT, LEFT);
  5057.          POWER_4 := MULT(POWER_2, POWER_2);
  5058.          POWER_8 := MULT(POWER_4, POWER_4);
  5059.          RESULT := POWER_8;
  5060.          REM_COUNT := REM_COUNT - 8;
  5061.       elsif COUNT > TWO_TWO_LESS_ONE then
  5062.          -- compute to POWER_4
  5063.          POWER_2 := MULT(LEFT, LEFT);
  5064.          POWER_4 := MULT(POWER_2, POWER_2);
  5065.          RESULT := POWER_4;
  5066.          REM_COUNT := REM_COUNT - 4;
  5067.       else
  5068.          -- compute to POWER_2
  5069.          POWER_2 := MULT(LEFT, LEFT);
  5070.          RESULT := POWER_2;
  5071.          REM_COUNT := REM_COUNT - 2;
  5072.       end if;
  5073.  
  5074.       -- the pre-computed values are now used to build
  5075.       -- to the answer
  5076.  
  5077.       -- loop until the power is reduced to under the
  5078.       -- maximum pre-computed value
  5079.       loop
  5080.          if REM_COUNT < TWO_THREE then 
  5081.            exit;
  5082.          end if;
  5083.          RESULT := MULT(RESULT, POWER_8);
  5084.          REM_COUNT := REM_COUNT - 8;
  5085.       end loop;
  5086.  
  5087.       -- the remaining power may be between 4 .. 7
  5088.       if REM_COUNT > TWO_TWO_LESS_ONE then
  5089.          RESULT := MULT(RESULT, POWER_4);
  5090.          REM_COUNT := REM_COUNT - 4;
  5091.       end if;
  5092.  
  5093.       -- the remaining power may be between 2 .. 3
  5094.       if REM_COUNT > 1 then
  5095.          RESULT := MULT(RESULT, POWER_2);
  5096.          REM_COUNT := REM_COUNT - 2;
  5097.       end if;
  5098.  
  5099.       -- the remaining power may be 1, therefore the sign
  5100.       -- is negative if the input number is negative
  5101.       if REM_COUNT = 1 then
  5102.          RESULT := MULT(RESULT, LEFT);
  5103.       end if;
  5104.  
  5105.       -- If exponent was negative, the result is inverted 
  5106.       if NEG_SIGN_EXP_FLAG then
  5107.          RESULT := ONE / RESULT;
  5108.       end if;
  5109.  
  5110.       ROUND_TO_TARGET(RESULT);
  5111.       return RESULT;
  5112.  
  5113.    exception
  5114.       when others =>
  5115.          raise MAE_NUMERIC_ERROR;
  5116.  
  5117.    end "**";
  5118.  
  5119. ---------------------------
  5120.  
  5121.    procedure GET(FROM : in STRING;
  5122.                  ITEM : out MAE_LONG_FLOAT_TYPE;
  5123.                  LAST : out POSITIVE) is
  5124.    -- The purpose of this function is to convert a string
  5125.    -- of characters into the MAE_LONG_FLOAT_TYPE structure.
  5126.    -- The string is valid if an only if it conforms to the
  5127.    -- format specified by the LRM
  5128.    --
  5129.    -- FORE . AFT
  5130.    -- FORE . AFT E EXP
  5131.    -- where 
  5132.    --    FORE : decimal digits, optional leading spaces,
  5133.    --            and a minus sign for negative values
  5134.    --    "."  : the decimal point
  5135.    --    AFT  : decimal digits
  5136.    --    EXP  : sign (plus or minus) and exponent
  5137.    --
  5138.    -- and is within the specified range for 
  5139.    -- MAE_LONG_FLOAT_TYPEs.
  5140.       INDEX : INTEGER;
  5141.       RESULT, TEMP, MULTIPLIER : MAE_LONG_FLOAT_TYPE;
  5142.       NEG_SIGN_FLAG : BOOLEAN := FALSE;
  5143.       FRACTION_FLAG, EXPONENT_FLAG, NEG_SIGN_EXP_FLAG : BOOLEAN := FALSE;
  5144.       EMPTY_FLAG : BOOLEAN := TRUE;
  5145.       S_PTR, POWER_OF_TEN, BASE_TEN_EXP : INTEGER := 0;
  5146.  
  5147.    begin
  5148.       -- Strip leading spaces if necessary
  5149.       INDEX := FROM'first;
  5150.       for I in FROM'first .. FROM'last loop
  5151.          if FROM(I) /= ' ' then
  5152.             exit;
  5153.          else
  5154.             INDEX := INDEX + 1;
  5155.          end if;
  5156.          -- if the string is empty
  5157.          if INDEX > FROM'last then
  5158.             raise MAE_FORMAT_ERROR;
  5159.          end if;
  5160.       end loop;
  5161.  
  5162.       -- Set the sign flag(assigned to the result sign before exiting).
  5163.       if FROM(INDEX) = '-' then
  5164.          NEG_SIGN_FLAG := TRUE;
  5165.          INDEX := INDEX + 1;
  5166.       elsif FROM(INDEX) = '+' then
  5167.          INDEX := INDEX + 1;
  5168.       end if;
  5169.  
  5170.       -- if the string is empty
  5171.       if INDEX > FROM'last then
  5172.          raise MAE_FORMAT_ERROR;
  5173.       end if;
  5174.  
  5175.       -- Store the integer portion
  5176.  
  5177.       for I in INDEX .. FROM'last loop
  5178.          S_PTR := I;
  5179.  
  5180.          case FROM(I) is
  5181.             when '0' .. '9' =>
  5182.                -- Multiply old result by ten and add in the digit
  5183.                -- (recall that MULT is multiply, ADD is add)
  5184.  
  5185.                RESULT := MULT(RESULT, TEN);
  5186.                case FROM(I) is
  5187.  
  5188.                   when '0' => null;
  5189.                   when '1' => RESULT := ADD(RESULT, ONE);
  5190.                   when '2' => RESULT := ADD(RESULT, TWO);
  5191.                   when '3' => RESULT := ADD(RESULT, THREE);
  5192.                   when '4' => RESULT := ADD(RESULT, FOUR);
  5193.                   when '5' => RESULT := ADD(RESULT, FIVE);
  5194.                   when '6' => RESULT := ADD(RESULT, SIX);
  5195.                   when '7' => RESULT := ADD(RESULT, SEVEN);
  5196.                   when '8' => RESULT := ADD(RESULT, EIGHT);
  5197.                   when '9' => RESULT := ADD(RESULT, NINE);
  5198.                   when others => raise MAE_FORMAT_ERROR;
  5199.                end case;
  5200.                -- Once a digit is encountered set empty false
  5201.                EMPTY_FLAG := FALSE;
  5202.                -- If the digit followed the decimal point increase
  5203.                -- the exponent counter
  5204.                if FRACTION_FLAG then
  5205.                   POWER_OF_TEN := POWER_OF_TEN + 1;
  5206.                end if;
  5207.  
  5208.             when ' ' =>
  5209.                -- If there is a space, before a digit, after the sign 
  5210.                -- exception, else check if it is the end of the number
  5211.                if EMPTY_FLAG then
  5212.                   -- spaces after the sign
  5213.                   raise MAE_FORMAT_ERROR;
  5214.                else
  5215.                   for J in I+1 .. FROM'last loop
  5216.                      if FROM(J) /= ' ' then
  5217.                         raise MAE_FORMAT_ERROR;
  5218.                      end if;
  5219.                   end loop;
  5220.                   exit;
  5221.                end if;
  5222.  
  5223.             when '.' => 
  5224.                if FRACTION_FLAG or EMPTY_FLAG then
  5225.                   -- two decimal points, or leading point
  5226.                   raise MAE_FORMAT_ERROR;
  5227.                else
  5228.                   FRACTION_FLAG := TRUE;
  5229.                end if;
  5230.  
  5231.             when 'e' | 'E' => 
  5232.                if EMPTY_FLAG then
  5233.                   -- no decimal number
  5234.                   raise MAE_FORMAT_ERROR;
  5235.                else
  5236.                   -- Set the exponent flag on
  5237.                   EXPONENT_FLAG := TRUE;
  5238.                   exit;
  5239.                end if;
  5240.  
  5241.             when others => raise MAE_FORMAT_ERROR;
  5242.          end case;
  5243.       end loop;
  5244.  
  5245.       -- Set the sign
  5246.       if NEG_SIGN_FLAG then
  5247.          RESULT.SIGN := NEG_SIGN;
  5248.       else
  5249.          RESULT.SIGN := POS_SIGN;
  5250.       end if;
  5251.  
  5252.  
  5253.       -- If the string contained the 'E' determine the exponent
  5254.       if EXPONENT_FLAG then
  5255.          EMPTY_FLAG := TRUE;
  5256.  
  5257.          -- Check the sign 
  5258.          S_PTR := S_PTR + 1;
  5259.          if FROM(S_PTR) = '-' then
  5260.             NEG_SIGN_EXP_FLAG := TRUE;
  5261.             INDEX := INDEX + 1;
  5262.          elsif FROM(S_PTR) = '+' then
  5263.             INDEX := INDEX + 1;
  5264.          else
  5265.             raise MAE_NUMERIC_ERROR;
  5266.          end if;
  5267.  
  5268.  
  5269.          for I in S_PTR+1 .. FROM'last loop
  5270.  
  5271.             case FROM(I) is
  5272.                when '0' .. '9' =>
  5273.                   case FROM(I) is
  5274.  
  5275.                      when '0' => BASE_TEN_EXP := BASE_TEN_EXP*10;
  5276.                      when '1' => BASE_TEN_EXP := BASE_TEN_EXP*10 + 1;
  5277.                      when '2' => BASE_TEN_EXP := BASE_TEN_EXP*10 + 2;
  5278.                      when '3' => BASE_TEN_EXP := BASE_TEN_EXP*10 + 3;
  5279.                      when '4' => BASE_TEN_EXP := BASE_TEN_EXP*10 + 4;
  5280.                      when '5' => BASE_TEN_EXP := BASE_TEN_EXP*10 + 5;
  5281.                      when '6' => BASE_TEN_EXP := BASE_TEN_EXP*10 + 6;
  5282.                      when '7' => BASE_TEN_EXP := BASE_TEN_EXP*10 + 7;
  5283.                      when '8' => BASE_TEN_EXP := BASE_TEN_EXP*10 + 8;
  5284.                      when '9' => BASE_TEN_EXP := BASE_TEN_EXP*10 + 9;
  5285.                      when others => raise MAE_FORMAT_ERROR;
  5286.                   end case;
  5287.                   EMPTY_FLAG := FALSE;
  5288.  
  5289.                when ' ' => 
  5290.                   if EMPTY_FLAG then
  5291.                      -- no exponent number
  5292.                     raise MAE_FORMAT_ERROR;
  5293.                   else
  5294.                      for J in I+1 .. FROM'last loop
  5295.                         if FROM(J) /= ' ' then
  5296.                            raise MAE_FORMAT_ERROR;
  5297.                         end if;
  5298.                      end loop;
  5299.                      exit;
  5300.                   end if;
  5301.  
  5302.                when others => raise MAE_FORMAT_ERROR;
  5303.  
  5304.             end case;
  5305.          end loop;
  5306.       end if;
  5307.  
  5308.       if EMPTY_FLAG or (POWER_OF_TEN = 0) then
  5309.          -- either (no number) or (no exponent) or (no fraction)
  5310.          raise MAE_FORMAT_ERROR;
  5311.       end if;
  5312.  
  5313.       if RESULT.COMPS = ZERO.COMPS then
  5314.          ITEM := ZERO;
  5315.       else
  5316.          -- If the base ten exponent was negative.
  5317.          if NEG_SIGN_EXP_FLAG then
  5318.             BASE_TEN_EXP := -BASE_TEN_EXP;
  5319.          end if;
  5320.  
  5321.          -- Now we must adjust the base ten exponent by the number of
  5322.          -- digits that follow the decimal point in the string.
  5323.          BASE_TEN_EXP := BASE_TEN_EXP - POWER_OF_TEN;
  5324.  
  5325.          -- If the input base ten exponent needs to be translated
  5326.          -- into a base two exponent, use the "and" routine to
  5327.          -- multiply but round after the final multiply.
  5328.          if BASE_TEN_EXP /= 0 then
  5329.            if BASE_TEN_EXP > 0 then
  5330.                while BASE_TEN_EXP >= 4 loop
  5331.                   RESULT := MULT(RESULT, TEN_THOUSAND);
  5332.                   BASE_TEN_EXP := BASE_TEN_EXP - 4;
  5333.                end loop;
  5334.                if BASE_TEN_EXP = 3 then
  5335.                   RESULT := MULT(RESULT, THOUSAND);
  5336.                end if;
  5337.                if BASE_TEN_EXP = 2 then
  5338.                   RESULT := MULT(RESULT, HUNDRED);
  5339.                end if;
  5340.                if BASE_TEN_EXP = 1 then
  5341.                   RESULT := MULT(RESULT, TEN);
  5342.                end if;
  5343.             else
  5344.                while BASE_TEN_EXP <= -4 loop
  5345.                   RESULT := MULT(RESULT, ONE_TEN_THOUSANDTH);
  5346.                   BASE_TEN_EXP := BASE_TEN_EXP + 4;
  5347.                end loop;
  5348.                if BASE_TEN_EXP = -3 then
  5349.                   RESULT := MULT(RESULT, ONE_THOUSANDTH);
  5350.                end if;
  5351.                if BASE_TEN_EXP = -2 then
  5352.                   RESULT := MULT(RESULT, ONE_HUNDREDTH);
  5353.                end if;
  5354.                if BASE_TEN_EXP = -1 then
  5355.                   RESULT := MULT(RESULT, ONE_TENTH);
  5356.                end if;
  5357.             end if;
  5358.          end if;
  5359.  
  5360.          ROUND_TO_TARGET(RESULT);
  5361.  
  5362.          ITEM := RESULT;
  5363.       end if;
  5364.  
  5365.       LAST := FROM'last;
  5366.  
  5367.  
  5368.    exception
  5369.       when others =>
  5370.          raise DATA_ERROR;
  5371.  
  5372.    end GET;
  5373.  
  5374. ------------------------------
  5375.  
  5376.    procedure MULT_BY_TEN (RESULT : in out COMPONENT_ARRAY_TYPE) is
  5377.       -- This routine is used by the binary to ASCII conversion
  5378.       -- (PUT) to extract the next digit by multiplying the
  5379.       -- array by ten, thus the digit is the most signif
  5380.       -- comp of the array "integer divided" by ten.
  5381.    begin
  5382.       for I in RESULT'first .. RESULT'last loop
  5383.          RESULT(I) := RESULT(I) * 10;
  5384.       end loop;
  5385.       RANGE_CHECK(RESULT);
  5386.  
  5387.    end MULT_BY_TEN;
  5388.  
  5389. ------------------------------
  5390.  
  5391.    procedure PUT(TO : out STRING;
  5392.                  ITEM : in MAE_LONG_FLOAT_TYPE;
  5393.                  AFT : in FIELD := LONG_DEFAULT_AFT;
  5394.                  EXP : in FIELD := LONG_DEFAULT_EXP) is
  5395.       -- The purpose of this function is to convert a 
  5396.       -- MAE_LONG_FLOAT_TYPE into string of characters.
  5397.       COMP_PTR, INDEX : INTEGER;
  5398.       RESULT : MAE_LONG_FLOAT_TYPE := ITEM;
  5399.       WORK_ARRAY : LONG_COMPONENT_ARRAY;
  5400.       TEMP_CHAR : STRING (1 .. 1);
  5401.       TEMP_VALUE : INTEGER;
  5402.       STRING_PIC : STRING (1 .. LONG_FLOAT_DIGITS+1) :=
  5403.                       EMPTY_STRING(1 .. LONG_FLOAT_DIGITS+1);
  5404.       DECIMAL_VALUE, OFFSET, OFFSET_BITS, POWER_OF_TEN : INTEGER := 0;
  5405.  
  5406.       LSB : INTEGER := (NO_COMP_BITS + 1 + (2*(LONG_FLOAT_DIGITS)));
  5407.       LSC, BIT_IN_LSC : INTEGER;
  5408.  
  5409.       NEG_SIGN_FLAG, NEG_SIGN_EXP_FLAG : BOOLEAN := FALSE;
  5410.       DISPLAY_DIGITS : INTEGER := 0;
  5411.       FIRST_DIGIT : BOOLEAN := TRUE;
  5412.  
  5413.       TO_INDEX : INTEGER := 0;
  5414.       EXPONENT_STRING : STRING (1 .. 4) := "   0";
  5415.       EXPONENT_INDEX : INTEGER := 0;
  5416.       EXPONENT_LENGTH : INTEGER := 1;
  5417.  
  5418.       ALMOST_ZERO : MAE_LONG_FLOAT_TYPE := ZERO;
  5419.  
  5420.       ACTUAL_FORE : INTEGER := 1;
  5421.       ACTUAL_AFT : INTEGER := AFT;
  5422.       ACTUAL_EXP : INTEGER := EXP;
  5423.  
  5424.       FORE_FIELD_ZERO_FLAG : BOOLEAN := FALSE;
  5425.       FORE_WIDTH_DIGITS_BEYOND_PRECISION : INTEGER := 0;
  5426.       AFT_WIDTH_DIGITS_BEYOND_PRECISION : INTEGER := 0;
  5427.       AFT_LEADING_ZERO_DIGITS : INTEGER := 0;
  5428.       SIGNIFICANT_AFT : INTEGER := 0;
  5429.  
  5430.    begin
  5431.       TO(TO'first .. TO'last) := EMPTY_STRING(1 .. TO'length);
  5432.  
  5433.       -- The variable INDEX is the pointer into the string.
  5434.       INDEX := STRING_PIC'first;
  5435.  
  5436.       -- Check for zero.
  5437.       if RESULT.COMPS /= ZERO.COMPS then
  5438.  
  5439.          -- Store the sign
  5440.          if RESULT.SIGN = NEG_SIGN then
  5441.             NEG_SIGN_FLAG := TRUE;
  5442.             RESULT.SIGN := POS_SIGN;
  5443.          end if;
  5444.    
  5445.          -- Determine the base ten exponent by forcing the result
  5446.          -- into the range .1 <= x < 1., and tracking the count.
  5447.          POWER_OF_TEN := -1;
  5448.          if RESULT < ONE then
  5449.             while RESULT < ONE_TEN_THOUSANDTH loop
  5450.                RESULT := MULT(RESULT, TEN_THOUSAND);
  5451.                POWER_OF_TEN := POWER_OF_TEN - 4;
  5452.             end loop;
  5453.             if RESULT < ONE_THOUSANDTH then
  5454.                RESULT := MULT(RESULT, THOUSAND);
  5455.                POWER_OF_TEN := POWER_OF_TEN - 3;
  5456.             end if;
  5457.             if RESULT < ONE_HUNDREDTH then
  5458.                RESULT := MULT(RESULT, HUNDRED);
  5459.                POWER_OF_TEN := POWER_OF_TEN - 2;
  5460.             end if;
  5461.             if RESULT < ONE_TENTH then
  5462.                RESULT := MULT(RESULT, TEN);
  5463.                POWER_OF_TEN := POWER_OF_TEN - 1;
  5464.             end if;
  5465.          else
  5466.             while RESULT >= THOUSAND loop
  5467.                RESULT := MULT(RESULT, ONE_TEN_THOUSANDTH);
  5468.                POWER_OF_TEN := POWER_OF_TEN + 4;
  5469.             end loop;
  5470.             if RESULT >= HUNDRED then
  5471.                RESULT := MULT(RESULT, ONE_THOUSANDTH);
  5472.                POWER_OF_TEN := POWER_OF_TEN + 3;
  5473.             end if;
  5474.             if RESULT >= TEN then
  5475.                RESULT := MULT(RESULT, ONE_HUNDREDTH);
  5476.                POWER_OF_TEN := POWER_OF_TEN + 2;
  5477.             end if;
  5478.             if RESULT >= ONE then
  5479.                RESULT := MULT(RESULT, ONE_TENTH);
  5480.                POWER_OF_TEN := POWER_OF_TEN + 1;
  5481.             end if;
  5482.          end if;
  5483.  
  5484.          -- Store the integer portion
  5485.          -- The OFFSET corrects the decimal value with respect to the
  5486.          -- RESULT.EXPONENT which must equal (0 | -1 | -2 | -3)
  5487.          OFFSET_BITS := -RESULT.EXPONENT;
  5488.          OFFSET := BASE_COMP_VALUE * (2**(OFFSET_BITS));
  5489.  
  5490.          -- Loop over the MAE_NUMBER taking the most significant
  5491.          -- decimal digit and storing it in the array(forewards)
  5492.          WORK_ARRAY := RESULT.COMPS.COMPONENT_ARRAY;
  5493.          -- The variable ALMOST_ZERO is zero thru all significant bits
  5494.          while (WORK_ARRAY > ALMOST_ZERO.COMPS.COMPONENT_ARRAY) loop
  5495.             -- Determine where the scaled least signif bit is located
  5496.             LSC := ((LONG_NUM_BITS - LSB) / NO_COMP_BITS) + 1;
  5497.             BIT_IN_LSC := ((LSB-1) rem NO_COMP_BITS) + 1;
  5498.             -- The least signif bit is scaled down by two bits
  5499.             -- instead of the true inverse log(2) which is approx 3.322
  5500.             -- since the original LSB is less than TARGET_LONG_NUM_BITS.
  5501.             LSB := LSB - 2;
  5502.             ALMOST_ZERO.COMPS.COMPONENT_ARRAY(LSC) := BIT_VALUE(BIT_IN_LSC);
  5503.             ALMOST_ZERO.COMPS.COMPONENT_ARRAY(LSC-1) := 0;
  5504.  
  5505.             MULT_BY_TEN(WORK_ARRAY);
  5506.  
  5507.             -- If the rest of the number(significant) is all nines, round up.
  5508.             if (WORK_ARRAY(WORK_ARRAY'last) rem BASE_COMP_VALUE) = 
  5509.                                  MAX_COMP_VALUE then
  5510.                COMP_PTR := WORK_ARRAY'last - 1;
  5511.                while WORK_ARRAY(COMP_PTR) = MAX_COMP_VALUE loop
  5512.                   COMP_PTR := COMP_PTR - 1;
  5513.                   if COMP_PTR <= LSC then
  5514.                      if (WORK_ARRAY(LSC) / BIT_VALUE(BIT_IN_LSC)) =
  5515.                             (MAX_COMP_VALUE / BIT_VALUE(BIT_IN_LSC)) then
  5516.                         -- Instead of adding a rounding value just set to
  5517.                         -- BASE_COMP_VALUE since either case will produce
  5518.                         -- a remaining number less than ALMOST_ZERO
  5519.                         WORK_ARRAY(LSC) := BASE_COMP_VALUE;
  5520.                         RANGE_CHECK(WORK_ARRAY);
  5521.                      end if;
  5522.                      exit;
  5523.                   end if;
  5524.                end loop;
  5525.             end if;
  5526.  
  5527.             -- Extract the decimal value from the array.
  5528.             DECIMAL_VALUE := WORK_ARRAY(WORK_ARRAY'last) / OFFSET;
  5529.             WORK_ARRAY(WORK_ARRAY'last) := WORK_ARRAY(WORK_ARRAY'last) -
  5530.                                               (DECIMAL_VALUE * OFFSET);
  5531.  
  5532.             -- The next check is valid the first time thru the loop
  5533.             -- and remedies the .99999999999 ...    case.
  5534.             if FIRST_DIGIT then
  5535.                FIRST_DIGIT := FALSE;
  5536.                if DECIMAL_VALUE = 10 then
  5537.                   STRING_PIC(INDEX) := '1';
  5538.                   INDEX := INDEX + 1;
  5539.                   POWER_OF_TEN := POWER_OF_TEN + 1;
  5540.                   exit;
  5541.                end if;
  5542.             end if;
  5543.  
  5544.             -- Get the ASCII value of the decimal value
  5545.             -- and store it in the string
  5546.             TEMP_CHAR := INTEGER'image(DECIMAL_VALUE);
  5547.             STRING_PIC(INDEX) := TEMP_CHAR(1);
  5548.             INDEX := INDEX + 1;
  5549.  
  5550.             -- If the (display number+1) decimal digits are in the string.
  5551.             if (INDEX=STRING_PIC'last+1) or (LSB<=NO_COMP_BITS) then
  5552.                exit;
  5553.             end if;
  5554.          end loop;
  5555.       end if;
  5556.  
  5557.       for I in INDEX .. STRING_PIC'last loop
  5558.          STRING_PIC(I) := '0';
  5559.       end loop;
  5560.  
  5561.       if AFT = 0 then
  5562.          ACTUAL_AFT := 1;
  5563.       end if;
  5564.       if EXP = 1 then
  5565.          ACTUAL_EXP := 2;
  5566.       end if;
  5567.  
  5568.       -- determine the number of digits to produce
  5569.       if ACTUAL_EXP /= 0 then
  5570.          -- ACTUAL_FORE must equal one
  5571.          if (ACTUAL_FORE + ACTUAL_AFT) <= LONG_FLOAT_DIGITS then
  5572.             DISPLAY_DIGITS := ACTUAL_FORE + ACTUAL_AFT;
  5573.          else
  5574.             DISPLAY_DIGITS := LONG_FLOAT_DIGITS;
  5575.             AFT_WIDTH_DIGITS_BEYOND_PRECISION :=
  5576.                     ACTUAL_AFT - (LONG_FLOAT_DIGITS - ACTUAL_FORE);
  5577.             ACTUAL_AFT := (LONG_FLOAT_DIGITS - ACTUAL_FORE);
  5578.          end if;
  5579.       else
  5580.          if POWER_OF_TEN >= 0 then
  5581.             ACTUAL_FORE := POWER_OF_TEN + 1;
  5582.             if (ACTUAL_FORE + ACTUAL_AFT) <= LONG_FLOAT_DIGITS then
  5583.                DISPLAY_DIGITS := ACTUAL_FORE + ACTUAL_AFT;
  5584.             else
  5585.                DISPLAY_DIGITS := LONG_FLOAT_DIGITS;
  5586.                AFT_WIDTH_DIGITS_BEYOND_PRECISION :=
  5587.                     ACTUAL_AFT - (LONG_FLOAT_DIGITS - ACTUAL_FORE);
  5588.                if AFT_WIDTH_DIGITS_BEYOND_PRECISION >= ACTUAL_AFT then
  5589.                   AFT_WIDTH_DIGITS_BEYOND_PRECISION := ACTUAL_AFT;
  5590.                   ACTUAL_AFT := 0;
  5591.                   FORE_WIDTH_DIGITS_BEYOND_PRECISION := 
  5592.                        ACTUAL_FORE - LONG_FLOAT_DIGITS;
  5593.                   ACTUAL_FORE := LONG_FLOAT_DIGITS;
  5594.                else
  5595.                   ACTUAL_AFT := (LONG_FLOAT_DIGITS - ACTUAL_FORE);
  5596.                end if;
  5597.             end if;
  5598.          else
  5599.             -- ACTUAL_FORE must equal one, with a value of zero
  5600.             FORE_FIELD_ZERO_FLAG := TRUE;
  5601.             AFT_LEADING_ZERO_DIGITS := abs(POWER_OF_TEN+1);
  5602.             SIGNIFICANT_AFT := ACTUAL_AFT - AFT_LEADING_ZERO_DIGITS;
  5603.             if SIGNIFICANT_AFT <= LONG_FLOAT_DIGITS then
  5604.                DISPLAY_DIGITS := SIGNIFICANT_AFT;
  5605.                if SIGNIFICANT_AFT <= 0 then
  5606.                   AFT_LEADING_ZERO_DIGITS := ACTUAL_AFT;
  5607.                   ACTUAL_AFT := 0;
  5608.                elsif SIGNIFICANT_AFT > 0 then
  5609.                   ACTUAL_AFT := SIGNIFICANT_AFT;
  5610.                end if;
  5611.             else
  5612.                DISPLAY_DIGITS := LONG_FLOAT_DIGITS;
  5613.                AFT_WIDTH_DIGITS_BEYOND_PRECISION := 
  5614.                   SIGNIFICANT_AFT - LONG_FLOAT_DIGITS;
  5615.                ACTUAL_AFT := LONG_FLOAT_DIGITS;
  5616.             end if;
  5617.          end if;
  5618.       end if;
  5619.  
  5620.       if DISPLAY_DIGITS > 0 then
  5621.          -- Round the digit in the last-1 position using the last digit.
  5622.          INDEX := DISPLAY_DIGITS + 1;
  5623.          if STRING_PIC(INDEX) >= '5' then
  5624.             STRING_PIC(INDEX) := '0';
  5625.             INDEX := INDEX - 1;
  5626.             STRING_PIC(INDEX) := CHARACTER'succ(STRING_PIC(INDEX));
  5627.             while STRING_PIC(INDEX) > '9' loop
  5628.                if INDEX = STRING_PIC'first then
  5629.                   -- rounding to outside array can only occur if
  5630.                   -- with FORE=1, value=0
  5631.                   STRING_PIC(INDEX) := '1';
  5632.                   POWER_OF_TEN := POWER_OF_TEN + 1;
  5633.                   if POWER_OF_TEN = 0 then
  5634.                      FORE_FIELD_ZERO_FLAG := FALSE;
  5635.                   elsif AFT_LEADING_ZERO_DIGITS > 0 then
  5636.                      AFT_LEADING_ZERO_DIGITS := AFT_LEADING_ZERO_DIGITS - 1;
  5637.                      AFT_WIDTH_DIGITS_BEYOND_PRECISION :=
  5638.                                AFT_WIDTH_DIGITS_BEYOND_PRECISION + 1;
  5639.                   end if;
  5640.                   exit;
  5641.                end if;
  5642.                      
  5643.                STRING_PIC(INDEX) := '0';
  5644.                INDEX := INDEX - 1;
  5645.                STRING_PIC(INDEX) := CHARACTER'succ(STRING_PIC(INDEX));
  5646.             end loop;      
  5647.             INDEX := INDEX + 1;
  5648.          else
  5649.             STRING_PIC(INDEX) := '0';
  5650.          end if;
  5651.       elsif DISPLAY_DIGITS = 0 then
  5652.          if STRING_PIC(STRING_PIC'first) >= '5' then
  5653.             STRING_PIC(STRING_PIC'first) := '1';
  5654.             POWER_OF_TEN := POWER_OF_TEN + 1;
  5655.             if POWER_OF_TEN = 0 then
  5656.                FORE_FIELD_ZERO_FLAG := FALSE;
  5657.             else
  5658.                AFT_LEADING_ZERO_DIGITS := AFT_LEADING_ZERO_DIGITS - 1;
  5659.                ACTUAL_AFT := 1;
  5660.             end if;
  5661.          end if;
  5662.       end if;      
  5663.  
  5664.       if (ACTUAL_EXP = 0) then
  5665.          -- fill the string in reverse
  5666.          TO_INDEX := TO'last;
  5667.          if FORE_FIELD_ZERO_FLAG then
  5668.             -- fore field is zero
  5669.             -- store the aft field
  5670.             for I in 1 .. AFT_WIDTH_DIGITS_BEYOND_PRECISION loop
  5671.                TO(TO_INDEX) := '0';
  5672.                TO_INDEX := TO_INDEX - 1;
  5673.             end loop;
  5674.             for I in reverse 1 .. ACTUAL_AFT loop
  5675.                TO(TO_INDEX) := STRING_PIC(I);
  5676.                TO_INDEX := TO_INDEX - 1;
  5677.             end loop;
  5678.             for I in 1 .. AFT_LEADING_ZERO_DIGITS loop
  5679.                TO(TO_INDEX) := '0';
  5680.                TO_INDEX := TO_INDEX - 1;
  5681.             end loop;
  5682.             TO(TO_INDEX) := '.';
  5683.             TO_INDEX := TO_INDEX - 1;
  5684.             TO(TO_INDEX) := '0';
  5685.             TO_INDEX := TO_INDEX - 1;
  5686.             if NEG_SIGN_FLAG then
  5687.                TO(TO_INDEX) := '-';
  5688.                TO_INDEX := TO_INDEX - 1;
  5689.             end if;
  5690.          else
  5691.             -- non-zero fore field
  5692.             for I in 1 .. AFT_WIDTH_DIGITS_BEYOND_PRECISION loop
  5693.                TO(TO_INDEX) := '0';
  5694.                TO_INDEX := TO_INDEX - 1;
  5695.             end loop;
  5696.             for I in reverse 1 .. ACTUAL_AFT loop
  5697.                TO(TO_INDEX) := STRING_PIC(ACTUAL_FORE+I);
  5698.                TO_INDEX := TO_INDEX - 1;
  5699.             end loop;
  5700.             TO(TO_INDEX) := '.';
  5701.             TO_INDEX := TO_INDEX - 1;
  5702.             for I in 1 .. FORE_WIDTH_DIGITS_BEYOND_PRECISION loop
  5703.                TO(TO_INDEX) := '0';
  5704.                TO_INDEX := TO_INDEX - 1;
  5705.             end loop;
  5706.             for I in reverse 1 .. ACTUAL_FORE loop
  5707.                TO(TO_INDEX) := STRING_PIC(I);
  5708.                TO_INDEX := TO_INDEX - 1;
  5709.             end loop;
  5710.             if NEG_SIGN_FLAG then
  5711.                TO(TO_INDEX) := '-';
  5712.                TO_INDEX := TO_INDEX - 1;
  5713.             end if;
  5714.          end if;
  5715.       else
  5716.          if STRING_PIC(STRING_PIC'first) = '0' then
  5717.             -- zero string, the length includes leading zero,
  5718.             -- '.', AFT, 'E', EXP 
  5719.             TO_INDEX := TO'last - (2 + ACTUAL_AFT + ACTUAL_EXP);
  5720.             TO(TO_INDEX) := '0';
  5721.             TO_INDEX := TO_INDEX + 1;
  5722.             TO(TO_INDEX) := '.';
  5723.             TO_INDEX := TO_INDEX + 1;
  5724.             -- fill out the aft field
  5725.             for I in 1 .. ACTUAL_AFT loop
  5726.                TO(TO_INDEX) := '0';
  5727.                TO_INDEX := TO_INDEX + 1;
  5728.             end loop;
  5729.             TO(TO_INDEX) := 'E';
  5730.             TO_INDEX := TO_INDEX + 1;
  5731.             TO(TO_INDEX) := '+';
  5732.             TO_INDEX := TO_INDEX + 1;
  5733.             -- fill out the exponent field
  5734.             for I in 1 .. ACTUAL_EXP-1 loop
  5735.                TO(TO_INDEX) := '0';
  5736.                TO_INDEX := TO_INDEX + 1;
  5737.             end loop;
  5738.          else
  5739.             -- If there is an exponent, store it in the string.
  5740.             if POWER_OF_TEN /= 0 then
  5741.                if POWER_OF_TEN < 0 then
  5742.                   NEG_SIGN_EXP_FLAG := TRUE;
  5743.                   POWER_OF_TEN := abs(POWER_OF_TEN);
  5744.                end if;
  5745.  
  5746.                -- determine the base ten exponent
  5747.                -- fill the string in reverse
  5748.                EXPONENT_INDEX := EXPONENT_STRING'last;
  5749.                while POWER_OF_TEN /= 0 loop
  5750.                   TEMP_VALUE := POWER_OF_TEN rem 10;
  5751.                   POWER_OF_TEN := POWER_OF_TEN / 10;
  5752.                   TEMP_CHAR := INTEGER'image(TEMP_VALUE);
  5753.                   EXPONENT_STRING(EXPONENT_INDEX) := TEMP_CHAR(1);
  5754.                   EXPONENT_INDEX := EXPONENT_INDEX - 1;
  5755.                end loop;
  5756.                EXPONENT_LENGTH := EXPONENT_STRING'last - EXPONENT_INDEX;
  5757.             end if;
  5758.  
  5759.             -- fill the string in reverse
  5760.             TO_INDEX := TO'last;
  5761.             -- store the exponent field
  5762.             for I in 1 .. EXPONENT_LENGTH loop
  5763.                TO(TO_INDEX) := EXPONENT_STRING((EXPONENT_STRING'last+1)-I);
  5764.                TO_INDEX := TO_INDEX - 1;
  5765.             end loop;
  5766.             -- fill out the exponent field
  5767.             for I in EXPONENT_LENGTH+1 .. ACTUAL_EXP-1 loop
  5768.                TO(TO_INDEX) := '0';
  5769.                TO_INDEX := TO_INDEX - 1;
  5770.             end loop;
  5771.             if NEG_SIGN_EXP_FLAG then
  5772.                TO(TO_INDEX) := '-';
  5773.             else
  5774.                TO(TO_INDEX) := '+';
  5775.             end if;
  5776.             TO_INDEX := TO_INDEX - 1;
  5777.             TO(TO_INDEX) := 'E';
  5778.             TO_INDEX := TO_INDEX - 1;
  5779.             -- store the aft field
  5780.             for I in 1 .. AFT_WIDTH_DIGITS_BEYOND_PRECISION loop
  5781.                TO(TO_INDEX) := '0';
  5782.                TO_INDEX := TO_INDEX - 1;
  5783.             end loop;
  5784.             for I in reverse 1 .. ACTUAL_AFT loop
  5785.                TO(TO_INDEX) := STRING_PIC(I+1);
  5786.                TO_INDEX := TO_INDEX - 1;
  5787.             end loop;
  5788.             TO(TO_INDEX) := '.';
  5789.             TO_INDEX := TO_INDEX - 1;
  5790.             TO(TO_INDEX) := STRING_PIC(STRING_PIC'first);
  5791.             TO_INDEX := TO_INDEX - 1;
  5792.             if NEG_SIGN_FLAG then
  5793.                TO(TO_INDEX) := '-';
  5794.                TO_INDEX := TO_INDEX - 1;
  5795.             end if;
  5796.          end if;
  5797.       end if;
  5798.                
  5799.    exception
  5800.       when others =>
  5801.          raise LAYOUT_ERROR;
  5802.  
  5803.    end PUT;
  5804.  
  5805. ---------------------------
  5806. -- The body of the package.
  5807. --
  5808. begin
  5809.  
  5810.    -- Initialize the digits ONE .. TEN with the DIGIT_PICTURE 
  5811.    -- and DIGIT_BINARY_EXPONENT arrays, and initialize ONE_TENTH 
  5812.    -- with an array specified in MAE_BASIC_OPERATIONS.  This allows
  5813.    -- for the length of the array to change in the basic operations
  5814.    -- and not caused a coding change in this package.  
  5815.    -- Notice that these values assume the declaration of the type
  5816.    -- is initially a zero value.  This assumption is justified since
  5817.    -- the declaration of the type is in this package specification.
  5818.    -- ZERO taken care of by the initial value.
  5819.    ONE.COMPS.COMPONENT_ARRAY(LONG_NUM_COMPS) := DIGIT_PICTURE(1);
  5820.    ONE.EXPONENT := DIGIT_BINARY_EXPONENT(1);
  5821.    TWO.COMPS.COMPONENT_ARRAY(LONG_NUM_COMPS) := DIGIT_PICTURE(2);
  5822.    TWO.EXPONENT := DIGIT_BINARY_EXPONENT(2);
  5823.    THREE.COMPS.COMPONENT_ARRAY(LONG_NUM_COMPS) := DIGIT_PICTURE(3);
  5824.    THREE.EXPONENT := DIGIT_BINARY_EXPONENT(3);
  5825.    FOUR.COMPS.COMPONENT_ARRAY(LONG_NUM_COMPS) := DIGIT_PICTURE(4);
  5826.    FOUR.EXPONENT := DIGIT_BINARY_EXPONENT(4);
  5827.    FIVE.COMPS.COMPONENT_ARRAY(LONG_NUM_COMPS) := DIGIT_PICTURE(5);
  5828.    FIVE.EXPONENT := DIGIT_BINARY_EXPONENT(5);
  5829.    SIX.COMPS.COMPONENT_ARRAY(LONG_NUM_COMPS) := DIGIT_PICTURE(6);
  5830.    SIX.EXPONENT := DIGIT_BINARY_EXPONENT(6);
  5831.    SEVEN.COMPS.COMPONENT_ARRAY(LONG_NUM_COMPS) := DIGIT_PICTURE(7);
  5832.    SEVEN.EXPONENT := DIGIT_BINARY_EXPONENT(7);
  5833.    EIGHT.COMPS.COMPONENT_ARRAY(LONG_NUM_COMPS) := DIGIT_PICTURE(8);
  5834.    EIGHT.EXPONENT := DIGIT_BINARY_EXPONENT(8);
  5835.    NINE.COMPS.COMPONENT_ARRAY(LONG_NUM_COMPS) := DIGIT_PICTURE(9);
  5836.    NINE.EXPONENT := DIGIT_BINARY_EXPONENT(9);
  5837.    TEN.COMPS.COMPONENT_ARRAY(LONG_NUM_COMPS) := DIGIT_PICTURE(10);
  5838.    TEN.EXPONENT := DIGIT_BINARY_EXPONENT(10);
  5839.  
  5840.    HUNDRED.COMPS := TEN.COMPS * TEN.COMPS;
  5841.    HUNDRED.EXPONENT := (TEN.EXPONENT + TEN.EXPONENT)
  5842.                             - HUNDRED.COMPS.BITS_SHIFTED;
  5843.    HUNDRED.COMPS.BITS_SHIFTED := 0;
  5844.  
  5845.    THOUSAND.COMPS := HUNDRED.COMPS * TEN.COMPS;
  5846.    THOUSAND.EXPONENT := (HUNDRED.EXPONENT + TEN.EXPONENT)
  5847.                             - THOUSAND.COMPS.BITS_SHIFTED;
  5848.    THOUSAND.COMPS.BITS_SHIFTED := 0;
  5849.  
  5850.    TEN_THOUSAND.COMPS := THOUSAND.COMPS * TEN.COMPS;
  5851.    TEN_THOUSAND.EXPONENT := (THOUSAND.EXPONENT + TEN.EXPONENT)
  5852.                             - TEN_THOUSAND.COMPS.BITS_SHIFTED;
  5853.    TEN_THOUSAND.COMPS.BITS_SHIFTED := 0;
  5854.  
  5855.  
  5856.    ONE_TENTH.COMPS := ONE.COMPS / TEN.COMPS;
  5857.    ONE_TENTH.EXPONENT := (ONE.EXPONENT - TEN.EXPONENT)
  5858.                             - ONE_TENTH.COMPS.BITS_SHIFTED;
  5859.    ONE_TENTH.COMPS.BITS_SHIFTED := 0;
  5860.  
  5861.    ONE_HUNDREDTH.COMPS := ONE_TENTH.COMPS / TEN.COMPS;
  5862.    ONE_HUNDREDTH.EXPONENT := (ONE_TENTH.EXPONENT - TEN.EXPONENT)
  5863.                             - ONE_HUNDREDTH.COMPS.BITS_SHIFTED;
  5864.    ONE_HUNDREDTH.COMPS.BITS_SHIFTED := 0;
  5865.  
  5866.    ONE_THOUSANDTH.COMPS := ONE_HUNDREDTH.COMPS / TEN.COMPS;
  5867.    ONE_THOUSANDTH.EXPONENT := (ONE_HUNDREDTH.EXPONENT - TEN.EXPONENT)
  5868.                             - ONE_THOUSANDTH.COMPS.BITS_SHIFTED;
  5869.    ONE_THOUSANDTH.COMPS.BITS_SHIFTED := 0;
  5870.  
  5871.    ONE_TEN_THOUSANDTH.COMPS := ONE_THOUSANDTH.COMPS / TEN.COMPS;
  5872.    ONE_TEN_THOUSANDTH.EXPONENT := (ONE_THOUSANDTH.EXPONENT - TEN.EXPONENT)
  5873.                             - ONE_TEN_THOUSANDTH.COMPS.BITS_SHIFTED;
  5874.    ONE_TEN_THOUSANDTH.COMPS.BITS_SHIFTED := 0;
  5875.  
  5876.  
  5877.    MAE_LONG_FLOAT_EPSILON := (TWO**(-(TARGET_LONG_NUM_BITS-1)));
  5878.    MAE_LONG_FLOAT_LARGE := ((TWO**(MAX_EXPONENT_VALUE-1)) -
  5879.                (TWO**(MAX_EXPONENT_VALUE-(TARGET_LONG_NUM_BITS))))
  5880.                *TWO;
  5881.    MAE_LONG_FLOAT_SMALL := (TWO**(MIN_EXPONENT_VALUE-1));
  5882.    MAE_LONG_FLOAT_LAST := MAE_LONG_FLOAT_LARGE;
  5883.    MAE_LONG_FLOAT_FIRST := -MAE_LONG_FLOAT_LARGE;
  5884.  
  5885.  
  5886. end MAE_LONG_FLOAT;
  5887. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  5888. --mae.txt
  5889. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  5890. -------------------------------------------------------------------------------
  5891. --                                                                           --
  5892. --             Emulation of Machine Arithmetic - a WIS Ada Tool              --
  5893. --                                                                           --
  5894. --                         Ada Technology Group                              --
  5895. --                         SYSCON Corporation                                --
  5896. --                         3990 Sherman Street                               --
  5897. --                         San Diego, CA. 92110                              --
  5898. --                                                                           --
  5899. --                        John Long & John Reddan                            --
  5900. --                                                                           --
  5901. -------------------------------------------------------------------------------
  5902.  
  5903. with MAE_BASIC_OPERATIONS;
  5904. with MAE_INTEGER;
  5905. with MAE_SHORT_FLOAT;
  5906. with MAE_LONG_FLOAT;
  5907.  
  5908. package MACHINE_ARITHMETIC_EMULATION is
  5909. --------------------------------------------------------------------
  5910. --  The purpose of this package is to emulate target machine
  5911. --  arithmetic on host machines with 16-bit or larger words.
  5912. --  This package will export support for target integer, real, 
  5913. --  and double precision real numbers.  
  5914. --
  5915. --  The emulation packages are currently configured to 
  5916. --  support Honeywell 36-bit arithmetic.
  5917. --
  5918. --  The ranges for the current configuration are as follows:
  5919. --
  5920. --     TARGET_INTEGER
  5921. --        range of -2**35 to 2**35-1
  5922. --     TARGET_SHORT_FLOAT
  5923. --        approximate range of 10**-38 to 10**38 and 0
  5924. --        mantissa => 27 bit binary fraction
  5925. --        exponent => -128 to 127
  5926. --     TARGET_LONG_FLOAT
  5927. --        approximate range of 10**-38 to 10**38 and 0
  5928. --        mantissa => 63 bit binary fraction
  5929. --        exponent => -128 to 127
  5930. --
  5931. --  Any errors which occur during use of the arithmetic and
  5932. --  boolean functions defined below will result in the
  5933. --  raising of the exception "MAE_NUMERIC_ERROR".  The 
  5934. --  exception declared in this package is a rename of
  5935. --  the predefined exception NUMERIC_ERROR.  This can be
  5936. --  changed for programs needing to handle arithmetic
  5937. --  exceptions generated by the emulation packages separately.
  5938. --
  5939.    
  5940.  
  5941. --------------------------------------------------------------------
  5942. -- Parameters within MAE_BASIC_OPERATIONS that need to be available
  5943. -- to the user of the Emulation of Machine Arithmetic package:
  5944. --
  5945.    subtype NUMBER_BASE is MAE_BASIC_OPERATIONS.NUMBER_BASE;
  5946.    DEFAULT_BASE : NUMBER_BASE renames MAE_BASIC_OPERATIONS.DEFAULT_BASE;
  5947.  
  5948.    subtype FIELD is MAE_BASIC_OPERATIONS.FIELD;
  5949.    TARGET_SHORT_DEFAULT_AFT : FIELD 
  5950.                  renames MAE_BASIC_OPERATIONS.SHORT_DEFAULT_AFT;
  5951.    TARGET_LONG_DEFAULT_AFT : FIELD 
  5952.                  renames MAE_BASIC_OPERATIONS.LONG_DEFAULT_AFT;
  5953.    TARGET_SHORT_DEFAULT_EXP : FIELD 
  5954.                  renames MAE_BASIC_OPERATIONS.SHORT_DEFAULT_EXP;
  5955.    TARGET_LONG_DEFAULT_EXP : FIELD 
  5956.                  renames MAE_BASIC_OPERATIONS.LONG_DEFAULT_EXP;
  5957.  
  5958.    --
  5959.    -- predefined attributes for the emulated types
  5960.    --
  5961.       TARGET_SHORT_FLOAT_DIGITS : INTEGER 
  5962.                  renames MAE_BASIC_OPERATIONS.SHORT_FLOAT_DIGITS; 
  5963.       TARGET_LONG_FLOAT_DIGITS : INTEGER 
  5964.                  renames MAE_BASIC_OPERATIONS.LONG_FLOAT_DIGITS; 
  5965.  
  5966.       TARGET_SHORT_FLOAT_EMAX : INTEGER 
  5967.                  renames MAE_BASIC_OPERATIONS.SHORT_FLOAT_EMAX;
  5968.       TARGET_LONG_FLOAT_EMAX : INTEGER
  5969.                  renames MAE_BASIC_OPERATIONS.LONG_FLOAT_EMAX;
  5970.  
  5971.       TARGET_SHORT_FLOAT_MACHINE_EMAX : INTEGER 
  5972.                  renames MAE_BASIC_OPERATIONS.SHORT_FLOAT_MACHINE_EMAX;
  5973.       TARGET_LONG_FLOAT_MACHINE_EMAX : INTEGER 
  5974.                  renames MAE_BASIC_OPERATIONS.LONG_FLOAT_MACHINE_EMAX;
  5975.  
  5976.       TARGET_SHORT_FLOAT_MACHINE_EMIN : INTEGER 
  5977.                  renames MAE_BASIC_OPERATIONS.SHORT_FLOAT_MACHINE_EMIN;
  5978.       TARGET_LONG_FLOAT_MACHINE_EMIN : INTEGER 
  5979.                  renames MAE_BASIC_OPERATIONS.LONG_FLOAT_MACHINE_EMIN;
  5980.  
  5981.       TARGET_SHORT_FLOAT_MACHINE_MANTISSA : INTEGER 
  5982.                  renames MAE_BASIC_OPERATIONS.SHORT_FLOAT_MACHINE_MANTISSA;
  5983.       TARGET_LONG_FLOAT_MACHINE_MANTISSA : INTEGER
  5984.                  renames MAE_BASIC_OPERATIONS.LONG_FLOAT_MACHINE_MANTISSA;
  5985.  
  5986.       TARGET_SHORT_FLOAT_MACHINE_OVERFLOWS : BOOLEAN 
  5987.                  renames MAE_BASIC_OPERATIONS.SHORT_FLOAT_MACHINE_OVERFLOWS;
  5988.       TARGET_LONG_FLOAT_MACHINE_OVERFLOWS : BOOLEAN
  5989.                  renames MAE_BASIC_OPERATIONS.LONG_FLOAT_MACHINE_OVERFLOWS;
  5990.  
  5991.       TARGET_SHORT_FLOAT_MACHINE_RADIX : INTEGER
  5992.                  renames MAE_BASIC_OPERATIONS.SHORT_FLOAT_MACHINE_RADIX;
  5993.       TARGET_LONG_FLOAT_MACHINE_RADIX : INTEGER
  5994.                  renames MAE_BASIC_OPERATIONS.LONG_FLOAT_MACHINE_RADIX;
  5995.  
  5996.       TARGET_SHORT_FLOAT_MACHINE_ROUNDS : BOOLEAN
  5997.                  renames MAE_BASIC_OPERATIONS.SHORT_FLOAT_MACHINE_ROUNDS;
  5998.       TARGET_LONG_FLOAT_MACHINE_ROUNDS : BOOLEAN
  5999.                  renames MAE_BASIC_OPERATIONS.LONG_FLOAT_MACHINE_ROUNDS;
  6000.  
  6001.       TARGET_SHORT_FLOAT_SAFE_EMAX : INTEGER 
  6002.                  renames MAE_BASIC_OPERATIONS.SHORT_FLOAT_SAFE_EMAX;
  6003.       TARGET_LONG_FLOAT_SAFE_EMAX : INTEGER 
  6004.                  renames MAE_BASIC_OPERATIONS.LONG_FLOAT_SAFE_EMAX;
  6005.  
  6006. --------------------------------------------------------------------
  6007. -- Visible operations with TARGET_INTEGER
  6008. --
  6009. -- The follow declaration should be private
  6010.  
  6011.    subtype TARGET_INTEGER is MAE_INTEGER.MAE_INTEGER_TYPE;
  6012.  
  6013.    -- The defined operators for this type are as follows:
  6014.  
  6015.    function TARGET_INTEGER_FIRST return TARGET_INTEGER;
  6016.    function TARGET_INTEGER_LAST return TARGET_INTEGER;
  6017.  
  6018.    -- Predefined system function "=" and function "/="
  6019.    function "<"    (LEFT, RIGHT : TARGET_INTEGER) return BOOLEAN;
  6020.    function "<="   (LEFT, RIGHT : TARGET_INTEGER) return BOOLEAN;
  6021.    function ">"    (LEFT, RIGHT : TARGET_INTEGER) return BOOLEAN;
  6022.    function ">="   (LEFT, RIGHT : TARGET_INTEGER) return BOOLEAN;
  6023.  
  6024.    function "+"    (RIGHT : TARGET_INTEGER) return TARGET_INTEGER;
  6025.    function "-"    (RIGHT : TARGET_INTEGER) return TARGET_INTEGER;
  6026.    function "abs"  (RIGHT : TARGET_INTEGER) return TARGET_INTEGER;
  6027.  
  6028.    function "+"    (LEFT,RIGHT : TARGET_INTEGER) return TARGET_INTEGER;
  6029.    function "-"    (LEFT,RIGHT : TARGET_INTEGER) return TARGET_INTEGER;
  6030.    function "*"    (LEFT,RIGHT : TARGET_INTEGER) return TARGET_INTEGER;
  6031.    function "/"    (LEFT,RIGHT : TARGET_INTEGER) return TARGET_INTEGER;
  6032.    function "rem"  (LEFT,RIGHT : TARGET_INTEGER) return TARGET_INTEGER;
  6033.    function "mod"  (LEFT,RIGHT : TARGET_INTEGER) return TARGET_INTEGER;
  6034.  
  6035.    function "**"   (LEFT : TARGET_INTEGER; RIGHT : INTEGER)
  6036.                        return TARGET_INTEGER;
  6037.  
  6038.    function TARGET_INTEGER_VALUE (STRING_PIC : STRING) 
  6039.                        return TARGET_INTEGER;
  6040.    function TARGET_INTEGER_IMAGE (STORE_PIC : TARGET_INTEGER) 
  6041.                        return STRING;
  6042.  
  6043.    procedure GET (FROM : in STRING;
  6044.                   ITEM : out TARGET_INTEGER;
  6045.                   LAST : out POSITIVE);
  6046.  
  6047.    procedure PUT (TO : out STRING;
  6048.                   ITEM : in TARGET_INTEGER;
  6049.                   BASE : in NUMBER_BASE := DEFAULT_BASE);
  6050.  
  6051. --------------------------------------------------------------------
  6052. -- Visible operations with TARGET_SHORT_FLOAT
  6053. --
  6054. -- The following declaration should be private
  6055.  
  6056.    subtype TARGET_SHORT_FLOAT is MAE_SHORT_FLOAT.MAE_SHORT_FLOAT_TYPE;
  6057.  
  6058.    -- The defined operators for this type are as follows:
  6059.  
  6060.  
  6061.    function TARGET_SHORT_FLOAT_EPSILON return TARGET_SHORT_FLOAT;
  6062.    function TARGET_SHORT_FLOAT_LARGE return TARGET_SHORT_FLOAT;
  6063.    function TARGET_SHORT_FLOAT_SMALL return TARGET_SHORT_FLOAT;
  6064.    function TARGET_SHORT_FLOAT_LAST return TARGET_SHORT_FLOAT;
  6065.    function TARGET_SHORT_FLOAT_FIRST return TARGET_SHORT_FLOAT;
  6066.  
  6067.    -- Predefined system function "=" and function "/="
  6068.    function "<"    (LEFT, RIGHT : TARGET_SHORT_FLOAT) return BOOLEAN;
  6069.    function "<="   (LEFT, RIGHT : TARGET_SHORT_FLOAT) return BOOLEAN;
  6070.    function ">"    (LEFT, RIGHT : TARGET_SHORT_FLOAT) return BOOLEAN;
  6071.    function ">="   (LEFT, RIGHT : TARGET_SHORT_FLOAT) return BOOLEAN;
  6072.  
  6073.    function "+"    (RIGHT : TARGET_SHORT_FLOAT) return TARGET_SHORT_FLOAT;
  6074.    function "-"    (RIGHT : TARGET_SHORT_FLOAT) return TARGET_SHORT_FLOAT;
  6075.    function "abs"  (RIGHT : TARGET_SHORT_FLOAT) return TARGET_SHORT_FLOAT;
  6076.  
  6077.    function "+"    (LEFT,RIGHT : TARGET_SHORT_FLOAT) return TARGET_SHORT_FLOAT;
  6078.    function "-"    (LEFT,RIGHT : TARGET_SHORT_FLOAT) return TARGET_SHORT_FLOAT;
  6079.    function "*"    (LEFT,RIGHT : TARGET_SHORT_FLOAT) return TARGET_SHORT_FLOAT;
  6080.    function "/"    (LEFT,RIGHT : TARGET_SHORT_FLOAT) return TARGET_SHORT_FLOAT;
  6081.  
  6082.    function "**"   (LEFT : TARGET_SHORT_FLOAT; RIGHT : INTEGER) 
  6083.                        return TARGET_SHORT_FLOAT;
  6084.  
  6085.    procedure GET (FROM : in STRING;
  6086.                   ITEM : out TARGET_SHORT_FLOAT;
  6087.                   LAST : out POSITIVE);
  6088.  
  6089.    procedure PUT (TO : out STRING;
  6090.                   ITEM : in TARGET_SHORT_FLOAT;
  6091.                   AFT : in FIELD := TARGET_SHORT_DEFAULT_AFT;
  6092.                   EXP : in FIELD := TARGET_SHORT_DEFAULT_EXP);
  6093.  
  6094. --------------------------------------------------------------------
  6095. -- Visible operations with TARGET_LONG_FLOAT
  6096. --
  6097. -- The following declaration should be private
  6098.  
  6099.    subtype TARGET_LONG_FLOAT is MAE_LONG_FLOAT.MAE_LONG_FLOAT_TYPE;
  6100.  
  6101.    -- The defined operators for this type are as follows:
  6102.  
  6103.    function TARGET_LONG_FLOAT_EPSILON return TARGET_LONG_FLOAT;
  6104.    function TARGET_LONG_FLOAT_LARGE return TARGET_LONG_FLOAT;
  6105.    function TARGET_LONG_FLOAT_SMALL return TARGET_LONG_FLOAT;
  6106.    function TARGET_LONG_FLOAT_LAST return TARGET_LONG_FLOAT;
  6107.    function TARGET_LONG_FLOAT_FIRST return TARGET_LONG_FLOAT;
  6108.  
  6109.    -- Predefined system function "=" and function "/="
  6110.    function "<"    (LEFT, RIGHT : TARGET_LONG_FLOAT) return BOOLEAN;
  6111.    function "<="   (LEFT, RIGHT : TARGET_LONG_FLOAT) return BOOLEAN;
  6112.    function ">"    (LEFT, RIGHT : TARGET_LONG_FLOAT) return BOOLEAN;
  6113.    function ">="   (LEFT, RIGHT : TARGET_LONG_FLOAT) return BOOLEAN;
  6114.  
  6115.    function "+"    (RIGHT : TARGET_LONG_FLOAT) return TARGET_LONG_FLOAT;
  6116.    function "-"    (RIGHT : TARGET_LONG_FLOAT) return TARGET_LONG_FLOAT;
  6117.    function "abs"  (RIGHT : TARGET_LONG_FLOAT) return TARGET_LONG_FLOAT;
  6118.  
  6119.    function "+"    (LEFT,RIGHT : TARGET_LONG_FLOAT) return TARGET_LONG_FLOAT;
  6120.    function "-"    (LEFT,RIGHT : TARGET_LONG_FLOAT) return TARGET_LONG_FLOAT;
  6121.    function "*"    (LEFT,RIGHT : TARGET_LONG_FLOAT) return TARGET_LONG_FLOAT;
  6122.    function "/"    (LEFT,RIGHT : TARGET_LONG_FLOAT) return TARGET_LONG_FLOAT;
  6123.  
  6124.    function "**"   (LEFT : TARGET_LONG_FLOAT; RIGHT : INTEGER) 
  6125.                        return TARGET_LONG_FLOAT;
  6126.  
  6127.    procedure GET (FROM : in STRING;
  6128.                   ITEM : out TARGET_LONG_FLOAT;
  6129.                   LAST : out POSITIVE);
  6130.  
  6131.    procedure PUT (TO : out STRING;
  6132.                   ITEM : in TARGET_LONG_FLOAT;
  6133.                   AFT : in FIELD := TARGET_LONG_DEFAULT_AFT;
  6134.                   EXP : in FIELD := TARGET_LONG_DEFAULT_EXP);
  6135.  
  6136. --------------------------------------------------------------------
  6137. -- private
  6138.  
  6139.    -- Note : Derived types are not supported under 
  6140.    -- Telesoft version 1.5
  6141.  
  6142.    -- The types are private to prevent direct manipulation of
  6143.    -- the components of the numbers.  The exported types
  6144.    -- are declarations of the appropriate types from the
  6145.    -- respective package.
  6146.  
  6147.       -- type TARGET_INTEGER is new MAE_INTEGER_TYPE;
  6148.  
  6149.       -- type TARGET_SHORT_FLOAT is new MAE_SHORT_FLOAT_TYPE;
  6150.  
  6151.       -- type TARGET_LONG_FLOAT is new MAE_SHORT_LONG_TYPE;
  6152.  
  6153.  
  6154. --------------------------------------------------------------------
  6155.  
  6156. end MACHINE_ARITHMETIC_EMULATION;
  6157.  
  6158. --------------------------------------------------------------------
  6159. --------------------------------------------------------------------
  6160.  
  6161. with MAE_BASIC_OPERATIONS;
  6162. with MAE_INTEGER;
  6163. with MAE_SHORT_FLOAT;
  6164. with MAE_LONG_FLOAT;
  6165.  
  6166. package body MACHINE_ARITHMETIC_EMULATION is
  6167. --------------------------------------------------------------------
  6168.  
  6169. -- Visible operations with TARGET_INTEGER
  6170. --
  6171.  
  6172.    function TARGET_INTEGER_FIRST return TARGET_INTEGER is
  6173.    begin
  6174.       return MAE_INTEGER.TARGET_INTEGER_FIRST;
  6175.    end;
  6176.  
  6177.    function TARGET_INTEGER_LAST return TARGET_INTEGER is
  6178.    begin
  6179.       return MAE_INTEGER.TARGET_INTEGER_LAST;
  6180.    end;
  6181.  
  6182.    -- Predefined system function "=" and function "/="
  6183.  
  6184.    function "<"    (LEFT, RIGHT : TARGET_INTEGER) return BOOLEAN is
  6185.    begin
  6186.       return MAE_INTEGER."<"(LEFT, RIGHT);
  6187.    end;
  6188.  
  6189.    function "<="   (LEFT, RIGHT : TARGET_INTEGER) return BOOLEAN is
  6190.    begin
  6191.       return MAE_INTEGER."<="(LEFT, RIGHT);
  6192.    end;
  6193.  
  6194.    function ">"    (LEFT, RIGHT : TARGET_INTEGER) return BOOLEAN is
  6195.    begin
  6196.       return MAE_INTEGER.">"(LEFT, RIGHT);
  6197.    end;
  6198.  
  6199.    function ">="   (LEFT, RIGHT : TARGET_INTEGER) return BOOLEAN is
  6200.    begin
  6201.       return MAE_INTEGER.">="(LEFT, RIGHT);
  6202.    end;
  6203.  
  6204.  
  6205.    function "+"    (RIGHT : TARGET_INTEGER) return TARGET_INTEGER is
  6206.    begin
  6207.       return MAE_INTEGER."+"(RIGHT);
  6208.    end;
  6209.  
  6210.    function "-"    (RIGHT : TARGET_INTEGER) return TARGET_INTEGER is
  6211.    begin
  6212.       return MAE_INTEGER."-"(RIGHT);
  6213.    end;
  6214.  
  6215.    function "abs"  (RIGHT : TARGET_INTEGER) return TARGET_INTEGER is
  6216.    begin
  6217.       return MAE_INTEGER."abs"(RIGHT);
  6218.    end;
  6219.  
  6220.  
  6221.    function "+"    (LEFT,RIGHT : TARGET_INTEGER) return TARGET_INTEGER is
  6222.    begin
  6223.       return MAE_INTEGER."+"(LEFT, RIGHT);
  6224.    end;
  6225.  
  6226.    function "-"    (LEFT,RIGHT : TARGET_INTEGER) return TARGET_INTEGER is
  6227.    begin
  6228.       return MAE_INTEGER."-"(LEFT, RIGHT);
  6229.    end;
  6230.  
  6231.    function "*"    (LEFT,RIGHT : TARGET_INTEGER) return TARGET_INTEGER is
  6232.    begin
  6233.       return MAE_INTEGER."*"(LEFT, RIGHT);
  6234.    end;
  6235.  
  6236.    function "/"    (LEFT,RIGHT : TARGET_INTEGER) return TARGET_INTEGER is
  6237.    begin
  6238.       return MAE_INTEGER."/"(LEFT, RIGHT);
  6239.    end;
  6240.  
  6241.    function "rem"  (LEFT,RIGHT : TARGET_INTEGER) return TARGET_INTEGER is
  6242.    begin
  6243.       return MAE_INTEGER."rem"(LEFT, RIGHT);
  6244.    end;
  6245.  
  6246.    function "mod"  (LEFT,RIGHT : TARGET_INTEGER) return TARGET_INTEGER is
  6247.    begin
  6248.       return MAE_INTEGER."mod"(LEFT, RIGHT);
  6249.    end;
  6250.  
  6251.  
  6252.    function "**"   (LEFT : TARGET_INTEGER; RIGHT : INTEGER) 
  6253.                        return TARGET_INTEGER is
  6254.    begin
  6255.       return MAE_INTEGER."**"(LEFT, RIGHT);
  6256.    end;
  6257.  
  6258.  
  6259.    function TARGET_INTEGER_VALUE (STRING_PIC : STRING) 
  6260.                                      return TARGET_INTEGER is
  6261.    begin
  6262.       return MAE_INTEGER.MAE_INTEGER_TYPE_VALUE(STRING_PIC);
  6263.    end;
  6264.  
  6265.    function TARGET_INTEGER_IMAGE (STORE_PIC : TARGET_INTEGER) 
  6266.                                      return STRING is
  6267.    begin
  6268.       return MAE_INTEGER.MAE_INTEGER_TYPE_IMAGE(STORE_PIC);
  6269.    end;
  6270.  
  6271.    procedure GET (FROM : in STRING;
  6272.                   ITEM : out TARGET_INTEGER;
  6273.                   LAST : out POSITIVE) is
  6274.    begin
  6275.       MAE_INTEGER.GET(FROM, ITEM, LAST);
  6276.    end;
  6277.  
  6278.    procedure PUT (TO : out STRING;
  6279.                   ITEM : in TARGET_INTEGER;
  6280.                   BASE : in NUMBER_BASE := DEFAULT_BASE) is
  6281.    begin
  6282.       MAE_INTEGER.PUT(TO, ITEM, BASE);
  6283.    end;
  6284.  
  6285. --------------------------------------------------------------------
  6286. -- Visible operations with TARGET_SHORT_FLOAT
  6287. --
  6288.  
  6289.    function TARGET_SHORT_FLOAT_EPSILON return TARGET_SHORT_FLOAT is
  6290.    begin
  6291.       return MAE_SHORT_FLOAT.TARGET_SHORT_FLOAT_EPSILON;
  6292.    end; 
  6293.  
  6294.    function TARGET_SHORT_FLOAT_LARGE return TARGET_SHORT_FLOAT is
  6295.    begin
  6296.       return MAE_SHORT_FLOAT.TARGET_SHORT_FLOAT_LARGE;
  6297.    end;
  6298.  
  6299.    function TARGET_SHORT_FLOAT_SMALL return TARGET_SHORT_FLOAT is
  6300.    begin
  6301.       return MAE_SHORT_FLOAT.TARGET_SHORT_FLOAT_SMALL;
  6302.    end;
  6303.  
  6304.    function TARGET_SHORT_FLOAT_LAST return TARGET_SHORT_FLOAT is
  6305.    begin
  6306.       return MAE_SHORT_FLOAT.TARGET_SHORT_FLOAT_LAST;
  6307.    end;
  6308.  
  6309.    function TARGET_SHORT_FLOAT_FIRST return TARGET_SHORT_FLOAT is
  6310.    begin
  6311.       return MAE_SHORT_FLOAT.TARGET_SHORT_FLOAT_FIRST;
  6312.    end;
  6313.  
  6314.    -- Predefined system function "=" and function "/="
  6315.  
  6316.    function "<"    (LEFT, RIGHT : TARGET_SHORT_FLOAT) return BOOLEAN is
  6317.    begin
  6318.       return MAE_SHORT_FLOAT."<"(LEFT, RIGHT);
  6319.    end;
  6320.  
  6321.    function "<="   (LEFT, RIGHT : TARGET_SHORT_FLOAT) return BOOLEAN is
  6322.    begin
  6323.       return MAE_SHORT_FLOAT."<="(LEFT, RIGHT);
  6324.    end;
  6325.  
  6326.    function ">"    (LEFT, RIGHT : TARGET_SHORT_FLOAT) return BOOLEAN is
  6327.    begin
  6328.       return MAE_SHORT_FLOAT.">"(LEFT, RIGHT);
  6329.    end;
  6330.  
  6331.    function ">="   (LEFT, RIGHT : TARGET_SHORT_FLOAT) return BOOLEAN is
  6332.    begin
  6333.       return MAE_SHORT_FLOAT.">="(LEFT, RIGHT);
  6334.    end;
  6335.  
  6336.  
  6337.    function "+"    (RIGHT : TARGET_SHORT_FLOAT) return TARGET_SHORT_FLOAT is
  6338.    begin
  6339.       return MAE_SHORT_FLOAT."+"(RIGHT);
  6340.    end;
  6341.  
  6342.    function "-"    (RIGHT : TARGET_SHORT_FLOAT) return TARGET_SHORT_FLOAT is
  6343.    begin
  6344.       return MAE_SHORT_FLOAT."-"(RIGHT);
  6345.    end;
  6346.  
  6347.    function "abs"  (RIGHT : TARGET_SHORT_FLOAT) return TARGET_SHORT_FLOAT is
  6348.    begin
  6349.       return MAE_SHORT_FLOAT."abs"(RIGHT);
  6350.    end;
  6351.  
  6352.  
  6353.    function "+"    (LEFT,RIGHT : TARGET_SHORT_FLOAT) 
  6354.                        return TARGET_SHORT_FLOAT is
  6355.    begin
  6356.       return MAE_SHORT_FLOAT."+"(LEFT, RIGHT);
  6357.    end;
  6358.  
  6359.    function "-"    (LEFT,RIGHT : TARGET_SHORT_FLOAT) 
  6360.                        return TARGET_SHORT_FLOAT is
  6361.    begin
  6362.       return MAE_SHORT_FLOAT."-"(LEFT, RIGHT);
  6363.    end;
  6364.  
  6365.    function "*"    (LEFT,RIGHT : TARGET_SHORT_FLOAT) 
  6366.                        return TARGET_SHORT_FLOAT is
  6367.    begin
  6368.       return MAE_SHORT_FLOAT."*"(LEFT, RIGHT);
  6369.    end;
  6370.  
  6371.    function "/"    (LEFT,RIGHT : TARGET_SHORT_FLOAT) 
  6372.                        return TARGET_SHORT_FLOAT is
  6373.    begin
  6374.       return MAE_SHORT_FLOAT."/"(LEFT, RIGHT);
  6375.    end;
  6376.  
  6377.  
  6378.    function "**"   (LEFT : TARGET_SHORT_FLOAT; RIGHT : INTEGER) 
  6379.                        return TARGET_SHORT_FLOAT is
  6380.    begin
  6381.       return MAE_SHORT_FLOAT."**"(LEFT, RIGHT);
  6382.    end;
  6383.  
  6384.  
  6385.    procedure GET (FROM : in STRING;
  6386.                   ITEM : out TARGET_SHORT_FLOAT;
  6387.                   LAST : out POSITIVE) is
  6388.    begin
  6389.       MAE_SHORT_FLOAT.GET(FROM, ITEM, LAST);
  6390.    end;
  6391.  
  6392.    procedure PUT (TO : out STRING;
  6393.                   ITEM : in TARGET_SHORT_FLOAT;
  6394.                   AFT : in FIELD := TARGET_SHORT_DEFAULT_AFT;
  6395.                   EXP : in FIELD := TARGET_SHORT_DEFAULT_EXP) is
  6396.    begin
  6397.       MAE_SHORT_FLOAT.PUT(TO, ITEM, AFT, EXP);
  6398.    end;
  6399.  
  6400. --------------------------------------------------------------------
  6401. -- Visible operations with TARGET_LONG_FLOAT
  6402. --
  6403.  
  6404.    function TARGET_LONG_FLOAT_EPSILON return TARGET_LONG_FLOAT is
  6405.    begin
  6406.       return MAE_LONG_FLOAT.TARGET_LONG_FLOAT_EPSILON;
  6407.    end; 
  6408.  
  6409.    function TARGET_LONG_FLOAT_LARGE return TARGET_LONG_FLOAT is
  6410.    begin
  6411.       return MAE_LONG_FLOAT.TARGET_LONG_FLOAT_LARGE;
  6412.    end;
  6413.  
  6414.    function TARGET_LONG_FLOAT_SMALL return TARGET_LONG_FLOAT is
  6415.    begin
  6416.       return MAE_LONG_FLOAT.TARGET_LONG_FLOAT_SMALL;
  6417.    end;
  6418.  
  6419.    function TARGET_LONG_FLOAT_LAST return TARGET_LONG_FLOAT is
  6420.    begin
  6421.       return MAE_LONG_FLOAT.TARGET_LONG_FLOAT_LAST;
  6422.    end;
  6423.  
  6424.    function TARGET_LONG_FLOAT_FIRST return TARGET_LONG_FLOAT is
  6425.    begin
  6426.       return MAE_LONG_FLOAT.TARGET_LONG_FLOAT_FIRST;
  6427.    end;
  6428.  
  6429.    -- Predefined system function "=" and function "/="
  6430.  
  6431.    function "<"    (LEFT, RIGHT : TARGET_LONG_FLOAT) return BOOLEAN is
  6432.    begin
  6433.       return MAE_LONG_FLOAT."<"(LEFT, RIGHT);
  6434.    end;
  6435.  
  6436.    function "<="   (LEFT, RIGHT : TARGET_LONG_FLOAT) return BOOLEAN is
  6437.    begin
  6438.       return MAE_LONG_FLOAT."<="(LEFT, RIGHT);
  6439.    end;
  6440.  
  6441.    function ">"    (LEFT, RIGHT : TARGET_LONG_FLOAT) return BOOLEAN is
  6442.    begin
  6443.       return MAE_LONG_FLOAT.">"(LEFT, RIGHT);
  6444.    end;
  6445.  
  6446.    function ">="   (LEFT, RIGHT : TARGET_LONG_FLOAT) return BOOLEAN is
  6447.    begin
  6448.       return MAE_LONG_FLOAT.">="(LEFT, RIGHT);
  6449.    end;
  6450.  
  6451.  
  6452.    function "+"    (RIGHT : TARGET_LONG_FLOAT) return TARGET_LONG_FLOAT is
  6453.    begin
  6454.       return MAE_LONG_FLOAT."+"(RIGHT);
  6455.    end;
  6456.  
  6457.    function "-"    (RIGHT : TARGET_LONG_FLOAT) return TARGET_LONG_FLOAT is
  6458.    begin
  6459.       return MAE_LONG_FLOAT."-"(RIGHT);
  6460.    end;
  6461.  
  6462.    function "abs"  (RIGHT : TARGET_LONG_FLOAT) return TARGET_LONG_FLOAT is
  6463.    begin
  6464.       return MAE_LONG_FLOAT."abs"(RIGHT);
  6465.    end;
  6466.  
  6467.  
  6468.    function "+"    (LEFT,RIGHT : TARGET_LONG_FLOAT) return 
  6469.                        TARGET_LONG_FLOAT is
  6470.    begin
  6471.       return MAE_LONG_FLOAT."+"(LEFT, RIGHT);
  6472.    end;
  6473.  
  6474.    function "-"    (LEFT,RIGHT : TARGET_LONG_FLOAT) 
  6475.                        return TARGET_LONG_FLOAT is
  6476.    begin
  6477.       return MAE_LONG_FLOAT."-"(LEFT, RIGHT);
  6478.    end;
  6479.  
  6480.    function "*"    (LEFT,RIGHT : TARGET_LONG_FLOAT) 
  6481.                        return TARGET_LONG_FLOAT is
  6482.    begin
  6483.       return MAE_LONG_FLOAT."*"(LEFT, RIGHT);
  6484.    end;
  6485.  
  6486.    function "/"    (LEFT,RIGHT : TARGET_LONG_FLOAT) 
  6487.                        return TARGET_LONG_FLOAT is
  6488.    begin
  6489.       return MAE_LONG_FLOAT."/"(LEFT, RIGHT);
  6490.    end;
  6491.  
  6492.  
  6493.    function "**"   (LEFT : TARGET_LONG_FLOAT; RIGHT : INTEGER) 
  6494.                        return TARGET_LONG_FLOAT is
  6495.    begin
  6496.       return MAE_LONG_FLOAT."**"(LEFT, RIGHT);
  6497.    end;
  6498.  
  6499.  
  6500.    procedure GET (FROM : in STRING;
  6501.                   ITEM : out TARGET_LONG_FLOAT;
  6502.                   LAST : out POSITIVE) is
  6503.    begin
  6504.       MAE_LONG_FLOAT.GET(FROM, ITEM, LAST);
  6505.    end;
  6506.  
  6507.    procedure PUT (TO : out STRING;
  6508.                   ITEM : in TARGET_LONG_FLOAT;
  6509.                   AFT : in FIELD := TARGET_LONG_DEFAULT_AFT;
  6510.                   EXP : in FIELD := TARGET_LONG_DEFAULT_EXP) is
  6511.    begin
  6512.       MAE_LONG_FLOAT.PUT(TO, ITEM, AFT, EXP);
  6513.    end;
  6514.  
  6515. --------------------------------------------------------------------
  6516. -- The body of the package
  6517. --
  6518. begin
  6519.    null;
  6520. end MACHINE_ARITHMETIC_EMULATION;
  6521.  
  6522.