home *** CD-ROM | disk | FTP | other *** search
/ Programmer's ROM - The Computer Language Library / programmersrom.iso / ada / simu / qsap.src < prev    next >
Encoding:
Text File  |  1988-05-03  |  328.4 KB  |  10,280 lines

  1. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  2. --qsap1.ada
  3. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  4. --===========================================================
  5. -- Source:     Division Software Technology and Support
  6. --             Western Development Laboratories
  7. --             Ford Aerospace & Communications Corporation
  8. --             ATTN:  Ada Tools Group
  9. -- Date   : June 1985
  10. --===========================================================
  11.  
  12.  
  13. package Network_Parameters is
  14. --===========================================================
  15. --     Contains QSAP Network Parameters Likely to be altered 
  16. --     during system installation. 
  17. --============================================================ 
  18.  
  19.  
  20.        --==========Setup Parameters ========================
  21.  
  22.     Max_Index_Size    : constant Natural := 100;
  23.                        --  Max RealMatrix and RealVector index sizes.
  24.                        --        Also sets Max Number of Nodes.
  25.                        --        Also sets Max Number of Jobs.
  26.  
  27.     Max_Float_Digits  : constant := 6;
  28.  
  29.     Max_Moment_Order  : constant := 5;
  30.  
  31.     Max_Coxian_Stages : constant := 20;
  32.  
  33. end Network_Parameters;
  34. package MIN_MAX_PAK is
  35.  
  36.    function MIN (X: INTEGER; Y: INTEGER) return INTEGER;
  37.    function MAX (X: INTEGER; Y: INTEGER) return INTEGER;
  38.  
  39. end MIN_MAX_PAK;
  40.  
  41. package body MIN_MAX_PAK is
  42.  
  43. -- ************************************************************
  44.  
  45. function MIN (X: INTEGER; Y: INTEGER) return INTEGER is
  46.  
  47. begin
  48.  
  49.    if X <= Y then
  50.       return X;
  51.    else
  52.       return Y;
  53.    end if;
  54.  
  55. end MIN;
  56.  
  57. -- ************************************************************
  58.  
  59. function MAX (X: INTEGER; Y: INTEGER) return INTEGER is
  60.  
  61. begin
  62.  
  63.    if X >= Y then
  64.       return X;
  65.    else
  66.       return Y;
  67.    end if;
  68.  
  69. end MAX;
  70.  
  71. end MIN_MAX_PAK;
  72. with TEXT_IO; use TEXT_IO;
  73. with MIN_MAX_PAK; use MIN_MAX_PAK;
  74. generic
  75.    type REAL is digits <>;
  76. package GEN_TEXT_HANDLER is
  77.  
  78.     MAX_TEXT_LENGTH: constant INTEGER := 256; -- max length of any text
  79.     SUBSCRIPT_RANGE: exception;
  80.  
  81.     subtype INDX  is INTEGER range 0 .. MAX_TEXT_LENGTH;
  82.      --==============================================
  83.     type    TEXT (MAX_LENGTH: INDX := 0) is private;
  84.      --==============================================
  85.  
  86.     function STRNG     (FROM: TEXT; LENG: NATURAL:=0)    return STRING;
  87.     function LENGTH    (FROM: TEXT)                      return INTEGER;
  88.     function EQUAL     (LEFT: TEXT; RIGHT: TEXT)         return BOOLEAN;
  89.     function "<"       (LEFT: TEXT; RIGHT: TEXT)         return BOOLEAN;
  90.     function "<="      (LEFT: TEXT; RIGHT: TEXT)         return BOOLEAN;
  91.     function ">"       (LEFT: TEXT; RIGHT: TEXT)         return BOOLEAN;
  92.     function ">="      (LEFT: TEXT; RIGHT: TEXT)         return BOOLEAN;
  93.  
  94.     function TXT       (FROM: STRING)                    return TEXT;
  95.     function TXT       (FROM: CHARACTER)                 return TEXT;
  96.     function TXT       (FROM: INTEGER; LENG: INTEGER)    return TEXT;
  97.     function TXT       (FROM: INTEGER)                   return TEXT;
  98.     function TXT       (FROM: REAL)                      return TEXT;
  99.  
  100.     function "&"       (LEFT: TEXT;   RIGHT: TEXT)       return TEXT;
  101.     function SUBSTR    (FROM: TEXT;   START: INTEGER;
  102.                                       LENG:  INTEGER)    return TEXT;
  103.     function SUBSTR    (FROM: TEXT;   START: INTEGER)    return TEXT;
  104.     function INDEX     (FROM: TEXT;   SEEK:  TEXT)       return INTEGER;
  105.     function BEFORE    (FROM: TEXT;   SEEK:  TEXT)       return TEXT;
  106.     function AFTER     (FROM: TEXT;   SEEK:  TEXT)       return TEXT;
  107.     function TRANSLATE (FROM: TEXT;   CHANGE:TEXT;
  108.                                       SEEK:  TEXT)       return TEXT;
  109.     function UP_CASE   (FROM:TEXT)                       return TEXT;
  110.     function LOW_CASE  (FROM:TEXT)                       return TEXT;
  111.     function REMOVE_LEADING         (FROM: TEXT;
  112.                                      REMOVE: STRING)     return TEXT;
  113.     function REMOVE_TRAILING        (FROM: TEXT;
  114.                                      REMOVE: STRING)     return TEXT;
  115.     function DUPLICATE              (REPEAT: STRING;
  116.                                      TIMES : INTEGER)    return TEXT;
  117.  
  118.     procedure SET(TO: in out STRING;  FROM: in TEXT);
  119.     procedure SET(TO: out INTEGER; FROM: in TEXT; NUMERIC: out BOOLEAN);
  120.     procedure SET(TO: out REAL;    FROM: in TEXT; NUMERIC: out BOOLEAN);
  121.     procedure SET(TO: out REAL;    FROM: in TEXT);
  122.  
  123. private
  124.  
  125.     type TEXT (MAX_LENGTH: INDX := 0) is
  126.     record
  127.         VALUE: STRING (1 .. MAX_LENGTH);
  128.     end record;
  129.  
  130. end GEN_TEXT_HANDLER;
  131. with TEXT_IO; use TEXT_IO;
  132.  
  133. package body GEN_TEXT_HANDLER is
  134.  
  135.  
  136.    package INT_IO is new INTEGER_IO(INTEGER); use INT_IO;
  137.    package FLT_IO is new FLOAT_IO(REAL);     use FLT_IO;
  138.  
  139. ------------------------------------------------------------------------
  140.  
  141.     function STRNG (FROM: TEXT; LENG: NATURAL:=0) return STRING is
  142.  
  143.        Blank: String (1 .. Leng-Length(From)) := (others => ' ');
  144.  
  145.     begin
  146.  
  147.        if    Leng = 0 then
  148.           return From.Value;
  149.        elsif Leng > Length(From) then
  150.           return From.Value & Blank;
  151.        else
  152.           return From.Value(1 .. Leng);
  153.        end if;
  154.  
  155.     end STRNG;
  156.  
  157. ------------------------------------------------------------------------
  158. ------------------------------------------------------------------------
  159.  
  160.     function LENGTH (FROM: TEXT)  return INTEGER is
  161.  
  162.     begin
  163.        return FROM.VALUE'LENGTH;
  164.     end LENGTH;
  165.  
  166. ------------------------------------------------------------------------
  167. ------------------------------------------------------------------------
  168.  
  169.     function EQUAL  (LEFT: TEXT; RIGHT: TEXT)  return BOOLEAN is
  170.  
  171.        NEW_LEFT:  STRING (1 .. RIGHT.VALUE'LENGTH);
  172.        NEW_RIGHT: STRING (1 .. LEFT.VALUE'LENGTH);
  173.  
  174.     begin
  175.        if    (LEFT.VALUE'LENGTH = RIGHT.VALUE'LENGTH) then
  176.           return  LEFT.VALUE = RIGHT.VALUE;
  177.        elsif (LEFT.VALUE'LENGTH < RIGHT.VALUE'LENGTH) then
  178.           SET    (NEW_LEFT, LEFT);
  179.           return  NEW_LEFT = RIGHT.VALUE;
  180.        else
  181.           SET    (NEW_RIGHT, RIGHT);
  182.           return  LEFT.VALUE = NEW_RIGHT;
  183.        end if;
  184.     end EQUAL;
  185.     function ">"    (LEFT: TEXT; RIGHT: TEXT)  return BOOLEAN is
  186.  
  187.        NEW_LEFT:  STRING (1 .. RIGHT.VALUE'LENGTH);
  188.        NEW_RIGHT: STRING (1 .. LEFT.VALUE'LENGTH);
  189.  
  190.     begin
  191.        if    (LEFT.VALUE'LENGTH = RIGHT.VALUE'LENGTH) then
  192.           return  LEFT.VALUE > RIGHT.VALUE;
  193.        elsif (LEFT.VALUE'LENGTH < RIGHT.VALUE'LENGTH) then
  194.           SET    (NEW_LEFT, LEFT);
  195.           return  NEW_LEFT > RIGHT.VALUE;
  196.        else
  197.           SET    (NEW_RIGHT, RIGHT);
  198.           return  LEFT.VALUE > NEW_RIGHT;
  199.        end if;
  200.     end ">";
  201.  
  202. ------------------------------------------------------------------------
  203. ------------------------------------------------------------------------
  204.  
  205.     function "<"    (LEFT: TEXT; RIGHT: TEXT)  return BOOLEAN is
  206.  
  207.        NEW_LEFT:  STRING (1 .. RIGHT.VALUE'LENGTH);
  208.        NEW_RIGHT: STRING (1 .. LEFT.VALUE'LENGTH);
  209.  
  210.     begin
  211.        if    (LEFT.VALUE'LENGTH = RIGHT.VALUE'LENGTH) then
  212.           return  LEFT.VALUE < RIGHT.VALUE;
  213.        elsif (LEFT.VALUE'LENGTH < RIGHT.VALUE'LENGTH) then
  214.           SET    (NEW_LEFT, LEFT);
  215.           return  NEW_LEFT < RIGHT.VALUE;
  216.        else
  217.           SET    (NEW_RIGHT, RIGHT);
  218.           return  LEFT.VALUE < NEW_RIGHT;
  219.        end if;
  220.     end "<";
  221.  
  222. ------------------------------------------------------------------------
  223. ------------------------------------------------------------------------
  224.  
  225.     function "<="   (LEFT: TEXT; RIGHT: TEXT)  return BOOLEAN is
  226.  
  227.     begin
  228.        return  not (LEFT > RIGHT);
  229.     end "<=";
  230.  
  231. ------------------------------------------------------------------------
  232. ------------------------------------------------------------------------
  233.  
  234.     function ">="   (LEFT: TEXT; RIGHT: TEXT)  return BOOLEAN is
  235.  
  236.     begin
  237.        return  not (LEFT < RIGHT);
  238.     end ">=";
  239.     function TXT    (FROM: STRING)           return TEXT is
  240.  
  241.     begin
  242.        return (FROM'LENGTH, FROM);
  243.     end TXT;
  244.  
  245. ------------------------------------------------------------------------
  246. ------------------------------------------------------------------------
  247.  
  248.     function TXT    (FROM: CHARACTER)        return TEXT is
  249.  
  250.        TO: STRING (1 .. 1);
  251.  
  252.     begin
  253.        TO (1) := FROM;
  254.        return (1, TO);
  255.     end TXT;
  256.  
  257. ------------------------------------------------------------------------
  258. ------------------------------------------------------------------------
  259.  
  260.     function TXT    (FROM: INTEGER; LENG: INTEGER)   return TEXT is
  261.  
  262.        TO: STRING (1 .. LENG);
  263.  
  264.     begin
  265.        PUT (TO, FROM);
  266.        return (LENG, TO);
  267.     end TXT;
  268.  
  269. ------------------------------------------------------------------------
  270. ------------------------------------------------------------------------
  271.  
  272.     function TXT  (FROM: INTEGER)  return TEXT is
  273.  
  274.        TO:   STRING (1 .. 20);
  275.  
  276.     begin
  277.        PUT (TO, FROM);
  278.        return  REMOVE_LEADING (TXT(TO), " ");
  279.     end TXT;
  280. function Txt (From: Real) return Text is
  281.  
  282.    S              : String (1 .. 20);
  283.    Exp_Notation   : Text;
  284.    Dec_Notation   : Text;
  285.    E_Position     : Integer;
  286.    Fore           : String (1 .. 1);
  287.    Aft            : Text;
  288.    Exponent       : Text;
  289.    Expon          : Integer;
  290.    Zeros_To_Add   : Integer;
  291.    Mantissa_Length: Integer;
  292.    Sign           : Text;
  293.    Exp_Sign       : Text;
  294.    Numeric        : Boolean;
  295.  
  296. begin
  297.  
  298.    Put (S, From, Aft => Real'Digits-1);
  299.    Exp_Notation := Remove_Leading (Up_Case (Txt(S)), " ");
  300.    E_Position   := Index (Exp_Notation, Txt('E'));
  301.  
  302.    if Substr(Exp_Notation,1,1) = Txt("-") then
  303.       Sign := Txt("-");
  304.       Set (Fore, Substr(Exp_Notation,2,1));
  305.       Aft := Remove_Trailing (Substr(Exp_Notation,4,E_Position-4),"0");
  306.    else
  307.       Sign := Txt("");
  308.       Set (Fore, Substr(Exp_Notation,1,1));
  309.       Aft := Remove_Trailing (Substr(Exp_Notation,3,E_Position-3),"0");
  310.    end if;
  311.  
  312.    if Length(Aft) = 0 then
  313.       Aft := Txt("0");
  314.    end if;
  315.  
  316.    Exp_Sign := Substr (Exp_Notation,E_Position+1,1);
  317.    if Exp_Sign = Txt("+") then
  318.       Exp_Sign := Txt("");
  319.    end if;
  320.  
  321.    Exponent := Remove_Leading (Substr (Exp_Notation,E_Position+2),
  322.                "0");
  323.    Set (Expon, Exp_Sign & Exponent, Numeric);
  324.  
  325.    Exp_Notation := Sign & Txt(Fore) & Txt(".") & Aft & Txt("e") &
  326.                    Exp_Sign & Exponent;
  327.    Mantissa_length := Length(Sign) + 1 + 1 + Length(Aft);
  328.  
  329.    if Expon < 0 then
  330.       if Aft = Txt("0") then
  331.          Mantissa_Length:= Mantissa_Length - 1;
  332.          Aft := Txt("");
  333.       end if;
  334.  
  335.       if Length(Exp_Notation) <= Mantissa_Length + Abs(Expon) then
  336.          return Exp_Notation;
  337.       else
  338.          return Sign & Txt("0.") & Duplicate("0",Abs(Expon)-1) &
  339.                 Txt(Fore) & Aft;
  340.       end if;
  341.    else
  342.       Zeros_To_Add := Max (Expon+1 - Length(Aft), 0);
  343.  
  344.       if Length(Sign) + Expon >= Real'Digits then
  345.          return Exp_Notation;
  346.       else
  347.          Dec_Notation := Txt(Fore) & Aft & Duplicate("0",Zeros_To_Add);
  348.          return Sign & Txt(Fore) & Substr(Dec_Notation,
  349.                 2,Expon) & Txt('.') & Substr(Dec_Notation,Expon+2);
  350.       end if;
  351.    end if;
  352.  
  353. end Txt;
  354.     function "&"    (LEFT: TEXT; RIGHT: TEXT)  return TEXT is
  355.  
  356.     begin
  357.        return TXT (STRNG(LEFT) & STRNG(RIGHT));
  358.     end "&";
  359.  
  360. ------------------------------------------------------------------------
  361. ------------------------------------------------------------------------
  362.  
  363.     function SUBSTR (FROM: TEXT; START: INTEGER; LENG: INTEGER) return TEXT is
  364.  
  365.     begin
  366.  
  367.        if (START < 1) or (START > LENGTH(FROM)) or (LENG < 0) or
  368.           (START+LENG > LENGTH(FROM)+1) then
  369.           raise SUBSCRIPT_RANGE;
  370.        end if;
  371.        return TXT (STRNG(FROM) (START .. START+LENG-1));
  372.  
  373.     end SUBSTR;
  374.  
  375. ------------------------------------------------------------------------
  376. ------------------------------------------------------------------------
  377.  
  378.     function SUBSTR (FROM: TEXT; START: INTEGER) return TEXT is
  379.  
  380.     begin
  381.  
  382.        if (START < 1) or (START > LENGTH(FROM))  then
  383.           raise SUBSCRIPT_RANGE;
  384.        end if;
  385.        return SUBSTR (FROM, START, LENGTH(FROM) + 1 - START);
  386.  
  387.     end SUBSTR;
  388.  
  389. ------------------------------------------------------------------------
  390. ------------------------------------------------------------------------
  391.  
  392.     function INDEX  (FROM: TEXT; SEEK: TEXT)  return INTEGER is
  393.  
  394.     begin
  395.  
  396.        if SEEK.VALUE'LENGTH = 0 then
  397.           return 0;
  398.        end if;
  399.  
  400.        for IDX in 1 .. INTEGER'(FROM.VALUE'LENGTH - SEEK.VALUE'LENGTH+1) loop
  401.           if FROM.VALUE (IDX .. IDX+SEEK.VALUE'LENGTH-1) = SEEK.VALUE then
  402.              return IDX;
  403.           end if;
  404.        end loop;
  405.        return 0;
  406.  
  407.     end INDEX;
  408.     function AFTER (FROM: TEXT; SEEK: TEXT)  return TEXT is
  409.  
  410.        MARK: INTEGER;
  411.  
  412.     begin
  413.        MARK := INDEX(FROM,SEEK);
  414.        if    MARK = 0 then
  415.           return (LENGTH(FROM), STRNG(FROM));
  416.        elsif MARK+LENGTH(SEEK)-1 < LENGTH(FROM) then
  417.           return SUBSTR (FROM, MARK+LENGTH(SEEK), LENGTH(FROM)-MARK-LENGTH(SEEK)+1);
  418.        else
  419.           return (0, "");
  420.        end if;
  421.     end AFTER;
  422.  
  423. ------------------------------------------------------------------------
  424. ------------------------------------------------------------------------
  425.  
  426. function TRANSLATE (FROM: TEXT; CHANGE: TEXT; SEEK: TEXT) return TEXT is
  427.  
  428.    LENG: INTEGER := MIN (LENGTH(CHANGE), LENGTH(SEEK));
  429.    TO:   TEXT    := FROM;
  430.  
  431. begin
  432.  
  433.    for FROMX in FROM.VALUE'RANGE loop
  434.       for SEEKX in 1 .. LENG loop
  435.          if FROM.VALUE (FROMX) = SEEK.VALUE (SEEKX) then
  436.             TO.VALUE (FROMX) := CHANGE.VALUE(SEEKX);
  437.             exit;
  438.          end if;
  439.       end loop;
  440.    end loop;
  441.  
  442.    return TO;
  443.  
  444. end TRANSLATE;
  445.  
  446. ------------------------------------------------------------------------
  447. ------------------------------------------------------------------------
  448.  
  449. function UP_CASE (FROM: TEXT) return TEXT is
  450.  
  451. begin
  452.  
  453.    return TRANSLATE (FROM, TXT("ABCDEFGHIJKLMNOPQRSTUVWXYZ"),
  454.                            TXT("abcdefghijklmnopqrstuvwxyz"));
  455.  
  456. end UP_CASE;
  457. function LOW_CASE (FROM: TEXT) return TEXT is
  458.  
  459. begin
  460.  
  461.    return TRANSLATE (FROM, TXT("abcdefghijklmnopqrstuvwxyz"),
  462.                            TXT("ABCDEFGHIJKLMNOPQRSTUVWXYZ"));
  463.  
  464. end LOW_CASE;
  465.  
  466. ------------------------------------------------------------------------
  467. ------------------------------------------------------------------------
  468.  
  469. function Remove_Leading (From:   Text;
  470.                          Remove: String) return Text is
  471.  
  472. begin
  473.  
  474.    for Idx in 1 .. From.Value'Length loop
  475.       if From.Value (Idx .. Idx) /= Remove then
  476.          return (From.Value'Length-Idx+1,
  477.                  From.Value (Idx .. From.Value'Length));
  478.       end if;
  479.    end loop;
  480.  
  481.    return (0, "");
  482.  
  483. end Remove_Leading;
  484.  
  485. ------------------------------------------------------------------------
  486. ------------------------------------------------------------------------
  487.  
  488. function Remove_Trailing (From:    Text;
  489.                           Remove:  String) return Text is
  490.  
  491. begin
  492.  
  493.    for Idx in reverse 1 .. From.Value'Length  loop
  494.       if From.Value (Idx .. Idx) /= Remove then
  495.          return (Idx, From.Value(1 .. Idx));
  496.       end if;
  497.    end loop;
  498.  
  499.    return (0, "");
  500.  
  501. end Remove_Trailing;
  502. function DUPLICATE  (REPEAT: STRING;
  503.                      TIMES : INTEGER)    return TEXT is
  504.  
  505.    TO:     TEXT := TXT("");
  506.  
  507. begin
  508.  
  509.    for CHARX in 1 .. TIMES loop
  510.       TO := TO & TXT(REPEAT);
  511.    end loop;
  512.  
  513.    return TO;
  514.  
  515. end DUPLICATE;
  516.  
  517. ------------------------------------------------------------------------
  518. ------------------------------------------------------------------------
  519.  
  520. function BEFORE (FROM: TEXT; SEEK: TEXT)  return TEXT is
  521.  
  522.    MARK: INTEGER;
  523.  
  524. begin
  525.    MARK := INDEX(FROM,SEEK);
  526.    if MARK = 0 then
  527.       return (LENGTH(FROM), STRNG(FROM));
  528.    else
  529.       return SUBSTR (FROM, 1, MARK-1);
  530.    end if;
  531. end BEFORE;
  532.  
  533. ------------------------------------------------------------------------
  534. ------------------------------------------------------------------------
  535.  
  536. procedure SET (TO: in out STRING; FROM: in TEXT) is
  537.  
  538.    OFFSET: INTEGER;
  539.  
  540. begin
  541.    if (FROM.VALUE'LENGTH <= TO'LENGTH) then
  542.       OFFSET := TO'FIRST - 1;
  543.       TO (1+OFFSET .. FROM.VALUE'LENGTH+OFFSET) := FROM.VALUE;
  544.       for IDX in INTEGER'(FROM.VALUE'LENGTH+1) .. TO'LENGTH loop
  545.          TO (IDX+OFFSET) := ' ';
  546.       end loop;
  547.    else
  548.       TO (1+OFFSET .. TO'LENGTH+OFFSET) := FROM.VALUE (1 .. TO'LENGTH);
  549.    end if;
  550. end SET;
  551. procedure SET (TO: out INTEGER; FROM: in TEXT; NUMERIC: out BOOLEAN) is
  552.  
  553.    COUNT: POSITIVE;
  554.  
  555. begin
  556.  
  557.    GET (FROM.VALUE, TO, COUNT);
  558.    NUMERIC := TRUE;
  559.  
  560.    exception when others =>
  561.       TO      := 0;
  562.       NUMERIC := FALSE;
  563.  
  564. end SET;
  565.  
  566. ------------------------------------------------------------------------
  567. ------------------------------------------------------------------------
  568.  
  569. procedure SET (TO: out REAL; FROM: in TEXT; NUMERIC: out BOOLEAN) is
  570.  
  571.    COUNT: POSITIVE;
  572.  
  573. begin
  574.  
  575.    GET (FROM.VALUE, TO, COUNT);
  576.    NUMERIC := TRUE;
  577.  
  578.    exception when others =>
  579.       TO      := 0.0;
  580.       NUMERIC := FALSE;
  581.  
  582. end SET;
  583.  
  584. ------------------------------------------------------------------------
  585. ------------------------------------------------------------------------
  586.  
  587. procedure SET (TO: out REAL; FROM: in TEXT) is
  588.  
  589.    COUNT: POSITIVE;
  590.  
  591. begin
  592.  
  593.    GET (FROM.VALUE, TO, COUNT);
  594.  
  595. end SET;
  596.  
  597.  
  598. end GEN_TEXT_HANDLER;
  599.  
  600. generic
  601.   type ListItem is private;
  602. --**************************
  603. package Gen_List_Handler is
  604. --=================GENERIC LIST HANDLER =======================
  605. --    Exports abstract data type ListType which supports a 
  606. --    bi-directionally linked list of User-Defined elements of 
  607. --    type ListItem . 
  608. --=============================================================
  609.  
  610.  
  611.    type ListType is private;
  612.  
  613.    type BeforeAfter is (Before,After);
  614.  
  615.    -- *** Movement Operators
  616.    procedure Move_To_First_Item( On        : in out ListType ;
  617.                                  Within_List : out Boolean );
  618.  
  619.    procedure Move_To_Last_Item( On        : in out ListType ;
  620.                                  Within_List : out Boolean );
  621.  
  622.    procedure Move_To_Next_Item ( On        : in out ListType ;
  623.                                  Within_List : out Boolean);
  624.  
  625.    procedure Move_To_Prev_Item ( On          : in out ListType;
  626.                                  Within_List : out Boolean);
  627.  
  628.    -- *** List Item operators 
  629.    procedure Get( From : in ListType;
  630.                   The_Value : out ListItem);
  631.  
  632.    procedure Insert( Onto  : in out ListType ;
  633.                      The_Value  : in ListItem ;
  634.                      Where : BeforeAfter);
  635.  
  636.    procedure Remove( From : in out ListType);
  637.  
  638.    procedure Replace( In_List : in out ListType ;
  639.                       Item : in ListItem);
  640.  
  641.    procedure Dispose( List : in out ListType);
  642.  
  643.  
  644.    -- *** List Attributes
  645.    function Is_Empty( List : in ListType) return Boolean;
  646.  
  647.    function Is_First_Item ( List : in ListType) return Boolean;
  648.  
  649.    function Is_Last_Item ( List : in ListType) return Boolean;
  650.  
  651.    function Length ( List : in ListType) return natural;
  652.  
  653.    List_Access_Exception : Exception;
  654.  
  655.    private
  656.       type chain_list;
  657.       type ListCell;
  658.       
  659.       type chain_list is access ListCell;
  660.       type ListCell is
  661.          record
  662.             Item_Value : ListItem;
  663.             Next_Item  : chain_list;
  664.             Prev_Item  : chain_list;
  665.          end record;
  666.  
  667.       type ListType is
  668.     record
  669.       head_node : chain_list;
  670.       current_node : chain_list;
  671.     end record;
  672.  
  673.    end;
  674. with Unchecked_Deallocation;
  675.  
  676. package body Gen_List_Handler is
  677.  
  678.  
  679.     procedure kill_node is new 
  680.                          Unchecked_Deallocation(ListCell,chain_list);
  681.  
  682.  --*************************************************************
  683.  
  684.     procedure Move_To_First_Item (On       : in out ListType;
  685.                       Within_List: out Boolean) is
  686.  
  687.         L: chain_list := On.head_node;
  688.  
  689.       begin
  690.         if L = null then
  691.           Within_List := FALSE;
  692.         else
  693.             Within_List := TRUE;
  694.             On.current_node := L;
  695.         end if;
  696.       end Move_To_First_Item;
  697.  
  698.  --*************************************************************
  699.  
  700.     procedure Move_To_Last_Item (On       : in out ListType;
  701.                       Within_List: out Boolean) is
  702.  
  703.         L: chain_list := On.current_node;
  704.  
  705.       begin
  706.         if On.head_node = null then
  707.           Within_List := FALSE;
  708.         else
  709.             Within_List := TRUE;
  710.             while L.Next_Item /= null loop
  711.             L:= L.Next_Item;
  712.             end loop;
  713.             On.current_node := L;
  714.         end if;
  715.       end Move_To_Last_Item;
  716.  
  717.  
  718.  --*************************************************************
  719.  
  720.     procedure Move_To_Next_Item (On       : in out ListType;
  721.                       Within_List: out Boolean) is
  722.  
  723.         L: chain_list := On.current_node;
  724.  
  725.       begin
  726.         Within_List := FALSE;
  727.         if On.head_node /= null then
  728.            if L.Next_Item /= null then
  729.               Within_List := TRUE;
  730.               L := L.Next_Item;
  731.               On.current_node := L;
  732.            end if;
  733.         end if;
  734.       end Move_To_Next_Item;
  735.  
  736.  --************************************************************
  737.  
  738.     procedure Move_To_Prev_Item (On       : in out ListType;
  739.                       Within_List: out Boolean) is
  740.  
  741.         L: chain_list := On.current_node;
  742.  
  743.       begin
  744.         Within_List := FALSE;
  745.         if On.head_node /= null then
  746.            if L.Prev_Item /= null then
  747.               Within_List := TRUE;
  748.               L := L.Prev_Item;
  749.               On.current_node := L;
  750.            end if;
  751.         end if;
  752.     end Move_To_Prev_Item;
  753.  
  754.  
  755.  --************************************************************
  756.  
  757.     procedure Get (From        : in ListType;
  758.                The_Value        : out ListItem) is
  759.  
  760.         L : chain_list := From.current_node;
  761.  
  762.     begin
  763.       if From.head_node = null then
  764.         raise List_Access_Exception;
  765.       else
  766.         The_Value := L.Item_Value;
  767.       end if;
  768.     end Get;
  769.  
  770.  
  771.  --************************************************************
  772.  
  773.     procedure Insert (Onto        : in out ListType;
  774.               The_Value    : in ListItem;
  775.               Where        : BeforeAfter ) is
  776.  
  777.         L : chain_list := Onto.current_node;
  778.         N : chain_list;
  779.  
  780.     begin
  781.  
  782.       N := new ListCell;
  783.       N.Item_Value := The_Value;
  784.       N.Next_Item  := null;
  785.       N.Prev_Item  := null;
  786.  
  787.       if Onto.head_node = null then
  788.          Onto.head_node := new ListCell;
  789.          Onto.head_node := N;
  790.          Onto.current_node := N;
  791.          return;
  792.       end if;
  793.  
  794.       If (Where = After) then 
  795.  
  796.        -- It is to be inserted after
  797.        if L.Next_Item /= null then
  798.         N.Next_Item := L.Next_Item;
  799.         L.Next_Item := N;
  800.         N.Prev_Item := L;
  801.         L := L.Next_Item;
  802.         N := N.Next_Item;
  803.         N.Prev_Item := L;
  804.           else
  805.         L.Next_Item := N;
  806.         N.Prev_Item := L;
  807.         L := L.Next_Item;
  808.        end if;
  809.  
  810.       else
  811.        -- It is to be inserted before
  812.        if L.Prev_Item /= null then
  813.         L := L.Prev_Item;
  814.         N.Next_Item := L.Next_Item;
  815.         L.Next_Item := N;
  816.         N.Prev_Item := L;
  817.         L := L.Next_Item;
  818.         N := N.Next_Item;
  819.         N.Prev_Item := L;
  820.           else
  821.         N.Next_Item := L;
  822.         L.Prev_Item := N;
  823.         L := L.Prev_Item;
  824.       end if;
  825.      end if;
  826.  
  827.     if L.Prev_Item = null then
  828.        Onto.head_node := L;
  829.     end if;
  830.  
  831.     Onto.current_node := L;
  832.     end Insert;
  833.  
  834.  --***********************************************************
  835.  
  836.     procedure Remove (From : in out ListType) is
  837.  
  838.         L : chain_list := From.current_node;
  839.         N : chain_list;
  840.  
  841.       begin
  842.  
  843.         if L.Next_Item /= null and L.Prev_Item = null then
  844.         -- remove first node
  845.         N := L;
  846.         L := L.Next_Item;
  847.         N.Next_Item := null;
  848.         L.Prev_Item := null;
  849.         kill_node (N);
  850.         From.head_node := L;
  851.  
  852.         elsif  L.Next_Item = null and L.Prev_Item /= null then
  853.         -- remove last node
  854.         N := L;
  855.         L := L.Prev_Item;
  856.         N.Prev_Item := null;
  857.         L.Next_Item := null;
  858.         kill_node(N);
  859.  
  860.         elsif  L.Next_Item /= null and L.Prev_Item /= null then
  861.         -- removing a middle node
  862.         N := L;
  863.         L := L.Prev_Item;
  864.         L.Next_Item := N.Next_Item;
  865.         N.Next_Item := null;
  866.         L := L.Next_Item;
  867.         L.Prev_Item := N.Prev_Item;
  868.         N.Prev_Item := null;
  869.         kill_node(N);
  870.  
  871.         else
  872.         -- no node to remove, be sure of it
  873.         kill_node(L);
  874.         From.head_node := null;
  875.             From.current_node := null;
  876.         end if;
  877.  
  878.         From.current_node := L;
  879.  
  880.      end Remove;
  881.  
  882.  --**********************************************************
  883.  
  884.     procedure Replace (In_List : in out ListType;
  885.                Item    : in ListItem) is
  886.  
  887.         L : chain_list := In_list.current_node;
  888.  
  889.      begin
  890.        If In_List.head_node = null then
  891.         raise List_Access_Exception;
  892.        else
  893.         L.Item_value := Item;
  894.         In_list.current_node := L; 
  895.        end if;
  896.      end Replace;
  897.  
  898.  --*********************************************************
  899.  
  900.     procedure Dispose( List : in out ListType) is
  901.  
  902.       L : chain_list := List.head_node;
  903.       N : chain_list;
  904.  
  905.     begin
  906.       if L /= null then
  907.       -- we kill the list
  908.       while L.Next_Item /= null loop
  909.         N := L;
  910.         L := L.Next_Item;
  911.         N.Next_Item := null;
  912.         L.Prev_Item := null;
  913.         kill_node (N);
  914.       end loop;
  915.       kill_node (L);
  916.       kill_node (List.current_node);
  917.       kill_node (List.head_node);
  918.       end if;
  919.     end Dispose;
  920.  
  921.  --********************************************************
  922.  
  923.     function Is_Empty(List : in ListType) return Boolean is
  924.  
  925.       L : chain_list := List.head_node;
  926.  
  927.       begin
  928.         if L = null then
  929.         return TRUE;
  930.          else
  931.         return FALSE;
  932.         end if;
  933.       end Is_Empty;
  934.  
  935.  --********************************************************
  936.     function Is_Last_Item (List : in ListType) return Boolean is
  937.  
  938.       L : chain_list ;
  939.  
  940.       begin
  941.     if List.head_node = null then
  942.         return TRUE;
  943.     end if;
  944.         L := List.current_node ;
  945.         if L.Next_Item = null then
  946.         return TRUE;
  947.          else
  948.         return FALSE;
  949.         end if;
  950.       end Is_Last_Item;
  951.  
  952.  --********************************************************
  953.     function Is_First_Item (List : in ListType) return Boolean is
  954.  
  955.       L : chain_list ;
  956.  
  957.       begin
  958.     if List.head_node = null then
  959.         return TRUE;
  960.     end if;
  961.         L := List.current_node ;
  962.         if L.Prev_Item = null then
  963.         return TRUE;
  964.          else
  965.         return FALSE;
  966.         end if;
  967.       end Is_First_Item;
  968.  
  969.  --********************************************************
  970.     function Length ( List : in ListType) return natural is
  971.  
  972.       L : chain_list := List.head_node;
  973.       N : chain_list;
  974.       counter : natural := 0;
  975.  
  976.       begin
  977.         if L = null then
  978.         return counter;
  979.         else
  980.         N := L;
  981.  
  982.         loop
  983.           counter := counter + 1;
  984.           if N.Next_Item = null then
  985.             return counter;
  986.           else
  987.             N := N.Next_Item;
  988.           end if;
  989.         end loop;
  990.  
  991.         end if;
  992.       end Length;
  993.  
  994.    end Gen_List_Handler;
  995. generic
  996.    type DynFloat is digits <>;
  997.    type IndexType is range <>;
  998. package Gen_Dyn_Mat is
  999. --==================  GENERIC DYNAMIC MATRIX PACKAGE ==================
  1000. --    Exports two Abstract Dynamic Array Types DynMatrix and DynVector. 
  1001. --    The size of the dynvector(or dynmatrix) can be constrained at  decl
  1002. --    time. These arrays must not be constrained at declaration time if 
  1003. --    they are to be changed during execution(by using the Allocate 
  1004. --    function or other exported function which returns a Dynamic type).
  1005. --             DV : DynVector(5)              -- Constrained to size 5
  1006. --             DV : DynVector := Allocate(5); -- Initialized to size 5
  1007. --=====================================================================
  1008.  
  1009.  
  1010.    --=============DYNAMIC ARRAY TYPES===============
  1011.    type DynVector(Size : IndexType := 1) is private;
  1012.  
  1013.    type DynMatrix(Row_Size : IndexType   := 1;
  1014.                   Col_Size : IndexType   := 1) is private;
  1015.    --===============================================
  1016.  
  1017.  
  1018.    type    Vect         is array (IndexType range <>) of DynFloat;
  1019.  
  1020.    type    Matrx         is array (IndexType   range<>,
  1021.                                    IndexType   range<>) of DynFloat;
  1022.     -- ******************* DynVector Primitives  **************
  1023.  
  1024.     --    Exports the Basic Array Operations (Assignment, Value_Of ...)
  1025.  
  1026.    function Allocate (Size   : IndexType) return DynVector;
  1027.    function Value_Of(DV      : DynVector; 
  1028.                      At_Index: IndexType) return DynFloat;
  1029.  
  1030.    function Last_Index_Of(DV : DynVector) return IndexType;
  1031.    function Dyn_Vector_Of(V  : Vect)      return DynVector;
  1032.    function Vector_Of(DV     : DynVector) return Vect;
  1033.  
  1034.    procedure Assign(DV       : in out DynVector;  
  1035.                     At_Index : IndexType ; 
  1036.                     Value    : DynFloat) ;
  1037.  
  1038.    pragma InLine (Allocate, Value_Of, Last_Index_Of, Dyn_Vector_Of,
  1039.                   Vector_Of, Assign);
  1040.  
  1041.    -- ******************  DynMatrix Primitives ***************
  1042.  
  1043.     --    Exports the Basic Matrix  Operations (Assignment, Value_Of ...)
  1044.  
  1045.    function Allocate(Row_Size , Col_Size : IndexType) return DynMatrix;
  1046.  
  1047.    function Value_Of( DM             : DynMatrix ;
  1048.                       At_Row, At_Col : IndexType) return DynFloat;
  1049.  
  1050.    function Last_Row_Of(DM  : DynMatrix) return IndexType;
  1051.  
  1052.    function Last_Col_Of(DM  : DynMatrix) return IndexType;
  1053.  
  1054.    function Dyn_Matrix_Of(M : Matrx)     return DynMatrix;
  1055.  
  1056.    function Matrix_Of(DM    : DynMatrix) return Matrx;
  1057.  
  1058.    procedure Assign( DM             : in out DynMatrix;
  1059.                      At_Row, At_Col : IndexType;
  1060.                      Value          : DynFloat);
  1061.    pragma InLine (Allocate, Value_Of, Last_Row_Of, Last_Col_Of,
  1062.                   Dyn_Matrix_Of, Matrix_Of, Assign );
  1063. --****************************** Matrix Library **************
  1064. --    Exports Mathematical Operations associated with arrays.
  1065. --              **** Vector Operations **** 
  1066.  
  1067.       function Vectors_OK(V1,V2: DynVector)      return Boolean;
  1068.  
  1069.       function "*"       (I : Integer ; V : DynVector) return DynVector;
  1070.       function "*"       (R : DynFloat; V : DynVector) return DynVector;
  1071.       function "+"       (V1,V2 : DynVector) return DynVector;
  1072.       function "-"       (V :     DynVector) return DynVector;
  1073.       function "-"       (V1,V2 : DynVector) return DynVector;
  1074.       function Dot       (V1,V2 : DynVector) return DynFloat;
  1075.       function Sum_Vec   (V :     DynVector) return DynFloat;
  1076.  
  1077.       function Make_Mat  (V :     DynVector;
  1078.                           Dim :   Positive) return DynMatrix;
  1079.  
  1080.       pragma InLine (Vectors_OK , Sum_Vec );
  1081.  
  1082.    -- **********   MATRIX operations   **********
  1083.  
  1084.       function Mat_Multiply_OK (M1,M2: DynMatrix) return Boolean;
  1085.       function Mat_Match       (M1,M2: DynMatrix) return Boolean;
  1086.  
  1087.       function "*" (I : Integer ; M : DynMatrix) return DynMatrix;
  1088.       function "*" (R : DynFloat ; M : DynMatrix) return DynMatrix;
  1089.       function "+" (M1,M2 : DynMatrix) return DynMatrix;
  1090.       function "-" (M :     DynMatrix) return DynMatrix;
  1091.       function "*" (M1,M2 : DynMatrix) return DynMatrix;
  1092.       function "-" (M1,M2 : DynMatrix) return DynMatrix;
  1093.       function Transpose_Mat  (M  : DynMatrix) return DynMatrix;
  1094.  
  1095.       function Sum_Mat_By_Row (M  : DynMatrix;
  1096.                                Row: IndexType) return DynFloat;
  1097.  
  1098.       function Sum_Mat_By_Col (M  : DynMatrix;
  1099.                                Col: IndexType) return DynFloat;
  1100.  
  1101.       function Extract_Row    (M  : DynMatrix;
  1102.                               Row : IndexType) return DynVector;
  1103.  
  1104.       function Extract_Col    (M  : DynMatrix;
  1105.                               Col : IndexType) return DynVector;
  1106.  
  1107.       procedure Replace_Row (In_Mat : in out DynMatrix; 
  1108.                              Row    : IndexType;
  1109.                              Value  : in DynVector); 
  1110.  
  1111.       procedure Replace_Col (In_Mat : in out DynMatrix; 
  1112.                              Col    : IndexType;
  1113.                              Value  : in DynVector); 
  1114.  
  1115.       pragma InLine ( Mat_Multiply_OK, Mat_Match,  Sum_Mat_By_Row, 
  1116.                       Sum_Mat_By_Col, Extract_Row, Extract_Col);
  1117.  
  1118.       function Unit_Mat (Size : IndexType)    return DynMatrix;
  1119.       function Invert_Mat (M : in  DynMatrix) return DynMatrix;
  1120.  
  1121.    -- **********   MATRIX and VECTOR operations   **********
  1122.  
  1123.       function Vec_Mat_OK (V :   DynVector;
  1124.                            M :   DynMatrix) return Boolean;
  1125.  
  1126.       function Mat_Vec_OK (M :   DynMatrix;
  1127.                            V :   DynVector) return Boolean;
  1128.  
  1129.       function "*"        (V :   DynVector;
  1130.                            M :   DynMatrix) return DynVector;
  1131.  
  1132.       function "*"        (M :   DynMatrix;
  1133.                            V :   DynVector) return DynVector;
  1134.  
  1135.      pragma InLine (Vec_Mat_OK , Mat_Vec_OK);
  1136.  
  1137.    -- **********   EXCEPTIONS **********
  1138.  
  1139.       Matrix_Mismatch_Error  : exception;
  1140.       Matrix_Inversion_Error : exception;
  1141.  
  1142. private
  1143.    type DynVector(Size : IndexType := 1) is 
  1144.       record
  1145.         Vec : Vect(1..Size);
  1146.       end record;
  1147.  
  1148.    type DynMatrix(Row_Size : IndexType   := 1;
  1149.                   Col_Size : IndexType   := 1) is 
  1150.      record
  1151.         Mat : Matrx (1  .. Row_Size,
  1152.                      1  .. Col_Size);
  1153.      end record;
  1154.  
  1155. end Gen_Dyn_Mat;
  1156.  
  1157. package body Gen_Dyn_Mat is
  1158.  
  1159.     --  *** DynVector Primitives  ***
  1160.  
  1161.    --*************************************************
  1162.    function Allocate( Size:IndexType) return DynVector is
  1163.    begin
  1164.          return (Size,(others => 0.0));
  1165.   end Allocate;
  1166.  
  1167.    --*************************************************
  1168.    function Value_Of(DV:DynVector; At_Index : IndexType) return DynFloat is
  1169.    begin
  1170.      return DV.Vec(At_Index);
  1171.    end Value_Of;
  1172.  
  1173.    --*************************************************
  1174.    function Last_Index_Of(DV:DynVector) return IndexType is
  1175.    begin
  1176.       return DV.Vec'Last;
  1177.    end Last_Index_Of;
  1178.  
  1179.    --*************************************************
  1180.    function Dyn_Vector_Of(V:Vect) return DynVector is
  1181.    begin
  1182.       return (V'last,(V));
  1183.    end Dyn_Vector_Of;
  1184.  
  1185.    --*************************************************
  1186.    function Vector_Of(DV:DynVector) return Vect is
  1187.    begin
  1188.       return DV.Vec;
  1189.    end Vector_Of;
  1190.  
  1191.    -- DynMatrix Primitives
  1192.  
  1193.    --*************************************************
  1194.    function Allocate( Row_Size, Col_Size : IndexType) return DynMatrix is
  1195.    begin
  1196.      return (Row_Size,Col_Size,(others=> (others =>0.0)));
  1197.    end Allocate;
  1198.      
  1199.  
  1200.    --*************************************************
  1201.    function Value_Of(DM : DynMatrix;
  1202.                      At_Row,At_Col :IndexType) return DynFloat is
  1203.    begin
  1204.       return DM.Mat(At_Row,At_Col);
  1205.    end Value_Of;
  1206.  
  1207.    --*************************************************
  1208.    procedure Assign(DV:in out DynVector;  At_Index:IndexType; Value:DynFloat)is 
  1209.    begin
  1210.       DV.Vec(At_Index) := Value;
  1211.    end Assign;
  1212.     -- *** DynMatrix Primitives ***
  1213.  
  1214.    --*************************************************
  1215.    function Last_Row_Of(DM:DynMatrix) return IndexType is
  1216.    begin
  1217.       return DM.Mat'Last(1);
  1218.    end Last_Row_Of;
  1219.  
  1220.    --*************************************************
  1221.    function Last_Col_Of(DM:DynMatrix) return IndexType is
  1222.    begin
  1223.      return DM.Mat'Last(2);
  1224.    end Last_Col_Of;
  1225.  
  1226.    --*************************************************
  1227.    function Dyn_Matrix_Of(M:Matrx) return DynMatrix is
  1228.    begin
  1229.     return (M'last(1),M'last(2),(M));
  1230.    end Dyn_Matrix_Of;
  1231.  
  1232.    --*************************************************
  1233.    function Matrix_Of(DM:DynMatrix) return Matrx is
  1234.    begin
  1235.       return DM.Mat;
  1236.    end Matrix_Of;
  1237.  
  1238.     -- *** Matrix Library Routines  ***
  1239.    --*************************************************
  1240.    procedure Assign( DM            : in out DynMatrix;
  1241.                      At_Row,At_Col : IndexType;
  1242.                      Value         : DynFloat)is
  1243.    begin
  1244.       DM.Mat(At_Row,At_Col) := Value;
  1245.    end Assign;
  1246.  
  1247.   --   ***** Matrix Library
  1248.   function Vectors_OK (V1,V2: DynVector) return Boolean is
  1249.      -- Returns true if V1 and V2 have same size
  1250.   begin
  1251.      return (V1.Vec'Length = V2.Vec'Length);
  1252.   end Vectors_OK;
  1253.  
  1254.   -- ************************************************************
  1255.  
  1256.   function "*" (I : Integer ; V : DynVector) return DynVector is
  1257.     Local : DynVector(V.Size);
  1258.   begin
  1259.     for Row in V.Vec'Range loop
  1260.        Local.Vec(Row) := DynFloat(I) * V.Vec(Row);
  1261.     end loop;
  1262.     return Local;
  1263.   end "*";
  1264.  
  1265.   -- ************************************************************
  1266.   function "*" (R : DynFloat ; V : DynVector) return DynVector is
  1267.     Local : DynVector(V.Size);
  1268.   begin
  1269.     for Row in V.Vec'Range loop
  1270.        Local.Vec(Row) := R * V.Vec(Row);
  1271.     end loop;
  1272.     return Local;
  1273.   end "*";
  1274.  
  1275.   -- ************************************************************
  1276.   function "+" (V1,V2: DynVector) return DynVector is
  1277.      Sum : DynVector (V1.Size);
  1278.   begin
  1279.      if Vectors_OK (V1,V2) then
  1280.         for Row in V1.Vec'Range loop
  1281.            Sum.Vec(Row) := V1.Vec(Row) + V2.Vec(Row);
  1282.         end loop;
  1283.         return Sum;
  1284.      else
  1285.         raise Matrix_Mismatch_Error;
  1286.      end if;
  1287.   end "+";
  1288.  
  1289.   -- ************************************************************
  1290.  
  1291.   function "-" (V: DynVector) return DynVector is
  1292.      -- Performs unitary minus
  1293.      Neg : DynVector(V.Size);
  1294.   begin
  1295.      for Row in V.Vec'Range loop
  1296.         Neg.Vec(Row) := -V.Vec(Row);
  1297.      end loop;
  1298.      return Neg;
  1299.   end "-";
  1300.  
  1301.   -- ************************************************************
  1302.  
  1303.   function "-" (V1,V2: DynVector) return DynVector is
  1304.      -- Performs vector subtraction V1 - V2
  1305.      Diff : DynVector(V1.Size);
  1306.   begin
  1307.      if Vectors_OK (V1,V2) then
  1308.         return V1 + (-V2);
  1309.      else
  1310.         raise Matrix_Mismatch_Error;
  1311.      end if;
  1312.   end "-";
  1313.    -- ************************************************************
  1314.  
  1315.   function Dot (V1,V2 :DynVector) return DynFloat is
  1316.      -- Performs vector dot product V1 * V2
  1317.      Sum: DynFloat;
  1318.   begin
  1319.      if Vectors_OK (V1,V2) then
  1320.         Sum := 0.0;
  1321.         for Row in V1.Vec'Range loop
  1322.            Sum := Sum + V1.Vec(Row) * V2.Vec(Row);
  1323.         end loop;
  1324.         return Sum;
  1325.      else
  1326.         raise Matrix_Mismatch_Error;
  1327.      end if;
  1328.   end Dot;
  1329.  
  1330.   -- ************************************************************
  1331.  
  1332.   function Sum_Vec (V: DynVector) return DynFloat is
  1333.      -- Sums the elements of vector V
  1334.      Sum: DynFloat;
  1335.   begin
  1336.      Sum := 0.0;
  1337.      for Row in V.Vec'Range loop
  1338.         Sum := Sum + V.Vec(Row);
  1339.      end loop;
  1340.      return Sum;
  1341.   end Sum_Vec;
  1342.  
  1343.   -- ************************************************************
  1344.  
  1345.   function Make_Mat (V:   DynVector;
  1346.                      Dim: Positive)  return DynMatrix is
  1347.      -- Converts V into a matrix. Dim determines in which dimension it goes
  1348.      M1: DynMatrix(V.Size,1);
  1349.      M2: DynMatrix(1,V.Size);
  1350.   begin
  1351.      if    (Dim = 1) then
  1352.         for Row in V.Vec'Range loop
  1353.            M1.Mat (Row,1) := V.Vec(Row);
  1354.         end loop;
  1355.         return M1;
  1356.      elsif (Dim = 2) then
  1357.         for Col in V.Vec'Range loop
  1358.            M2.Mat (1,Col) := V.Vec(Col);
  1359.         end loop;
  1360.         return M2;
  1361.      else
  1362.         raise Matrix_Mismatch_Error;
  1363.      end if;
  1364.   end Make_Mat;
  1365.  
  1366.   -- ************************************************************
  1367.  
  1368.   function Mat_Multiply_OK (M1,M2: DynMatrix) return Boolean is
  1369.      -- Returns true if number of cols in M1 = number of rows in M2
  1370.   begin
  1371.      return (M1.Mat'Length(2) = M2.Mat'Length(1));
  1372.   end Mat_Multiply_Ok;
  1373.  
  1374.   -- ************************************************************
  1375.  
  1376.   function Mat_Match (M1,M2: DynMatrix) return Boolean is
  1377.      -- Returns true if M1 and M2 have same dimension
  1378.   begin
  1379.      return (M1.Mat'Length(1) = M2.Mat'Length(1)) and
  1380.             (M1.Mat'Length(2) = M2.Mat'Length(2));
  1381.   end Mat_Match;
  1382.  
  1383.   -- ************************************************************
  1384.  
  1385.   function "*" (I : Integer ; M : DynMatrix) return DynMatrix is
  1386.     Local : DynMatrix(M.Row_Size,M.Col_Size);
  1387.   begin
  1388.      for Row in M.Mat'Range(1) loop
  1389.         for Col in M.Mat'Range(2) loop
  1390.            Local.Mat(Row,Col) := DynFloat(I) * M.Mat(Row,Col);
  1391.         end loop;
  1392.      end loop;
  1393.      return Local;
  1394.   end "*";
  1395.       
  1396.   -- ************************************************************
  1397.  
  1398.   function "*" (R : DynFloat ; M : DynMatrix) return DynMatrix is
  1399.     Local : DynMatrix(M.Row_Size,M.Col_Size);
  1400.   begin
  1401.      for Row in M.Mat'Range(1) loop
  1402.         for Col in M.Mat'Range(2) loop
  1403.            Local.Mat(Row,Col) := R * M.Mat(Row,Col);
  1404.         end loop;
  1405.      end loop;
  1406.      return Local;
  1407.   end "*";
  1408.  
  1409.  
  1410.   -- ************************************************************
  1411.   function "+" (M1,M2: DynMatrix) return DynMatrix is
  1412.      -- Performs matrix addition.
  1413.      Sum:       DynMatrix (M1.Row_Size, M1.Col_Size);
  1414.   begin
  1415.      if Mat_Match (M1,M2) then
  1416.         for Row in M1.Mat'Range(1) loop
  1417.            for Col in M1.Mat'Range(2) loop
  1418.               Sum.Mat(Row,Col) := M1.Mat(Row,Col) + M2.Mat(Row,Col);
  1419.            end loop;
  1420.         end loop;
  1421.         return Sum;
  1422.      else
  1423.         raise Matrix_Mismatch_Error;
  1424.      end if;
  1425.   end "+";
  1426.  
  1427.   -- ************************************************************
  1428.  
  1429.   function "-" (M: DynMatrix) return DynMatrix is
  1430.      -- Performs unitary minus
  1431.      Neg : DynMatrix (M.Row_Size, M.Col_Size);
  1432.   begin
  1433.      for Row in M.Mat'Range(1) loop
  1434.         for Col in M.Mat'Range(2) loop
  1435.            Neg.Mat(Row,Col) := -M.Mat(Row,Col);
  1436.         end loop;
  1437.      end loop;
  1438.      return Neg;
  1439.   end "-";
  1440.  
  1441.   -- ************************************************************
  1442.  
  1443.   function "-" (M1,M2: DynMatrix) return DynMatrix is
  1444.      -- Performs matrix substraction M1 - M2
  1445.      Diff : DynMatrix (M1.Row_Size, M1.Col_Size);
  1446.   begin
  1447.      if Mat_Match (M1,M2) then
  1448.         return M1 + (-M2);
  1449.      else
  1450.         raise Matrix_Mismatch_Error;
  1451.      end if;
  1452.   end "-";
  1453.  
  1454.   -- ************************************************************
  1455.  
  1456.   function Transpose_Mat (M: DynMatrix) return DynMatrix is
  1457.      -- Performs matrix transposition
  1458.      Tran: DynMatrix (M.Col_Size, M.Row_Size);
  1459.   begin
  1460.      for Row in M.Mat'Range(1) loop
  1461.         for Col in M.Mat'Range(2) loop
  1462.            Tran.Mat(Col,Row) := M.Mat(Row,Col);
  1463.         end loop;
  1464.      end loop;
  1465.      return Tran;
  1466.   end Transpose_Mat;
  1467.  
  1468.   -- ************************************************************
  1469.  
  1470.   function Extract_Row (M:   DynMatrix;
  1471.                         Row: IndexType)     return DynVector is
  1472.      -- Extracts row Row from M
  1473.      Slice: DynVector (M.Col_Size);
  1474.   begin
  1475.      if Row in M.Mat'Range(1) then 
  1476.         for Col in M.Mat'Range(2) loop
  1477.            Slice.Vec(Col) := M.Mat(Row,Col);
  1478.         end loop;
  1479.         return Slice;
  1480.      else
  1481.         raise Matrix_Mismatch_Error;
  1482.      end if;
  1483.   end Extract_Row;
  1484.  
  1485.   -- ************************************************************
  1486.  
  1487.   function Extract_Col (M:   DynMatrix;
  1488.                         Col: IndexType)     return DynVector is
  1489.      -- Extracts column Col from M
  1490.      Slice: DynVector (M.Row_Size);
  1491.   begin
  1492.      if Col in M.Mat'Range(2) then 
  1493.         for Row in M.Mat'Range(1) loop
  1494.            Slice.Vec(Row) := M.Mat(Row,Col);
  1495.         end loop;
  1496.         return Slice;
  1497.      else
  1498.         raise Matrix_Mismatch_Error;
  1499.      end if;
  1500.   end Extract_Col;
  1501.  
  1502.   --***************************************************
  1503.   procedure Replace_Row (In_Mat : in out DynMatrix; Row  : IndexType; 
  1504.                          Value  : in DynVector) is 
  1505.   begin
  1506.      if (In_Mat.Mat'Last(2) /= Value.Vec'Last) or
  1507.                           (Row not in In_Mat.Mat'Range(1)) then
  1508.         raise Matrix_Mismatch_Error;
  1509.      end if;
  1510.      for Col in In_Mat.Mat'Range(2) loop 
  1511.         In_Mat.Mat(Row,Col) := Value.Vec(Col);
  1512.      end loop;
  1513.   end Replace_Row;
  1514.  
  1515.   --***************************************************
  1516.   procedure Replace_Col (In_Mat : in out DynMatrix; Col  : IndexType; 
  1517.                          Value  : in DynVector) is 
  1518.   begin
  1519.      if (In_Mat.Mat'last(1) /= Value.Vec'last) or
  1520.                           (Col not in In_Mat.Mat'range(2)) then
  1521.         raise Matrix_Mismatch_Error;
  1522.      end if;
  1523.      for Row in In_Mat.Mat'Range(1) loop 
  1524.         In_Mat.Mat(Row,Col) := Value.Vec(Row);
  1525.      end loop;
  1526.   end Replace_Col;
  1527.  
  1528.  
  1529.   -- ************************************************************
  1530.  
  1531.   function Sum_Mat_By_Row  (M:   DynMatrix;
  1532.                             Row: IndexType)     return DynFloat is
  1533.      -- Sums the elements in row Row of M
  1534.   begin
  1535.      if Row in M.Mat'range then
  1536.         return Sum_Vec (Extract_Row (M,Row));
  1537.      else
  1538.         raise Matrix_Mismatch_Error;
  1539.      end if;
  1540.    end Sum_Mat_By_Row;
  1541.  
  1542.   -- ************************************************************
  1543.  
  1544.   function Sum_Mat_By_Col  (M:   DynMatrix;
  1545.                             Col: IndexType)     return DynFloat is
  1546.      -- Sums the elements in column Col of M
  1547.   begin
  1548.      if Col in M.Mat'range then
  1549.         return Sum_Vec (Extract_Col (M,Col));
  1550.      else
  1551.         raise Matrix_Mismatch_Error;
  1552.      end if;
  1553.   end ;
  1554.  
  1555.   -- ************************************************************
  1556.  
  1557.   function "*" (M1,M2: DynMatrix) return DynMatrix is
  1558.      -- Performs matrix multiplication M1 * M2
  1559.      Prod: DynMatrix (M1.Row_Size, M2.Col_Size);
  1560.   begin
  1561.      if Mat_Multiply_OK (M1,M2) then
  1562.         for Row in M1.Mat'Range(1) loop
  1563.            for Col in M2.Mat'Range(2) loop
  1564.               Prod.Mat(Row,Col) := Dot (Extract_Row(M1,Row), Extract_Col(M2,Col));
  1565.            end loop;
  1566.         end loop;
  1567.         return Prod;
  1568.      else
  1569.         raise Matrix_Mismatch_Error;
  1570.      end if;
  1571.   end "*";
  1572.  
  1573.   -- ************************************************************
  1574.  
  1575.   function Vec_Mat_OK (V: DynVector;
  1576.                        M: DynMatrix) return Boolean is
  1577.      -- Determines if V * M is defined
  1578.   begin
  1579.      return (V.Vec'Length = M.Mat'Length(1));
  1580.   end Vec_Mat_OK;
  1581.  
  1582.   -- ************************************************************
  1583.  
  1584.   function Mat_Vec_OK (M: DynMatrix;
  1585.                        V: DynVector) return Boolean is
  1586.      -- Determines if M * V is defined
  1587.   begin
  1588.      return (V.Vec'Length = M.Mat'Length(2));
  1589.   end Mat_Vec_OK;
  1590.  
  1591.   -- ************************************************************
  1592.  
  1593.   function "*" (V: DynVector;
  1594.                 M: DynMatrix) return DynVector is
  1595.      -- Performs matrix multiplication V * M where V is considered to
  1596.      -- be a 1 by V.Vec'Length matrix
  1597.      M_Vec: DynMatrix(1,V.Size);
  1598.   begin
  1599.      if Vec_Mat_OK (V, M) then
  1600.         M_Vec := Make_Mat(V,2);
  1601.         return Extract_Row (M_Vec * M, 1);
  1602.      else
  1603.         raise Matrix_Mismatch_Error;
  1604.      end if;
  1605.   end "*";
  1606.  
  1607.   -- ************************************************************
  1608.  
  1609.   function "*" (M: DynMatrix;
  1610.                 V: DynVector) return DynVector is
  1611.      -- Performs matrix multiplication M * V where V is considered to
  1612.      -- be a V.Vec'Length by 1 matrix
  1613.      M_Vec: DynMatrix(V.Size,1);
  1614.   begin
  1615.      if Mat_Vec_OK (M, V) then
  1616.         M_Vec := Make_Mat(V,1);
  1617.         return Extract_Col (M * M_Vec, 1);
  1618.      else
  1619.         raise Matrix_Mismatch_Error;
  1620.      end if;
  1621.   end "*";
  1622.  
  1623.   -- ************************************************************
  1624.  
  1625.   function Unit_Mat(Size: in IndexType) return DynMatrix is
  1626.      Unitary : DynMatrix(Size,Size):=(Size,Size,(others=>(others=>0.0)));
  1627.   begin
  1628.      for RowCol in Unitary.Mat'Range(1) loop
  1629.         Unitary.Mat(RowCol,RowCol) := 1.0;
  1630.      end loop;
  1631.      return Unitary;
  1632.   end;
  1633.  
  1634.    -- ************************************************************
  1635.  
  1636.    function Invert_Mat   (M       : in DynMatrix) return DynMatrix is
  1637.  
  1638.     Size :constant IndexType  := M.Mat'Last(1);
  1639.     type IndexVector is array (IndexType range <>) of IndexType;
  1640.     subtype RowIndex is IndexType range 1.. Size;
  1641.     Unit        : DynMatrix(Size,Size):= Unit_Mat(Size);
  1642.     Unitary     : DynMatrix(Size,Size):= Unit_Mat(Size);
  1643.     Local       : DynMatrix(Size,Size):= M;
  1644.     Permut      : IndexVector(1..Size);
  1645.     Temp        : DynFloat;
  1646.     Norm        : DynFloat;
  1647.     Pivot       : DynFloat;
  1648.     Virtual_Row : RowIndex ;
  1649.     Actual_Row  : RowIndex ;
  1650.     Temp_Row    : RowIndex ;
  1651.     Found_Pivot : Boolean ;
  1652. begin
  1653.  
  1654.     if (M.Row_Size /= M.Col_Size) then
  1655.        raise Matrix_Mismatch_Error;
  1656.     end if;
  1657.  
  1658.     for I in Permut'Range loop
  1659.       Permut(I) := I;
  1660.     end loop;
  1661.  
  1662.     for IJ in 1..M.Col_Size loop
  1663.       Pivot := 0.0;
  1664.       Found_Pivot := False;
  1665.  
  1666.           -- Search for Pivot Point in Column IJ
  1667.       for I in IJ .. M.Row_Size loop
  1668.         Temp := Abs(Local.Mat(Permut(I) , IJ));
  1669.         if Temp > Pivot then
  1670.            Pivot := Temp;
  1671.            Virtual_Row := i;
  1672.            Found_Pivot := True;
  1673.         end if;
  1674.       end loop;
  1675.  
  1676.            -- Check for zero Pivot
  1677.       if Found_Pivot then
  1678.          Pivot := Local.Mat(Permut(Virtual_Row) , IJ);
  1679.       end if;
  1680.       if (Abs(Pivot) < 1.0E-7 ) then
  1681.           raise Matrix_Inversion_Error; 
  1682.       end if;
  1683.  
  1684.  
  1685.            -- Do a Virtual Swapping of Rows by swapping Permut array.
  1686.  
  1687.       if Found_Pivot then
  1688.          Temp_Row := Permut(IJ);
  1689.          Permut(IJ) := Permut(Virtual_Row);
  1690.          Permut(Virtual_Row) := Temp_Row;
  1691.       end if;
  1692.  
  1693.             -- Get the actual row of Local.Mat of the new pivot( now
  1694.             --     the virtual row of 'IJ'
  1695.       Actual_Row := Permut(IJ);
  1696.  
  1697.             -- Divide pivot row by Pivot value.
  1698.                           -- (Note: items to left of IJ are Zero!)
  1699.       for Run_Col  in IJ.. Local.Col_Size loop
  1700.          Temp := Local.Mat(Actual_Row,Run_Col);
  1701.          Local.Mat(Actual_Row,Run_Col) := Temp / Pivot;
  1702.       end loop;
  1703.  
  1704.       for Run_Col in 1.. Local.Col_Size loop
  1705.          Temp := Unit.Mat(Actual_Row,Run_Col);
  1706.          Unit.Mat(Actual_Row,Run_Col) := Temp / Pivot;
  1707.       end loop;
  1708.  
  1709.             -- Zero out current column except for actual pivot row
  1710.       for Run_Row in 1.. Local.Row_Size loop
  1711.          if Run_Row = Actual_Row then
  1712.              null;
  1713.          else
  1714.             Norm := Local.Mat( Run_Row , IJ);
  1715.             if Norm = 0.0 then
  1716.                null;
  1717.             else
  1718.                for Run_Col in IJ .. Local.Col_Size loop
  1719.                   Temp := Local.Mat(Run_Row,Run_Col);
  1720.                   Local.Mat(Run_Row,Run_Col) :=  Temp - Norm *
  1721.                                      Local.Mat(Actual_Row,Run_Col);
  1722.                end loop;
  1723.                for Run_Col in 1 .. Local.Col_Size loop
  1724.                   Temp := Unit.Mat(Run_Row,Run_Col);
  1725.                   Unit.Mat(Run_Row,Run_Col) := Temp - Norm *
  1726.                              Unit.Mat(Actual_Row,Run_Col);
  1727.                end loop;
  1728.             end if;
  1729.          end if;
  1730.       end loop;
  1731.  
  1732.               -- Unit Matrix now has inverse of Local.Mat. Copy
  1733.               -- Unit.Mat into Unitary matrix with re-indexing.
  1734.  
  1735.       Unitary := (Unit.Row_Size,Unit.Col_Size,(others=>(others=>0.0)));
  1736.       for Row in 1.. M.Row_Size loop
  1737.          Actual_Row := Permut(Row);
  1738.          for Col in 1..M.Col_Size loop
  1739.            Unitary.Mat(Row,Col) := Unit.Mat(Actual_Row,Col);
  1740.          end loop;
  1741.      end loop;
  1742.    end loop;
  1743.    return Unitary  ;
  1744. end Invert_Mat;
  1745.  
  1746.  
  1747. end Gen_Dyn_Mat;
  1748. with Network_Parameters; use Network_Parameters;
  1749. --**********************************************
  1750. package Global_Types is
  1751. --==============================================================
  1752. --     Defines Constants and Types used globally in QSAP system. 
  1753. --==============================================================
  1754.  
  1755.   Nth_Order : constant Natural := Max_Moment_Order;
  1756.  
  1757.   Max_Index : constant Natural  :=Max_Index_Size;   
  1758.  
  1759.   subtype NumNodes         is Integer   range 0..Max_Index ;
  1760.   subtype NumJobs          is Integer   range 0..Max_Index ;
  1761.   subtype JobIndex         is Integer   range 1..Max_Index + 1;
  1762.   subtype NumErlangStages  is Integer   range 1..Integer'Last;
  1763.   subtype NumCoxianStages  is Integer   range 1..Max_Coxian_Stages;
  1764.   subtype NumServers       is Integer   range 1.. NumJobs'Last;
  1765.   subtype NumMoments       is Integer   range 1.. Nth_Order;
  1766.  
  1767.   type Real             is digits Max_Float_Digits;
  1768.   subtype MIndex is Natural range 0..Max_Index + 1;
  1769.  
  1770.   subtype ExponRate        is Real  range 1.0E-5 .. Real'Last;
  1771.   subtype ErlangRate       is Real  range 1.0E-5 .. Real'Last;
  1772.   subtype CoxianRate       is Real  range 1.0E-5 .. Real'Last;
  1773.   subtype Probs            is Real digits 3  range 0.0 .. 1.0;
  1774.   subtype MomentValue   is Real ;
  1775.  
  1776.   type CoxianRates  is array (NumCoxianStages range <>) of CoxianRate;
  1777.   type ContinProbs  is array (NumCoxianStages range <>) of Probs;
  1778.   type NodeMoments  is array (NumMoments range <>) of MomentValue;
  1779.   type ServDist     is (Exponential, Erlang, Coxian);
  1780.   type ServMode     is (FCFS, P_Share, PR_LCFS, NQ);
  1781.  
  1782.   function Map (Ith_Job : NumJobs) return JobIndex;
  1783.   --==================Note===========================================
  1784.   -- Many Modules require a matrix where the Column index(NumJobs) 
  1785.   -- must have a range from 0 .. NumJobs'Last. However, the indices in
  1786.   -- RealMatrix have a range 1 .. NumJobs'Last+1. Function Map provides
  1787.   -- this transformation.  Mat(I,Map(Ith_Job)) --> Mat(I, Ith_Job+1). 
  1788.   --=================================================================
  1789.  
  1790.   subtype NodeName is String(1..15);
  1791.  
  1792.   type CoxianDist  (Num_Coxian_Stages: NumCoxianStages :=
  1793.                                        NumCoxianStages'First) is
  1794.      record
  1795.         Contin_Probs: ContinProbs (NumCoxianStages'First ..
  1796.                                    Num_Coxian_Stages);
  1797.         Coxian_Rates: CoxianRates (NumCoxianStages'First ..
  1798.                                    Num_Coxian_Stages);
  1799.      end record;
  1800.  
  1801.   type ServFunct (Serv_Dist:  ServDist
  1802.                               := ServDist'First) is
  1803.      record
  1804.         case Serv_Dist is
  1805.            when Exponential     =>
  1806.               Expon_Rate        : ExponRate;
  1807.            when Erlang          =>
  1808.               Num_Erlang_Stages : NumErlangStages;
  1809.               Erlang_Rate       : ErlangRate;
  1810.            when Coxian          =>
  1811.               Coxian_Dist       : CoxianDist;
  1812.         end case;
  1813.      end record;
  1814.   
  1815.   type ServDisc is
  1816.      record
  1817.         Serv_Mode     : ServMode;
  1818.         Num_Servers   : NumServers;
  1819.         Serv_Funct    : ServFunct;       
  1820.      end record;
  1821.  
  1822. end Global_Types;
  1823.  
  1824.  
  1825. package body Global_Types is
  1826.    function Map ( Ith_Job : NumJobs) return JobIndex is
  1827.    begin
  1828.      return JobIndex(Ith_Job + 1);
  1829.    end Map;
  1830. end Global_Types;
  1831. with Global_types;
  1832. with Gen_Text_Handler;
  1833. package TEXT_HANDLER is new GEN_TEXT_HANDLER(Global_Types.Real);
  1834.  
  1835. with Gen_Dyn_Mat;
  1836. with Global_Types;use Global_Types;
  1837. --***********************************************
  1838. package Real_Mat_Pak is
  1839. --=============================================================
  1840. --     Exports a RealVector and RealMatrix which are dynamic vectors
  1841. --     and matrices whose indices are of type MIndex and whose 
  1842. --     components are of type Real(as defined in package Global_types). 
  1843. --     Useful DynMatrix and DynVectors operators defined in Gen_Dyn_Mat
  1844. --     are also made visible(exported). 
  1845. --=============================================================
  1846.    package Mat_Pak is new Gen_Dyn_Mat(
  1847.                           Global_Types.Real, Global_Types.Mindex);
  1848.    type    Vector  is  new Mat_Pak.Vect; 
  1849.    type    Matrix  is  new Mat_Pak.Matrx; 
  1850.  
  1851.    type RealVector is  new Mat_Pak.DynVector;
  1852.    type RealMatrix is  new Mat_Pak.DynMatrix;
  1853.  
  1854.     -- ******************* DynVector Primitives  **************
  1855.    function Allocate (Size : Mindex) return RealVector
  1856.                            renames Real_Mat_Pak.Allocate;
  1857.  
  1858.    function Value_Of(DV:RealVector; At_Index: Mindex) return Real
  1859.                            renames Real_Mat_Pak.Value_Of;
  1860.  
  1861.    function Last_Index_Of(DV:RealVector) return Mindex
  1862.                            renames Real_Mat_Pak.Last_Index_Of;
  1863.  
  1864.    function Real_Vector_Of(V:Vector) return RealVector;
  1865.  
  1866.    function Vector_Of(DV:RealVector) return Vector;
  1867.  
  1868.    procedure Assign(DV       : in out RealVector;  
  1869.                     At_Index : Mindex ; 
  1870.                     Value    : Real) renames Real_Mat_Pak.Assign;
  1871.  
  1872.    function Allocate(Row_Size , Col_Size : Mindex) return RealMatrix
  1873.                            renames Real_Mat_Pak.Allocate;
  1874.  
  1875.    function Value_Of(DM : RealMatrix ;
  1876.                       At_Row, At_Col : Mindex) return Real
  1877.                            renames Real_Mat_Pak.Value_Of;
  1878.  
  1879.    function Last_Row_Of(DM : RealMatrix) return Mindex
  1880.                            renames Real_Mat_Pak.Last_Row_Of;
  1881.  
  1882.    function Last_Col_Of(DM : RealMatrix) return Mindex
  1883.                            renames Real_Mat_Pak.Last_Col_Of;
  1884.  
  1885.    function Real_Matrix_Of(M : Matrix) return RealMatrix;
  1886.  
  1887.    function Matrix_Of(DM : RealMatrix) return Matrix;
  1888.  
  1889.    procedure Assign( DM             : in out RealMatrix;
  1890.                      At_Row, At_Col : Mindex;
  1891.                      Value          : Real) 
  1892.                       renames Real_Mat_Pak.Assign;
  1893. --****************************** Matrix Library **************
  1894.  
  1895. --          **** Vector Operations **** 
  1896.  
  1897.       function Vectors_OK      (V1,V2: RealVector)      return Boolean
  1898.                            renames Real_Mat_Pak.Vectors_Ok;
  1899.  
  1900.       function "*"  (I : Integer ; V : RealVector) return RealVector
  1901.                            renames Real_Mat_Pak."*";
  1902.  
  1903.       function "*"  (R : Real; V : RealVector) return RealVector
  1904.                            renames Real_Mat_Pak."*";
  1905.  
  1906.       function "+"  (V1,V2: RealVector)      return RealVector
  1907.                            renames Real_Mat_Pak."+";
  1908.  
  1909.       function "-"  (V:     RealVector)      return RealVector
  1910.                            renames Real_Mat_Pak."-";
  1911.  
  1912.       function "-"  (V1,V2: RealVector)      return RealVector
  1913.                            renames Real_Mat_Pak."-";
  1914.  
  1915.       function Dot  (V1,V2: RealVector)      return Real
  1916.                            renames Real_Mat_Pak.Dot;
  1917.  
  1918.       function Sum_Vec     (V:     RealVector)      return Real
  1919.                            renames Real_Mat_Pak.Sum_Vec;
  1920.  
  1921.       function Make_Mat    (V:     RealVector;
  1922.                            Dim:   Positive)       return RealMatrix;
  1923.    -- **********   MATRIX operations   **********
  1924.  
  1925.       function Mat_Multiply_OK (M1,M2: RealMatrix) return Boolean
  1926.                            renames Real_Mat_Pak.Mat_Multiply_Ok;
  1927.  
  1928.       function Mat_Match  (M1,M2: RealMatrix) return Boolean
  1929.                            renames Real_Mat_Pak.Mat_Match;
  1930.  
  1931.       function "*"    (I : Integer ; M : RealMatrix) return RealMatrix
  1932.                            renames Real_Mat_Pak."*";
  1933.  
  1934.       function "*"    (R : Real; M : RealMatrix) return RealMatrix
  1935.                            renames Real_Mat_Pak."*";
  1936.  
  1937.       function "+"    (M1,M2: RealMatrix) return RealMatrix
  1938.                            renames Real_Mat_Pak."+";
  1939.  
  1940.       function "-"    (M:     RealMatrix) return RealMatrix
  1941.                            renames Real_Mat_Pak."-";
  1942.  
  1943.       function "*"    (M1,M2: RealMatrix) return RealMatrix
  1944.                            renames Real_Mat_Pak."*";
  1945.  
  1946.       function "-"    (M1,M2: RealMatrix) return RealMatrix
  1947.                            renames Real_Mat_Pak."-";
  1948.  
  1949.       function Transpose_Mat   (M: RealMatrix) return RealMatrix
  1950.                            renames Real_Mat_Pak.Transpose_Mat;
  1951.  
  1952.       function Sum_Mat_By_Row  (M: RealMatrix; Row: Mindex) return Real
  1953.                            renames Real_Mat_Pak.Sum_Mat_By_Row;
  1954.  
  1955.       function Sum_Mat_By_Col  (M: RealMatrix; Col: Mindex) return Real
  1956.                            renames Real_Mat_Pak.Sum_Mat_By_Col;
  1957.       function Extract_Row     (M:   RealMatrix;
  1958.                                 Row: Mindex)     return RealVector;
  1959.  
  1960.       function Extract_Col     (M:   RealMatrix;
  1961.                                 Col: Mindex)     return RealVector;
  1962.  
  1963.       procedure Replace_Row (In_Mat : in out RealMatrix; Row : Mindex; 
  1964.                              Value : in RealVector); 
  1965.  
  1966.       procedure Replace_Col (In_Mat : in out RealMatrix; Col : Mindex; 
  1967.                              Value : in RealVector); 
  1968.  
  1969.  
  1970.       function Unit_Mat (Size: Mindex)    return RealMatrix
  1971.                            renames Real_Mat_Pak.Unit_Mat;
  1972.  
  1973.       function Invert_Mat  (M: in  RealMatrix) return RealMatrix
  1974.                            renames Real_Mat_Pak.Invert_Mat;
  1975.  
  1976.    -- **********   MATRIX and VECTOR operations   **********
  1977.  
  1978.       function Vec_Mat_OK      (V:   RealVector;
  1979.                                 M:   RealMatrix) return Boolean;
  1980.  
  1981.       function Mat_Vec_OK      (M:   RealMatrix;
  1982.                                 V:   RealVector) return Boolean;
  1983.  
  1984.       function "*"             (V:   RealVector;
  1985.                                 M:   RealMatrix) return RealVector;
  1986.  
  1987.       function "*"             (M:   RealMatrix;
  1988.                                 V:   RealVector) return RealVector;
  1989.     
  1990.       Matrix_Inversion_Error : exception renames 
  1991.                                     Mat_Pak.Matrix_Inversion_Error;
  1992.       Matrix_Mismatch_Error  : exception renames 
  1993.                                     Mat_Pak.Matrix_Mismatch_Error;
  1994.  
  1995.  
  1996. end Real_Mat_Pak;
  1997.  
  1998. package body Real_Mat_Pak is
  1999.    use Mat_Pak;
  2000.  
  2001.    function Real_Vector_Of(V:Vector) return RealVector is 
  2002.    begin
  2003.         return RealVector(Mat_Pak.Dyn_Vector_Of(Vect(V)));
  2004.    end Real_Vector_Of;
  2005.  
  2006.    function Vector_Of(DV:RealVector) return Vector is 
  2007.    begin
  2008.         return Vector(Mat_Pak.Vector_Of(DynVector(DV)));
  2009.    end Vector_Of;
  2010.    
  2011.    function Real_Matrix_Of(M : Matrix) return RealMatrix is 
  2012.    begin
  2013.       return RealMatrix(Mat_Pak.Dyn_Matrix_Of(Matrx(M)));
  2014.    end Real_Matrix_Of;
  2015.  
  2016.    function Matrix_Of(DM : RealMatrix) return Matrix is 
  2017.    begin
  2018.       return Matrix(Mat_Pak.Matrix_Of(DynMatrix(DM)));
  2019.    end Matrix_Of;
  2020.  
  2021.    function Make_Mat  (V:     RealVector;
  2022.                        Dim:   Positive)  return RealMatrix is
  2023.    begin
  2024.       return RealMatrix(Mat_Pak.Make_Mat( DynVector(V) , Dim));
  2025.    end Make_Mat;
  2026.  
  2027.  
  2028.   function Extract_Row    (M  : RealMatrix;
  2029.                            Row: Mindex)     return RealVector is 
  2030.   begin
  2031.      return RealVector(Mat_Pak.Extract_Row( DynMatrix(M),Row));
  2032.   end Extract_Row;
  2033.  
  2034.   function Extract_Col     (M  : RealMatrix;
  2035.                             Col: Mindex)     return RealVector is 
  2036.   begin
  2037.      return RealVector(Mat_Pak.Extract_Col( DynMatrix(M), Col));
  2038.   end Extract_Col;
  2039.        
  2040.  
  2041.   procedure Replace_Row (In_Mat : in out RealMatrix; Row : Mindex; 
  2042.                           Value : in RealVector) is 
  2043.   begin
  2044.      Replace_Row(In_Mat, Row, DynVector(Value));
  2045.   end Replace_Row;
  2046.  
  2047.   procedure Replace_Col (In_Mat : in out RealMatrix; Col : Mindex; 
  2048.                           Value : in RealVector)  is
  2049.   begin  
  2050.      Replace_Col(In_Mat, Col, DynVector(Value));
  2051.   end Replace_Col;
  2052.  
  2053.   function Vec_Mat_OK      (V:   RealVector;
  2054.                             M:   RealMatrix) return Boolean is 
  2055.   begin
  2056.      return Vec_Mat_OK(DynVector(V),M);
  2057.   end Vec_Mat_OK;
  2058.  
  2059.   function Mat_Vec_OK      (M:   RealMatrix;
  2060.                             V:   RealVector) return Boolean is
  2061.   begin
  2062.      return Mat_Vec_OK(M,DynVector(V));
  2063.   end Mat_Vec_OK;
  2064.  
  2065.   function "*"             (V:   RealVector;
  2066.                             M:   RealMatrix) return RealVector is 
  2067.   begin
  2068.      return RealVector(DynVector(V) * M);
  2069.   end "*"; 
  2070.  
  2071.   function "*"             (M:   RealMatrix;
  2072.                             V:   RealVector) return RealVector is 
  2073.   begin
  2074.      return RealVector(M * DynVector(V));
  2075.   end "*"; 
  2076.  
  2077. end Real_Mat_Pak;
  2078. --  The following is a series of complete and machine-independent,
  2079. --  but not necessarily efficient, packages which, if compiled in order,
  2080. --  will provide the elementary functions required by some benchmarks
  2081. --*********************************
  2082. package FLOATING_CHARACTERISTICS is
  2083. --================MACHINE INDEPENDENT FLOATING POINT=================
  2084. --  This package is a floating mantissa definition of a binary FLOAT 
  2085. --  This is a preliminary package that defines the properties 
  2086. --  of the particular floating point type for which we are going to
  2087. --  generate the math routines
  2088. --  The constants are those required by the routines described in
  2089. --  "Software Manual for the Elementary Functions" W. Cody & W. Waite
  2090. --  Prentice-Hall 1980
  2091. --  rather than the functions themselves, but might as well be here
  2092. --  Most of these could be in the form of attributes if 
  2093. --  all the floating types to be considered were those built into the
  2094. --  compiler, but we also want to be able to support user defined types
  2095. --  such as software floating types of greater precision than
  2096. --  the hardware affords, or types defined on one machine to
  2097. --  simulate another
  2098. --  So we use the Cody-Waite names and derive them from an adaptation of the
  2099. --  MACHAR routine as given by Cody-Waite in Appendix B
  2100. --=====================================================================
  2101.  
  2102.     IBETA : INTEGER;
  2103.     --  The radix of the floating-point representation
  2104.  
  2105.     IT : INTEGER;
  2106.     --  The number of base IBETA digits in the DIS_FLOAT significand
  2107.  
  2108.     IRND : INTEGER;
  2109.     --  TRUE (1) if floating addition rounds, FALSE (0) if truncates
  2110.  
  2111.     NGRD : INTEGER;
  2112.     --  Number of guard digits for multiplication
  2113.  
  2114.     MACHEP : INTEGER;
  2115.     --  The largest negative integer such that
  2116.     --    1.0 + FLOAT(IBETA) ** MACHEP /= 1.0
  2117.     --  except that MACHEP is bounded below by -(IT + 3)
  2118.  
  2119.     NEGEP : INTEGER;
  2120.     --  The largest negative integer such that
  2121.     --    1.0 -0 FLOAT(IBETA) ** NEGEP /= 1.0
  2122.     --  except that NEGEP is bounded below by -(IT + 3)
  2123.  
  2124.     IEXP : INTEGER;
  2125.     --  The number of bits (decimal places if IBETA = 10)
  2126.     --  reserved for the representation of the exponent (including
  2127.     --  the bias or sign) of a floating-point number
  2128.  
  2129.     MINEXP : INTEGER;
  2130.     --  The largest in magnitude negative integer such that
  2131.     --  FLOAT(IBETA) ** MINEXP is a positive floating-point number
  2132.  
  2133.  
  2134.     MAXEXP : INTEGER;
  2135.     --  The largest positive exponent for a finite floating-point number
  2136.  
  2137.     EPS : FLOAT;
  2138.     --  The smallest positive floating-point number such that
  2139.     --                              1.0 + EPS /= 1.0
  2140.     --  In particular, if IBETA = 2 or IRND = 0,
  2141.     --  EPS = FLOAT(IBETA) ** MACHEP
  2142.     --  Otherwise, EPS = (FLOAT(IBETA) ** MACHEP) / 2
  2143.  
  2144.  
  2145.     EPSNEG : FLOAT;
  2146.     --  A small positive floating-point number such that 1.0-EPSNEG /= 1.0
  2147.  
  2148.     XMIN : FLOAT;
  2149.     --  The smallest non-vanishing floating-point power of the radix
  2150.     --  In particular, XMIN = FLOAT(IBETA) ** MINEXP
  2151.  
  2152.     XMAX : FLOAT;
  2153.     --  The largest finite floating-point number
  2154.  
  2155. --  Here the structure of the floating type is defined
  2156. --  I have assumed that the exponent is always some integer form
  2157. --  The mantissa can vary
  2158. --  Most often it will be a fixed type or the same floating type
  2159. --  depending on the most efficient machine implementation
  2160. --  Most efficient implementation may require details of the machine hardware
  2161. --  In this version the simplest representation is used
  2162. --  The mantissa is extracted into a FLOAT and uses the predefined operations
  2163.   type EXPONENT_TYPE is new INTEGER;    --  should be derived  ##########
  2164.   subtype MANTISSA_TYPE is FLOAT;     --   range -1.0..1.0;
  2165. --  A consequence of the rigorous constraints on MANTISSA_TYPE is that
  2166. --  operations must be very carefully examined to make sure that no number
  2167. --  greater than one results
  2168. --  Actually this limitation is important in constructing algorithms
  2169. --  which will also run when MANTISSA_TYPE is a fixed point type
  2170.  
  2171. --  If we are not using the STANDARD type, we have to define all the 
  2172. --  operations at this point
  2173. --  We also need PUT for the type if it is not otherwise available
  2174.  
  2175. --  Now we do something strange
  2176. --  Since we do not know in the following routines whether the mantissa
  2177. --  will be carried as a fixed or floating type, we have to make some
  2178. --  provision for dividing by two
  2179. --  We cannot use the literals, since FIXED/2.0 and FLOAT/2 will fail
  2180. --  We define a type-dependent factor that will work
  2181.   MANTISSA_DIVISOR_2 : constant FLOAT := 2.0;
  2182.   MANTISSA_DIVISOR_3 : constant FLOAT := 3.0;
  2183. --  This will work for the MANTISSA_TYPE defined above
  2184. --  The alternative of defining an operation "/" to take care of it
  2185. --  is too sweeping and would allow unAda-like errors
  2186.  
  2187.   MANTISSA_HALF : constant MANTISSA_TYPE := 0.5;
  2188.  
  2189.  
  2190.   procedure DEFLOAT(X : in FLOAT;
  2191.                     N : in out EXPONENT_TYPE; F : in out MANTISSA_TYPE);
  2192.   procedure REFLOAT(N : in EXPONENT_TYPE; F : in MANTISSA_TYPE;
  2193.                                                    X : in out FLOAT);
  2194. --  Since the user may wish to define a floating type by some other name
  2195. --  CONVERT_TO_FLOAT is used rather than just FLOAT for explicit coersion
  2196.   function CONVERT_TO_FLOAT(K : INTEGER) return FLOAT;
  2197.   function CONVERT_TO_FLOAT(N : EXPONENT_TYPE) return FLOAT;
  2198.   function CONVERT_TO_FLOAT(F : MANTISSA_TYPE) return FLOAT;
  2199.  
  2200. end FLOATING_CHARACTERISTICS;
  2201. with TEXT_IO; use TEXT_IO;
  2202. package body FLOATING_CHARACTERISTICS is
  2203. --  This package is a floating mantissa definition of a binary FLOAT
  2204.  
  2205.     A, B, Y, Z : FLOAT;
  2206.     I, K, MX, IZ : INTEGER;
  2207.     BETA, BETAM1, BETAIN : FLOAT;
  2208.     ONE : FLOAT := 1.0;
  2209.     ZERO : FLOAT := 0.0;
  2210.  
  2211.   procedure DEFLOAT(X : in FLOAT;
  2212.                     N : in out EXPONENT_TYPE; F : in out MANTISSA_TYPE) is
  2213. --  This is admittedly a slow method - but portable - for breaking down
  2214. --  a floating point number into its exponent and mantissa
  2215. --  Obviously with knowledge of the machine representation
  2216. --  it could be replaced with a couple of simple extractions
  2217.     EXPONENT_LENGTH : INTEGER := IEXP;
  2218.     M : EXPONENT_TYPE;
  2219.     W, Y, Z : FLOAT;
  2220.   begin
  2221.     N := 0;
  2222.     F := 0.0;
  2223.     Y := ABS(X);
  2224.     if Y = 0.0  then
  2225.       return;
  2226.     elsif Y < 0.5  then
  2227.       for J in reverse 0..(EXPONENT_LENGTH - 2)  loop
  2228.       --  Dont want to go all the way to 2.0**(EXPONENT_LENGTH - 1)
  2229.       --  Since that (or its reciprocal) will overflow if exponent biased
  2230.       --  Ought to use talbular values rather than compute each time
  2231.         M := EXPONENT_TYPE(2 ** J);
  2232.         Z := 1.0 / (2.0**integer (M));
  2233.         W := Y / Z;
  2234.         if W < 1.0  then
  2235.           Y := W;
  2236.           N := N - M;
  2237.         end if;
  2238.       end loop;
  2239.     else
  2240.       for J in reverse 0..(EXPONENT_LENGTH - 2)  loop
  2241.         M := EXPONENT_TYPE(2 ** J);
  2242.         Z := 2.0**integer (M);
  2243.         W := Y / Z;
  2244.         if W >= 0.5  then
  2245.           Y := W;
  2246.           N := N + M;
  2247.         end if;
  2248.       end loop;
  2249.     --  And just to clear up any loose ends from biased exponents
  2250.     end if;
  2251.     while Y < 0.5  loop
  2252.       Y := Y * 2.0;
  2253.       N := N - 1;
  2254.     end loop;
  2255.     while Y >= 1.0  loop
  2256.       Y := Y / 2.0;
  2257.       N := N + 1;
  2258.     end loop;
  2259.     F := MANTISSA_TYPE(Y);
  2260.     if X < 0.0  then
  2261.       F := -F;
  2262.     end if;
  2263.     return;
  2264.   exception
  2265.   when others =>
  2266.     N := 0;
  2267.     F := 0.0;
  2268.     return;
  2269.   end DEFLOAT;
  2270.  
  2271.  
  2272.   procedure REFLOAT(N : in EXPONENT_TYPE; F : in MANTISSA_TYPE; 
  2273.                                                    X : in out FLOAT) is
  2274. --  Again a brute force method - but portable
  2275. --  Watch out near MAXEXP
  2276.     M : INTEGER;
  2277.     Y : FLOAT;
  2278.   begin
  2279.     if F = 0.0  then
  2280.       X := ZERO;
  2281.       return;
  2282.     end if;
  2283.     M := INTEGER(N);
  2284.     Y := ABS(FLOAT(F));
  2285.     while Y < 0.5  loop
  2286.       M := M - 1;
  2287.       if M < MINEXP  then
  2288.         X := ZERO;
  2289.       end if;
  2290.       Y := Y + Y;
  2291.       exit when M <= MINEXP;
  2292.     end loop;
  2293.     if M = MAXEXP  then
  2294.       M := M - 1;
  2295.       X := Y * 2.0**M;
  2296.       X := X * 2.0;
  2297.     elsif M <= MINEXP + 2  then
  2298.       M := M + 3;
  2299.       X := Y * 2.0**M;
  2300.       X := ((X / 2.0) / 2.0) / 2.0;
  2301.     else
  2302.       X := Y * 2.0**M;
  2303.     end if;
  2304.     if F < 0.0  then
  2305.       X := -X;
  2306.     end if;
  2307.     return;
  2308.   end REFLOAT;
  2309.  
  2310.   function CONVERT_TO_FLOAT(K : INTEGER) return FLOAT is
  2311.   begin
  2312.     return FLOAT(K);
  2313.   end CONVERT_TO_FLOAT;
  2314.  
  2315.   function CONVERT_TO_FLOAT(N : EXPONENT_TYPE) return FLOAT is
  2316.   begin
  2317.     return FLOAT(N);
  2318.   end CONVERT_TO_FLOAT;
  2319.  
  2320.   function CONVERT_TO_FLOAT(F : MANTISSA_TYPE) return FLOAT is
  2321.   begin
  2322.     return FLOAT(F);
  2323.   end CONVERT_TO_FLOAT;
  2324.  
  2325.  
  2326. begin--  Initialization for the VAX with values derived by MACHAR
  2327. --  In place of running MACHAR as the actual initialization
  2328.  
  2329. --  IBETA :=    2;
  2330. --  IT :=    24;
  2331. --  IRND :=    1;
  2332. --  NEGEP :=    -24;
  2333. --  EPSNEG :=    5.9604644E-008;
  2334. --  MACHEP :=    -24;
  2335. --  EPS :=    5.9604644E-008;
  2336. --  NGRD :=    0;
  2337. --  XMIN := 5.9E-39;
  2338. --  MINEXP :=    -126;
  2339. --  IEXP :=    8;
  2340. --  MAXEXP :=    127;
  2341. --  XMAX :=    8.5E37 * 2.0;
  2342.  
  2343.  
  2344. ----  This initialization is the MACHAR routine of Cody and Waite Appendix B.
  2345. --  PUT("INITIALIZATING WITH MACHAR     -     ");
  2346.       A := ONE;
  2347.       while (((A + ONE) - A) - ONE) = ZERO  loop
  2348.         A := A + A;
  2349.       end loop;
  2350.       B := ONE;
  2351.       while ((A + B) - A) = ZERO  loop
  2352.         B := B + B;
  2353.       end loop;
  2354.       IBETA := INTEGER((A + B) - A);
  2355.       BETA := CONVERT_TO_FLOAT(IBETA);
  2356.  
  2357.  
  2358.       IT := 0;
  2359.       B := ONE;
  2360.       while (((B + ONE) - B) - ONE) = ZERO  loop
  2361.         IT := IT + 1;
  2362.         B := B * BETA;
  2363.       end loop;
  2364.  
  2365.  
  2366.       IRND := 0;
  2367.       BETAM1 := BETA - ONE;
  2368.       if ((A + BETAM1) - A) /= ZERO  then
  2369.         IRND := 1;
  2370.       end if;
  2371.  
  2372.  
  2373.       NEGEP := IT + 3;
  2374.       BETAIN := ONE / BETA;
  2375.       A := ONE;
  2376.         for I in 1..NEGEP  loop
  2377. --  for I in 1..50  loop
  2378. --  exit when I > NEGEP;
  2379.         A := A * BETAIN;
  2380.       end loop;
  2381.       B := A;
  2382.       while ((ONE - A) - ONE) = ZERO  loop
  2383.         A := A * BETA;
  2384.         NEGEP := NEGEP - 1;
  2385.       end loop;
  2386.       NEGEP := -NEGEP;
  2387.  
  2388.  
  2389.       EPSNEG := A;
  2390.       if (IBETA /= 2) and (IRND /= 0)  then
  2391.         A := (A * (ONE + A)) / (ONE + ONE);
  2392.         if ((ONE - A) - ONE) /= ZERO  then
  2393.           EPSNEG := A;
  2394.         end if;
  2395.       end if;
  2396.  
  2397.  
  2398.       MACHEP := -IT - 3;
  2399.       A := B;
  2400.       while ((ONE + A) - ONE) = ZERO  loop
  2401.         A := A * BETA;
  2402.         MACHEP := MACHEP + 1;
  2403.       end loop;
  2404.  
  2405.  
  2406.       EPS := A;
  2407.       if (IBETA /= 2) and (IRND /= 0)  then
  2408.         A := (A * (ONE + A)) / (ONE + ONE);
  2409.         if ((ONE + A) - ONE) /= ZERO  then
  2410.           EPS := A;
  2411.         end if;
  2412.       end if;
  2413.  
  2414.  
  2415.       NGRD := 0;
  2416.       if ((IRND = 0) and ((ONE + EPS) * ONE - ONE) /= ZERO)  then
  2417.         NGRD := 1;
  2418.       end if;
  2419.  
  2420.  
  2421.       I := 0;
  2422.       K := 1;
  2423.       Z := BETAIN;
  2424.       loop
  2425.         Y := Z;
  2426.         Z := Y * Y;
  2427.         A := Z * ONE;
  2428.         exit when ((A + A) = ZERO) or (ABS(Z) >= Y);
  2429.         I := I + 1;
  2430.         K := K + K;
  2431.       end loop;
  2432.       if (IBETA /= 10)  then
  2433.         IEXP := I + 1;
  2434.         MX := K + K;
  2435.       else
  2436.         IEXP := 2;
  2437.         IZ := IBETA;
  2438.         while (K >= IZ)  loop
  2439.           IZ := IZ * IBETA;
  2440.           IEXP := IEXP + 1;
  2441.         end loop;
  2442.         MX := IZ + IZ - 1;
  2443.       end if;
  2444.  
  2445.       loop
  2446.         XMIN := Y;
  2447.         Y := Y * BETAIN;
  2448.         A := Y * ONE;
  2449.         exit when ((A + A) = ZERO) or (ABS(Y) >= XMIN);
  2450.         K := K + 1;
  2451.       end loop;
  2452.  
  2453.  
  2454.       MINEXP := -K;
  2455.  
  2456.  
  2457.       if ((MX <= (K + K - 3)) and (IBETA /= 10))  then
  2458.         MX := MX + MX;
  2459.         IEXP := IEXP + 1;
  2460.       end if;
  2461.  
  2462.  
  2463.       MAXEXP := MX + MINEXP;
  2464.       I := MAXEXP + MINEXP;
  2465.       if ((IBETA = 2) and (I = 0))  then
  2466.         MAXEXP := MAXEXP - 1;
  2467.       end if;
  2468.       if (I > 20)  then
  2469.         MAXEXP := MAXEXP - 1;
  2470.       end if;
  2471.       if (A /= Y)  then
  2472.         MAXEXP := MAXEXP - 2;
  2473.       end if;
  2474.  
  2475.  
  2476.       XMAX := ONE - EPSNEG;
  2477.       if ((XMAX * ONE) /= XMAX)  then
  2478.         XMAX := ONE - BETA * EPSNEG;
  2479.       end if;
  2480.       XMAX := XMAX / (BETA * BETA * BETA * XMIN);
  2481.       I := MAXEXP + MINEXP + 3;
  2482.       if I > 0  then
  2483.         for J in 1..50  loop
  2484.     exit when J > I;
  2485.           if IBETA = 2  then
  2486.             XMAX := XMAX + XMAX;
  2487.           else
  2488.             XMAX := XMAX * BETA;
  2489.           end if;
  2490.         end loop;
  2491.       end if;
  2492.  
  2493. --  PUT("INITIALIZED"); NEW_LINE;
  2494.  
  2495. end FLOATING_CHARACTERISTICS;
  2496. with TEXT_IO; use TEXT_IO;
  2497. package NUMERIC_IO is
  2498.  
  2499.   procedure GET(FILE : in FILE_TYPE; ITEM : out INTEGER);
  2500.   procedure GET(ITEM : out INTEGER);
  2501.   procedure GET(FILE : in FILE_TYPE; ITEM : out FLOAT);
  2502.   procedure GET(ITEM : out FLOAT);
  2503.   procedure PUT(FILE : in FILE_TYPE; ITEM : in INTEGER);
  2504.   procedure PUT(ITEM : in INTEGER; WIDTH : in FIELD);
  2505.   procedure PUT(ITEM : in INTEGER);
  2506.   procedure PUT(FILE : in FILE_TYPE; ITEM : in FLOAT);
  2507.   procedure PUT(ITEM : in FLOAT);
  2508.  
  2509. end NUMERIC_IO;
  2510.  
  2511.  
  2512. with TEXT_IO;
  2513. use TEXT_IO;
  2514. package body NUMERIC_IO is
  2515. -- This ought to be done by instantiating the FLoaT_IO and INTEGER_IO
  2516. --  But if you dont yet have the generic TEXT_IO implemented yet
  2517. --  then something like this does the job on the DEC-10 IAPC
  2518. --  But it is a kludge
  2519. --  No effort has been put into making it pretty or portable
  2520. package int_io is new text_io.integer_io (integer);
  2521. package flt_io is new text_io.float_io (float);
  2522. use INT_IO; use FLT_IO;
  2523.  
  2524.   procedure GET(FILE : in FILE_TYPE; ITEM : out INTEGER) is
  2525.   begin
  2526. INT_IO.GET(FILE, ITEM);
  2527.   end GET;
  2528.  
  2529.   procedure GET(ITEM : out INTEGER) is
  2530.   begin
  2531. INT_IO.GET(ITEM);
  2532.   end GET;
  2533.  
  2534.   procedure GET(FILE : in FILE_TYPE; ITEM : out FLOAT) is
  2535.   begin
  2536. FLT_IO.GET(FILE, ITEM);
  2537.   end GET;
  2538.  
  2539.   procedure GET(ITEM : out FLOAT) is
  2540.   begin
  2541. FLT_IO.GET(ITEM);
  2542.   end GET;
  2543.  
  2544.   procedure PUT(FILE : in FILE_TYPE; ITEM : in INTEGER) is
  2545.   begin
  2546. INT_IO.PUT(FILE, ITEM);
  2547.   end PUT;
  2548.  
  2549.   procedure PUT(ITEM : in INTEGER; WIDTH : in FIELD) is
  2550.     J, K, M : INTEGER := 0;
  2551.   begin
  2552.     if WIDTH = 1  then
  2553.       case ITEM is
  2554.         when 0  => PUT('0');
  2555.         when 1  => PUT('1');
  2556.         when 2  => PUT('2');
  2557.         when 3  => PUT('3');
  2558.         when 4  => PUT('4');
  2559.         when 5  => PUT('5');
  2560.         when 6  => PUT('6');
  2561.         when 7  => PUT('7');
  2562.         when 8  => PUT('8');
  2563.         when 9  => PUT('9');
  2564.         when others  => PUT('*');
  2565.       end case;
  2566.     else
  2567.       if ITEM < 0  then
  2568.         PUT('-');
  2569.         J := -ITEM;
  2570.       else
  2571.         PUT(' ');
  2572.         J := ITEM;
  2573.       end if;
  2574.       for I in 1..WIDTH-1  loop
  2575.         M := 10**(WIDTH - 1 - I);
  2576.         K := J / M;
  2577.         J := J - K*M;
  2578.         NUMERIC_IO.PUT(K, 1);
  2579.       end loop;
  2580.     end if;
  2581.   end PUT;
  2582.  
  2583.   procedure PUT(ITEM : in INTEGER) is
  2584.   begin
  2585. INT_IO.PUT(ITEM);
  2586.   end PUT;
  2587.  
  2588.   procedure PUT(FILE : in FILE_TYPE; ITEM : in FLOAT) is
  2589.   begin
  2590. FLT_IO.PUT(FILE, ITEM);
  2591.   end PUT;
  2592.  
  2593.   procedure PUT(ITEM : in FLOAT) is
  2594.   begin
  2595. FLT_IO.PUT(ITEM);
  2596.   end PUT;
  2597.  
  2598. end NUMERIC_IO;
  2599. with FLOATING_CHARACTERISTICS; use FLOATING_CHARACTERISTICS;
  2600. package NUMERIC_PRIMITIVES is
  2601.  
  2602.   --  This may seem a little much but is put in this form to allow the
  2603.   --  same form to be used for a generic package
  2604.   --  If that is not needed, simple litterals could be substituted
  2605.   ZERO  : FLOAT := CONVERT_TO_FLOAT(INTEGER(0));
  2606.   ONE   : FLOAT := CONVERT_TO_FLOAT(INTEGER(1));
  2607.   TWO   : FLOAT := ONE + ONE;
  2608.   THREE : FLOAT := ONE + ONE + ONE;
  2609.   HALF  : FLOAT := ONE / TWO;
  2610.  
  2611.   --  The following "constants" are effectively deferred to
  2612.   --  the initialization part of the package body
  2613.   --  This is in order to make it possible to generalize the floating type
  2614.   --  If that capability is not desired, constants may be included here
  2615.   PI            : FLOAT;
  2616.   ONE_OVER_PI   : FLOAT;
  2617.   TWO_OVER_PI   : FLOAT;
  2618.   PI_OVER_TWO   : FLOAT;
  2619.   PI_OVER_THREE : FLOAT;
  2620.   PI_OVER_FOUR  : FLOAT;
  2621.   PI_OVER_SIX   : FLOAT;
  2622.  
  2623.  
  2624.   function SIGN(X, Y : FLOAT) return FLOAT;
  2625.     --  Returns the value of X with the sign of Y
  2626.   function MAX(X, Y :  FLOAT) return FLOAT;
  2627.     --  Returns the algebraicly larger of X and Y
  2628.   function TRUNCATE(X : FLOAT) return FLOAT;
  2629.     --  Returns the floating value of the integer no larger than X
  2630.     --  AINT(X)
  2631.   function ROUND(X : FLOAT) return FLOAT;
  2632.     --  Returns the floating value nearest X
  2633.     --  AINTRND(X)
  2634.   function RAN return FLOAT;
  2635.     --  This uses a portable algorithm and is included at this point
  2636.     --  Algorithms that presume unique machine hardware information
  2637.     --  should be initiated in FLOATING_CHARACTERISTICS
  2638.  
  2639. end NUMERIC_PRIMITIVES;
  2640.  
  2641.  
  2642.  
  2643. with FLOATING_CHARACTERISTICS; use FLOATING_CHARACTERISTICS;
  2644. package body NUMERIC_PRIMITIVES is
  2645.  
  2646.  
  2647.   function SIGN(X, Y : FLOAT) return FLOAT is
  2648.     --  Returns the value of X with the sign of Y
  2649.   begin
  2650.     if Y >= 0.0  then
  2651.       return X;
  2652.     else
  2653.       return -X;
  2654.     end if;
  2655.   end SIGN;
  2656.  
  2657.   function MAX(X, Y : FLOAT) return FLOAT is
  2658.   begin
  2659.     if X >= Y  then
  2660.       return X;
  2661.     else
  2662.       return Y;
  2663.     end if;
  2664.   end MAX;
  2665.  
  2666.   function TRUNCATE(X : FLOAT) return FLOAT is
  2667.   --  Optimum code depends on how the system rounds at exact halves
  2668.   begin
  2669.     if FLOAT(INTEGER(X)) = X  then
  2670.       return X;
  2671.     end if;
  2672.     if X > ZERO  then
  2673.       return FLOAT(INTEGER(X - HALF));
  2674.     elsif X = ZERO  then
  2675.       return ZERO;
  2676.     else
  2677.       return FLOAT(INTEGER(X + HALF));
  2678.     end if;
  2679.   end TRUNCATE;
  2680.  
  2681.   function ROUND(X : FLOAT) return FLOAT is
  2682.   begin
  2683.     return FLOAT(INTEGER(X));
  2684.   end ROUND;
  2685.  
  2686.  
  2687.   package KEY is
  2688.     X : INTEGER := 10_001;
  2689.     Y : INTEGER := 20_001;
  2690.     Z : INTEGER := 30_001;
  2691.   end KEY;
  2692.  
  2693.   function RAN return FLOAT is
  2694.   --  This rectangular random number routine is adapted from a report
  2695.   --  "A Pseudo-Random Number Generator" by B. A. Wichmann and I. D. Hill
  2696.   --  NPL Report DNACS XX (to be published)
  2697.   --  In this stripped version, it is suitable for machines supporting 
  2698.   --  INTEGER at only 16 bits and is portable in Ada
  2699.     W : FLOAT;
  2700.   begin
  2701.  
  2702.     KEY.X := 171 * (KEY.X mod 177 - 177) -  2 * (KEY.X / 177);
  2703.     if KEY.X < 0  then
  2704.       KEY.X := KEY.X + 30269;
  2705.     end if;
  2706.  
  2707.     KEY.Y := 172 * (KEY.Y mod 176 - 176) - 35 * (KEY.Y / 176);
  2708.     if KEY.Y < 0  then
  2709.       KEY.Y := KEY.Y + 30307;
  2710.     end if;
  2711.  
  2712.     KEY.Z := 170 * (KEY.Z mod 178 - 178) - 63 * (KEY.Z / 178);
  2713.     if KEY.Z < 0  then
  2714.       KEY.Z := KEY.Z + 30323;
  2715.     end if;
  2716.  
  2717.     --  CONVERT_TO_FLOAT is used instead of FLOAT since the floating
  2718.     --  type may be software defined
  2719.  
  2720.     W :=     CONVERT_TO_FLOAT(KEY.X)/30269.0
  2721.            + CONVERT_TO_FLOAT(KEY.Y)/30307.0
  2722.            + CONVERT_TO_FLOAT(KEY.Z)/30323.0;
  2723.  
  2724.     return  W - CONVERT_TO_FLOAT(INTEGER(W - 0.5));
  2725.  
  2726.   end RAN;
  2727.  
  2728. begin
  2729.   PI            := CONVERT_TO_FLOAT(INTEGER(3)) +
  2730.                    CONVERT_TO_FLOAT(MANTISSA_TYPE(0.14159_26535_89793_23846));
  2731.   ONE_OVER_PI   := CONVERT_TO_FLOAT(MANTISSA_TYPE(0.31830_98861_83790_67154));
  2732.   TWO_OVER_PI   := CONVERT_TO_FLOAT(MANTISSA_TYPE(0.63661_97723_67581_34308));
  2733.   PI_OVER_TWO   := CONVERT_TO_FLOAT(INTEGER(1)) +
  2734.                    CONVERT_TO_FLOAT(MANTISSA_TYPE(0.57079_63267_94896_61923));
  2735.   PI_OVER_THREE := CONVERT_TO_FLOAT(INTEGER(1)) +
  2736.                    CONVERT_TO_FLOAT(MANTISSA_TYPE(0.04719_75511_96597_74615));
  2737.   PI_OVER_FOUR  := CONVERT_TO_FLOAT(MANTISSA_TYPE(0.78539_81633_97448_30962));
  2738.   PI_OVER_SIX   := CONVERT_TO_FLOAT(MANTISSA_TYPE(0.52359_87755_98298_87308));
  2739.  
  2740. end NUMERIC_PRIMITIVES;
  2741.  
  2742.  
  2743.  
  2744.  
  2745.  
  2746.  
  2747.  
  2748. with FLOATING_CHARACTERISTICS; use FLOATING_CHARACTERISTICS;
  2749.  
  2750. --************************
  2751. package CORE_FUNCTIONS is
  2752. --================================================
  2753. --      Machine independent basic Math functions.
  2754. --===============================================
  2755.  
  2756.   EXP_LARGE : FLOAT;
  2757.   EXP_SMALL : FLOAT;
  2758.  
  2759.   function SQRT(X : FLOAT) return FLOAT;
  2760.   function LOG10(X : FLOAT) return FLOAT;
  2761.   function EXP(X : FLOAT) return FLOAT;
  2762.   function "**"(X, Y : FLOAT) return FLOAT;
  2763.   function ATAN(X : FLOAT) return FLOAT;
  2764.  
  2765.   ill_neg_SQRT_used_abs,
  2766.   ill_SQRT_used_1,
  2767.   ill_neg_LOG_used_abs,
  2768.   ill_zero_LOG_val,
  2769.   ill_LOG_ret_zero,
  2770.   ill_large_val_EXP,
  2771.   ill_neg_val_EXP,
  2772.   ill_EXP_ret_one,
  2773.   ill_EXPONENT_used_abs,
  2774.   ill_EXPONENT_val,
  2775.   ill_large_val_EXPONENT,
  2776.   ill_small_val_EXPONENT : exception;
  2777.  
  2778. end CORE_FUNCTIONS;
  2779.  
  2780.  
  2781.  
  2782.  
  2783. with TEXT_IO; use TEXT_IO;
  2784. with FLOATING_CHARACTERISTICS; use FLOATING_CHARACTERISTICS;
  2785. with NUMERIC_IO; use NUMERIC_IO;
  2786. with NUMERIC_PRIMITIVES; use NUMERIC_PRIMITIVES;
  2787. package body CORE_FUNCTIONS is
  2788.  
  2789. --  The following routines are coded directly from the algorithms and
  2790. --  coeficients given in "Software Manual for the Elementry Functions"
  2791. --  by William J. Cody, Jr. and William Waite, Prentice_Hall, 1980
  2792. --  CBRT by analogy
  2793. --  A more general formulation uses MANTISSA_TYPE, etc.
  2794. --  The coeficients are appropriate for 25 to 32 bits floating significance
  2795. --  They will work for less but slightly shorter versions are possible
  2796. --  The routines are coded to stand alone so they need not be compiled together
  2797.  
  2798. --  These routines have been coded to accept a general MANTISSA_TYPE
  2799. --  That is, they are designed to work with a manitssa either fixed of float
  2800. --  There are some explicit conversions which are required but these will
  2801. --  not cause any extra code to be generated
  2802.  
  2803. --      16 JULY 1982       W A WHITAKER  AFATL EGLIN AFB FL 32542
  2804. --                         T C EICHOLTZ  USAFA
  2805.  
  2806.  
  2807.   function SQRT(X : FLOAT) return FLOAT is
  2808.     M, N : EXPONENT_TYPE;
  2809.     F, Y : MANTISSA_TYPE;
  2810.     RESULT : FLOAT;
  2811.  
  2812.     subtype INDEX is INTEGER range 0..100;    --  #########################
  2813.     SQRT_L1 : INDEX := 3;
  2814.     --  Could get away with SQRT_L1 := 2 for 28 bits
  2815.     --  Using the better Cody-Waite coeficients overflows MANTISSA_TYPE
  2816.     SQRT_C1 : MANTISSA_TYPE := 8#0.3317777777#;
  2817.     SQRT_C2 : MANTISSA_TYPE := 8#0.4460000000#;
  2818.     SQRT_C3 : MANTISSA_TYPE := 8#0.55202_36314_77747_36311_0#;
  2819.  
  2820.   begin
  2821.     if X = ZERO  then
  2822.       RESULT := ZERO;
  2823.       return RESULT;
  2824.     elsif X = ONE  then            --  To get exact SQRT(1.0)
  2825.       RESULT := ONE;
  2826.       return RESULT;
  2827.     elsif X < ZERO  then
  2828.       raise ill_neg_SQRT_used_abs;
  2829.       RESULT := SQRT(ABS(X));
  2830.       return RESULT;
  2831.     else
  2832.       DEFLOAT(X, N, F);
  2833.       Y := SQRT_C1 + MANTISSA_TYPE(SQRT_C2 * F);
  2834.       for J in 1..SQRT_L1  loop
  2835.         Y := Y/MANTISSA_DIVISOR_2 + MANTISSA_TYPE((F/MANTISSA_DIVISOR_2)/Y);
  2836.       end loop;
  2837.       if (N mod 2) /= 0  then
  2838.         Y := MANTISSA_TYPE(SQRT_C3 * Y);
  2839.         N := N + 1;
  2840.       end if;
  2841.       M := N/2;
  2842.       REFLOAT(M,Y,RESULT);
  2843.       return RESULT;
  2844.     end if;
  2845.   exception
  2846.   when others =>
  2847.     raise ill_SQRT_used_1;
  2848.     return ONE;
  2849.   end SQRT;
  2850.  
  2851.  
  2852.     function LOG(X : FLOAT) return FLOAT is
  2853.   --  Uses fixed formulation for generality
  2854.  
  2855.     RESULT : FLOAT;
  2856.     N : EXPONENT_TYPE;
  2857.     XN : FLOAT;
  2858.     Y : FLOAT;
  2859.     F : MANTISSA_TYPE;
  2860.     Z, ZDEN, ZNUM : MANTISSA_TYPE;
  2861.  
  2862.     C0 : constant MANTISSA_TYPE := 0.20710_67811_86547_52440;
  2863.                                                --  SQRT(0.5) - 0.5
  2864.     C1 : constant FLOAT := 8#0.543#;
  2865.     C2 : constant FLOAT :=-2.12194_44005_46905_82767_9E-4;
  2866.  
  2867.     function R(Z : MANTISSA_TYPE) return MANTISSA_TYPE is
  2868.     --  Use fixed formulation here because the float coeficents are > 1.0
  2869.     --  and would exceed the limits on a MANTISSA_TYPE
  2870.       A0 : constant MANTISSA_TYPE := 0.04862_85276_587;
  2871.       B0 : constant MANTISSA_TYPE := 0.69735_92187_803;
  2872.       B1 : constant MANTISSA_TYPE :=-0.125;
  2873.       C  : constant MANTISSA_TYPE := 0.01360_09546_862;
  2874.     begin
  2875.       return Z + MANTISSA_TYPE(Z * 
  2876.           MANTISSA_TYPE(MANTISSA_TYPE(Z * Z) * (C +
  2877.           MANTISSA_TYPE(A0/(B0 + MANTISSA_TYPE(B1 * MANTISSA_TYPE(Z * Z)))))));
  2878.     end R;
  2879.  
  2880.   begin
  2881.  
  2882.     if X < ZERO      then
  2883.       raise ill_neg_LOG_used_abs;
  2884.       RESULT := LOG(ABS(X));
  2885.     elsif X = ZERO  then
  2886.       raise ill_zero_LOG_val;
  2887.       RESULT := -XMAX;      --  SUPPOSED TO BE -LARGE
  2888.     else
  2889.       DEFLOAT(X,N,F);
  2890.       ZNUM := F - MANTISSA_HALF;
  2891.       Y := CONVERT_TO_FLOAT(ZNUM);
  2892.       ZDEN := ZNUM / MANTISSA_DIVISOR_2 + MANTISSA_HALF;
  2893.       if ZNUM > C0  then
  2894.         Y := Y - MANTISSA_HALF;
  2895.         ZNUM := ZNUM - MANTISSA_HALF;
  2896.         ZDEN := ZDEN + MANTISSA_HALF/MANTISSA_DIVISOR_2;
  2897.       else
  2898.         N := N -1;
  2899.       end if;
  2900.       Z    := MANTISSA_TYPE(ZNUM / ZDEN);
  2901.       RESULT := CONVERT_TO_FLOAT(R(Z));
  2902.       if N /= 0  then
  2903.         XN := CONVERT_TO_FLOAT(N);
  2904.         RESULT := (XN * C2 + RESULT) + XN * C1;
  2905.       end if;
  2906.     end if;
  2907.     return RESULT;
  2908.  
  2909.   exception
  2910.   when others =>
  2911.     raise ill_LOG_ret_zero;
  2912.     return ZERO;
  2913.   end LOG;
  2914.  
  2915.  
  2916.  
  2917.   function LOG10(X : FLOAT) return FLOAT is
  2918.     LOG_10_OF_2 : constant FLOAT :=
  2919.              CONVERT_TO_FLOAT(MANTISSA_TYPE(8#0.33626_75425_11562_41615#));
  2920.   begin
  2921.     return LOG(X) * LOG_10_OF_2;
  2922.   end LOG10;
  2923.  
  2924.  
  2925.  
  2926.   function EXP(X : FLOAT) return FLOAT is
  2927.  
  2928.     RESULT : FLOAT;
  2929.     N : EXPONENT_TYPE;
  2930.     XG, XN, X1, X2 : FLOAT;
  2931.     F, G : MANTISSA_TYPE;
  2932.  
  2933.     BIGX : FLOAT := EXP_LARGE;
  2934.     SMALLX : FLOAT := EXP_SMALL;
  2935.  
  2936.     ONE_OVER_LOG_2 : constant FLOAT :=  1.4426_95040_88896_34074;
  2937.     C1 : constant FLOAT :=  0.69335_9375;
  2938.     C2 : constant FLOAT := -2.1219_44400_54690_58277E-4;
  2939.  
  2940.     function R(G : MANTISSA_TYPE) return MANTISSA_TYPE is
  2941.       Z , GP, Q : MANTISSA_TYPE;
  2942.  
  2943.       P0 : constant MANTISSA_TYPE :=  0.24999_99999_9992;
  2944.       P1 : constant MANTISSA_TYPE :=  0.00595_04254_9776;
  2945.       Q0 : constant MANTISSA_TYPE :=  0.5;
  2946.       Q1 : constant MANTISSA_TYPE :=  0.05356_75176_4522;
  2947.       Q2 : constant MANTISSA_TYPE :=  0.00029_72936_3682;
  2948.     begin
  2949.       Z  := MANTISSA_TYPE(G * G);
  2950.       GP := MANTISSA_TYPE( (MANTISSA_TYPE(P1 * Z) + P0) * G );
  2951.       Q  := MANTISSA_TYPE( (MANTISSA_TYPE(Q2 * Z) + Q1) * Z ) + Q0;
  2952.       return MANTISSA_HALF + MANTISSA_TYPE( GP /(Q - GP) );
  2953.     end R;
  2954.  
  2955.  
  2956.   begin
  2957.  
  2958.     if X > BIGX  then
  2959.       raise ill_large_val_EXP;
  2960.       RESULT := XMAX;
  2961.     elsif X < SMALLX  then
  2962.       raise ill_neg_val_EXP;
  2963.       RESULT := ZERO;
  2964.     elsif ABS(X) < EPS  then
  2965.       RESULT := ONE;
  2966.     else
  2967.       N  := EXPONENT_TYPE(X * ONE_OVER_LOG_2);
  2968.       XN := CONVERT_TO_FLOAT(N);
  2969.       X1 := ROUND(X);
  2970.       X2 := X - X1;
  2971.       XG := ( (X1 - XN * C1) + X2 ) - XN * C2;
  2972.       G  := MANTISSA_TYPE(XG);
  2973.       N  := N + 1;
  2974.       F := R(G);
  2975.       REFLOAT(N, F, RESULT);
  2976.     end if;
  2977.     return RESULT;
  2978.  
  2979.   exception
  2980.   when others =>
  2981.     raise ill_EXP_ret_one;
  2982.     return ONE;
  2983.   end EXP;
  2984.  
  2985. function "**" (X, Y : FLOAT) return FLOAT is
  2986. --  This is the last function to be coded since it appeared that it really
  2987. --  was un-Ada-like and ought not be in the regular package
  2988. --  Nevertheless it was included in this version
  2989. --  It is specific for FLOAT and does not have the MANTISSA_TYPE generality
  2990.   M, N : EXPONENT_TYPE;
  2991.   G : MANTISSA_TYPE;
  2992.   P, TEMP, IW1, I : INTEGER;
  2993.   RESULT, Z, V, R, U1, U2, W, W1, W2, W3, Y1, Y2 : FLOAT;
  2994.  
  2995.   K : constant FLOAT := 0.44269_50408_88963_40736;
  2996.   IBIGX : constant INTEGER := INTEGER(TRUNCATE(16.0 * LOG(XMAX) - 1.0));
  2997.   ISMALLX : constant INTEGER := INTEGER(TRUNCATE(16.0 * LOG(XMIN) + 1.0));
  2998.  
  2999.   P1 : constant FLOAT := 0.83333_32862_45E-1;
  3000.   P2 : constant FLOAT := 0.12506_48500_52E-1;
  3001.  
  3002.   Q1 : constant FLOAT := 0.69314_71805_56341;
  3003.   Q2 : constant FLOAT := 0.24022_65061_44710;
  3004.   Q3 : constant FLOAT := 0.55504_04881_30765E-1;
  3005.   Q4 : constant FLOAT := 0.96162_06595_83789E-2;
  3006.   Q5 : constant FLOAT := 0.13052_55159_42810E-2;
  3007.  
  3008.   A1 : array (1 .. 17) of FLOAT:=
  3009.      (  8#1.00000_0000#,        
  3010.         8#0.75222_5750#,        
  3011.         8#0.72540_3067#,        
  3012.         8#0.70146_3367#,        
  3013.         8#0.65642_3746#,        
  3014.         8#0.63422_2140#,        
  3015.         8#0.61263_4520#,        
  3016.         8#0.57204_2434#,        
  3017.         8#0.55202_3631#,        
  3018.         8#0.53254_0767#,        
  3019.         8#0.51377_3265#,        
  3020.         8#0.47572_4623#,        
  3021.         8#0.46033_7602#,        
  3022.         8#0.44341_7233#,        
  3023.         8#0.42712_7017#,        
  3024.         8#0.41325_3033#,        
  3025.         8#0.40000_0000#  );        
  3026.                 
  3027.   A2 : array (1 .. 8) of FLOAT :=
  3028.      (  8#0.00000_00005_22220_66302_61734_72062#,
  3029.         8#0.00000_00003_02522_47021_04062_61124#,
  3030.         8#0.00000_00005_21760_44016_17421_53016#,
  3031.         8#0.00000_00007_65401_41553_72504_02177#,
  3032.         8#0.00000_00002_44124_12254_31114_01243#,
  3033.         8#0.00000_00000_11064_10432_66404_42174#,
  3034.         8#0.00000_00004_72542_16063_30176_55544#,
  3035.         8#0.00000_00001_74611_03661_23056_22556#  );
  3036.        
  3037.  
  3038.   function REDUCE (V : FLOAT) return FLOAT is
  3039.   begin
  3040.     return FLOAT(INTEGER(16.0 * V)) * 0.0625;
  3041.   end REDUCE;
  3042.  
  3043.   begin
  3044.     if X <= ZERO then
  3045.       if X < ZERO then
  3046.         RESULT := (ABS(X))**Y;
  3047.     raise ill_EXPONENT_used_abs;
  3048.       else
  3049.         if Y <= ZERO then
  3050.           if Y = ZERO then
  3051.             RESULT := ZERO;
  3052.           else
  3053.             RESULT := XMAX;
  3054.           end if;
  3055.       raise ill_EXPONENT_val;
  3056.         else
  3057.           RESULT := ZERO;
  3058.         end if;
  3059.       end if;
  3060.     else
  3061.       DEFLOAT(X, M, G);
  3062.       P := 1;
  3063.       if G <= A1(9) then
  3064.         P := 9;
  3065.       end if;
  3066.       if G <= A1(P+4) then
  3067.         P := P + 4;
  3068.       end if;
  3069.       if G <= A1(P+2) then
  3070.         P := P + 2;
  3071.       end if;
  3072.       Z := ((G - A1(P+1)) - A2((P+1)/2))/(G + A1(P+1));
  3073.       Z := Z + Z;
  3074.       V := Z * Z;
  3075.       R := (P2 * V + P1) * V * Z;
  3076.       R := R + K * R;
  3077.       U2 := (R + Z * K) + Z;
  3078.       U1 := FLOAT(INTEGER(M) * 16 - P) * 0.0625;
  3079.       Y1 := REDUCE(Y);
  3080.       Y2 := Y - Y1;
  3081.       W := U2 * Y + U1 * Y2;
  3082.       W1 := REDUCE(W);
  3083.       W2 := W - W1;
  3084.       W := W1 + U1 * Y1;
  3085.       W1 := REDUCE(W);
  3086.       W2 := W2 + (W - W1);
  3087.       W3 := REDUCE(W2);
  3088.       IW1 := INTEGER(TRUNCATE(16.0 * (W1 + W3)));
  3089.       W2 := W2 - W3;
  3090.       if W > FLOAT(IBIGX) then
  3091.         RESULT := XMAX;
  3092.     raise ill_large_val_EXPONENT;
  3093.       elsif W < FLOAT(ISMALLX) then
  3094.         RESULT := ZERO;
  3095.     raise ill_small_val_EXPONENT;
  3096.       else
  3097.         if W2 > ZERO then
  3098.           W2 := W2 - 0.0625;
  3099.           IW1 := IW1 + 1;
  3100.         end if;
  3101.         if IW1 < INTEGER(ZERO) then
  3102.           I := 0;
  3103.         else 
  3104.           I := 1;
  3105.         end if;
  3106.         M := EXPONENT_TYPE(I + IW1/16);
  3107.         P := 16 * INTEGER(M) - IW1;
  3108.         Z := ((((Q5 * W2 + Q4) * W2 + Q3) * W2 + Q2) * W2 + Q1) * W2;
  3109.         Z := A1(P+1) + (A1(P+1) * Z);  
  3110.  
  3111.         REFLOAT(M, Z, RESULT);
  3112.       end if;
  3113.     end if;
  3114.     return RESULT;
  3115.   end "**";
  3116.  
  3117.  
  3118.  
  3119. --  The following routines are coded directly from the algorithms and
  3120. --  coeficients given in "Software Manual for the Elementry Functions"
  3121. --  by William J. Cody, Jr. and William Waite, Prentice_Hall, 1980
  3122. --  This particular version is stripped to work with FLOAT and INTEGER
  3123. --  and uses a mantissa represented as a FLOAT
  3124. --  A more general formulation uses MANTISSA_TYPE, etc.
  3125. --  The coeficients are appropriate for 25 to 32 bits floating significance
  3126. --  They will work for less but slightly shorter versions are possible
  3127. --  The routines are coded to stand alone so they need not be compiled together
  3128.  
  3129. --      16 JULY 1982       W A WHITAKER  AFATL EGLIN AFB FL 32542
  3130. --                         T C EICHOLTZ  USAFA
  3131.  
  3132.  
  3133.  
  3134.  
  3135.  
  3136.  
  3137.  
  3138.   function ATAN(X : FLOAT) return FLOAT is
  3139.     F, G : FLOAT;
  3140.     subtype REGION is INTEGER range 0..3;    --  ##########
  3141.     N : REGION;
  3142.     RESULT : FLOAT;
  3143.  
  3144.     BETA : FLOAT := CONVERT_TO_FLOAT(IBETA);
  3145.  
  3146.     EPSILON : FLOAT := BETA ** (-IT/2);
  3147.  
  3148.     SQRT_3           : constant FLOAT :=  1.73205_08075_68877_29353;
  3149.     SQRT_3_MINUS_1   : constant FLOAT :=  0.73205_08075_68877_29353;
  3150.     TWO_MINUS_SQRT_3 : constant FLOAT :=  0.26794_91924_31122_70647;
  3151.  
  3152.     function R(G : FLOAT) return FLOAT is
  3153.       P0 : constant FLOAT := -0.14400_83448_74E1;
  3154.       P1 : constant FLOAT := -0.72002_68488_98;
  3155.       Q0 : constant FLOAT :=  0.43202_50389_19E1;
  3156.       Q1 : constant FLOAT :=  0.47522_25845_99E1;
  3157.       Q2 : constant FLOAT :=  1.0;
  3158.     begin
  3159.       return ((P1*G + P0)*G) / ((G + Q1)*G + Q0);
  3160.     end R;
  3161.  
  3162.   begin
  3163.     F := ABS(X);
  3164.  
  3165.     if F > 1.0  then
  3166.       F := 1.0 / F;
  3167.       N := 2;
  3168.     else
  3169.       N := 0;
  3170.     end if;
  3171.  
  3172.     if F > TWO_MINUS_SQRT_3  then
  3173.       F := (((SQRT_3_MINUS_1 * F - 0.5) - 0.5) + F) / (SQRT_3 + F);
  3174.       N := N + 1;
  3175.     end if;
  3176.  
  3177.     if ABS(F) < EPSILON  then
  3178.       RESULT := F;
  3179.     else
  3180.       G := F * F;
  3181.       RESULT := F + F * R(G);
  3182.     end if;
  3183.  
  3184.     if N > 1  then
  3185.       RESULT := - RESULT;
  3186.     end if;
  3187.  
  3188.     case N is
  3189.     when 0  =>
  3190.       RESULT := RESULT;
  3191.     when 1  =>
  3192.       RESULT := PI_OVER_SIX + RESULT;
  3193.     when 2  =>
  3194.       RESULT := PI_OVER_TWO + RESULT;
  3195.     when 3  =>
  3196.       RESULT := PI_OVER_THREE + RESULT;
  3197.     end case;
  3198.  
  3199.     if X < 0.0  then
  3200.       RESULT := - RESULT;
  3201.     end if;
  3202.  
  3203.     return RESULT;
  3204.  
  3205.   end ATAN;
  3206.  
  3207.  
  3208.  
  3209. begin
  3210.   EXP_LARGE := LOG(XMAX) * (ONE - EPS);
  3211.   EXP_SMALL := LOG(XMIN) * (ONE - EPS);
  3212. end CORE_FUNCTIONS;
  3213. generic
  3214.    type FltType is digits <>;
  3215.    type IntType is range <>;
  3216. --******************************************************
  3217. package Gen_Math is
  3218. --=============GENERIC MATH ROUTINES =================================
  3219. --     Exports basic math functions used by QSAP tool
  3220. --     Installation Notes:
  3221. --       o Two versions of package body are supplied:
  3222. --          Ada Version                   : Gen_Math_Body_Ada.ada
  3223. --          Data General Assembly Version : Gen_Math_Body_DG.ada
  3224. --                 (See User's Manual for accessing DG Math Library) 
  3225. --
  3226. --       o Ada Version is portable but very SLOW( >15 times) than DG Ver. 
  3227. --       o Installer should develop new package body for his particular
  3228. --                system.
  3229. --=================================================================== 
  3230.  
  3231.  
  3232.    function Log( X : FltType) return FltType;
  3233.  
  3234.    function Sqrt( X : FltType ) return FltType ;
  3235.  
  3236.    function Exp ( X : FltType ) return FltType;
  3237.  
  3238.    pragma INLINE (Log,Sqrt,Exp);
  3239.  
  3240. end Gen_Math;
  3241. with Core_Functions ; 
  3242. package body Gen_Math is
  3243. --===================================================================
  3244.  
  3245.               -- UNIVERSAL MATH VERSION -- Very Slow!
  3246.  
  3247. --   Universal version of math library(routines written in Ada lang).
  3248. --   Approximately 10-15 times slower than corresponding routines 
  3249. --   written in Assembly language.
  3250. --===================================================================
  3251.  
  3252.  function LOGARITHM_10(X:FLOAT) return FLOAT renames CORE_Functions.LOG10;
  3253.  function EXPONENTIAL(X:Float) return FLOAT renames CORE_Functions.EXP;
  3254.  function SQUARE_ROOT(X:FLOAT) return FLOAT renames CORE_Functions.SQRT; 
  3255.  
  3256.    --******************************************* 
  3257.    function Log( X : FltType) return FltType is 
  3258.       -- Natural Log
  3259.    begin 
  3260.      return FltType(Logarithm_10(Float(X)))/0.4342945; 
  3261.    end Log; 
  3262.  
  3263.    --*******************************************
  3264.    function Sqrt( X : FltType ) return FltType is 
  3265.    begin
  3266.      return FltType(Square_Root(Float(X)));
  3267.    end Sqrt;
  3268.  
  3269.     --*******************************************
  3270.    function Exp ( X : FltType ) return FltType is 
  3271.    begin
  3272.      return FltType(Exponential(Float(X)));
  3273.    end Exp;
  3274. end Gen_Math;
  3275. generic
  3276.    type FltType is digits <>;
  3277.    type IntType is range <>;
  3278. package Gen_Factorials is
  3279. --================Table-Based Generic Factorial Functions ==============
  3280. --     Factorial Values up to LARGEST_FACT are computed during package
  3281. --     elaboration and are stored in a look-up table (for efficiency
  3282. --     purposes). 
  3283. --======================================================================
  3284.  
  3285.    LARGEST_FACT : constant := 50;
  3286.  
  3287.    function Fact( I: IntType) return FltType;
  3288.      -- Exception FACTORIAL_TOO_LARGE is raised if I > LARGEST_FACT.
  3289.  
  3290.    function Log_Fact(I:IntType) return FltType; 
  3291.      -- Returns the Log of the Factorial. For Factorials greater than
  3292.      -- LARGEST_FACT Stirlings Approximation Formula is used. 
  3293.  
  3294.    function Bin_Coeff( Left:IntType; Right: IntType) return FltType;
  3295.      --            Left ! / ( Right ! * (Left - Right) ! )
  3296.  
  3297.    FACTORIAL_TOO_LARGE : exception;
  3298.  
  3299. end Gen_Factorials;
  3300.  
  3301. with Gen_Math;
  3302. package body Gen_Factorials is
  3303.  
  3304.     package Math_Pak is new Gen_Math(FltType,IntType); use Math_Pak;
  3305.  
  3306.     Fact_Table : array (IntType range 0.. Largest_Fact) of FltType;
  3307.  
  3308.     --*******************************************
  3309.     procedure Initialize_Table is
  3310.     begin
  3311.       Fact_Table(0) := 1.0;
  3312.       for I in 1 .. IntType'(Largest_Fact) loop
  3313.          Fact_Table(I) := FltType(I) * Fact_Table(I-1);
  3314.       end loop;
  3315.     end Initialize_Table;
  3316.    
  3317.     --*******************************************
  3318.     function Fact(I : IntType) return FltType is
  3319.     begin
  3320.        if I > LARGEST_FACT then
  3321.          raise FACTORIAL_TOO_LARGE;
  3322.        end if; 
  3323.        return Fact_Table(I);
  3324.     end Fact;
  3325.  
  3326.    function Log_Fact(I : IntType) return FltType is
  3327.       F:FltType := FltType(I);
  3328.    begin
  3329.        if I < Largest_Fact then
  3330.            return Log(Fact(I));
  3331.        else
  3332.                -- Stirlings Formula
  3333.            return 0.91894 + (F + 0.5) * Log(F) - F; 
  3334.        end if;
  3335.    end Log_Fact;
  3336.  
  3337.  
  3338.     --*******************************************
  3339.    function Bin_Coeff( Left:IntType ; Right: IntType ) return FltType is
  3340.    begin
  3341.       if Left > Right then
  3342.          return Fact(Left) / (Fact(Right)* Fact(Left-Right));
  3343.       elsif Left=Right then
  3344.          return 1.0;
  3345.       else
  3346.          return 0.0;
  3347.       end if;
  3348.    end Bin_Coeff;
  3349.   
  3350. begin
  3351.   Initialize_Table;
  3352. end Gen_Factorials;
  3353.   with Global_Types; use Global_Types;
  3354.   with Real_Mat_Pak; use Real_Mat_Pak;
  3355.   --**********************
  3356.   package Node_Servicer is
  3357.   --=====================================================
  3358.   --    Package exports an abstract data type NodeDef which
  3359.   --    contains information about a node. Functions are provided
  3360.   --    to access and modify this information.
  3361.   --=====================================================
  3362.  
  3363.     --======================
  3364.     type NodeDef is private;
  3365.     --======================
  3366.  
  3367.     function Create_Node  ( Node_Name          : in NodeName;
  3368.                             Status             : in Boolean;
  3369.                             Serv_Disc          : in ServDisc;
  3370.                             Connect_Probs      : in RealVector)
  3371.                                                   return NodeDef;
  3372.  
  3373.     function Modify_Node(Node          : in NodeDef;
  3374.                          Node_Name     : in NodeName) return NodeDef; 
  3375.  
  3376.     function Modify_Node(Node          : in NodeDef;
  3377.                          Connect_Probs : RealVector) return Nodedef;
  3378.  
  3379.     function Modify_Node(Node          : in NodeDef;
  3380.                          Serv_Disc     : ServDisc) return Nodedef;
  3381.  
  3382.        -- Attributes of NodeDef
  3383.  
  3384.     function Name_Of_Node(     Node : in NodeDef) return NodeName;
  3385.  
  3386.     function Node_Complete    (Node : in NodeDef) return Boolean;
  3387.  
  3388.     function Node_Serv_Disc(   Node : in NodeDef) return ServDisc;
  3389.  
  3390.     function Node_Num_Servers ( Node : in NodeDef) return NumServers;
  3391.  
  3392.     function Node_Serv_Mode   ( Node : in NodeDef) return ServMode;
  3393.  
  3394.     function Node_Serv_Funct(  Node : in NodeDef) return ServFunct;
  3395.  
  3396.     function Node_Cox_Dist(    Node : in NodeDef) return CoxianDist;
  3397.  
  3398.     function Node_Connect_Prob(Node : in NodeDef) return RealVector; 
  3399.  
  3400.     Node_Access_Exception : Exception;
  3401.  
  3402.   private
  3403.      type NodeDef is record
  3404.         Node_Name       : NodeName;
  3405.         Complete        : Boolean;
  3406.         Serv_Disc       : ServDisc;
  3407.         Connect_Probs   : RealVector;  
  3408.      end record;
  3409.   end Node_Servicer;
  3410.   with Text_Io; use Text_Io;
  3411.   package body Node_Servicer is
  3412.  
  3413.  
  3414.     --**************************************************************
  3415.     function Create_Node  ( Node_Name          : in NodeName;
  3416.                             Status             : in Boolean;
  3417.                             Serv_Disc          : in ServDisc;
  3418.                             Connect_Probs      : in RealVector)
  3419.                                                   return NodeDef is
  3420.       Node : NodeDef ;
  3421.     begin
  3422.        Node.Node_Name     := Node_Name;
  3423.        Node.Complete      := Status;
  3424.        Node.Serv_Disc     := Serv_Disc;
  3425.        Node.Connect_Probs := Connect_Probs;
  3426.              --***** Compiler Bug-- Compiler dies very painfully
  3427.        --Node := (Node_Name,Serv_Disc, Connect_Probs);
  3428.        return Node;
  3429.     end Create_Node;
  3430.        
  3431.  
  3432.     --**************************************************************
  3433.     function Modify_Node(Node : in NodeDef ; Node_Name: in NodeName)
  3434.                                                     return NodeDef is
  3435.        Local_Node :NodeDef := Node;
  3436.     begin
  3437.        Local_Node.Node_Name := Node_Name;
  3438.        return Local_Node;
  3439.     end Modify_Node;
  3440.  
  3441.     --**************************************************************
  3442.     function Modify_Node(Node : in NodeDef ; Connect_Probs : RealVector)
  3443.                                                            return Nodedef is
  3444.        Local_Node : NodeDef:=Node;
  3445.     begin
  3446.        Local_Node.Connect_Probs := Connect_Probs;
  3447.        return Local_Node;
  3448.     end Modify_Node;
  3449.  
  3450.  
  3451.     --**************************************************************
  3452.     function Modify_Node(Node : in NodeDef ;  Serv_Disc: ServDisc)
  3453.                                              return Nodedef is
  3454.        Local_Node : NodeDef:=Node;
  3455.     begin
  3456.        Local_Node.Serv_Disc := Serv_Disc;
  3457.        return Local_Node;
  3458.     end Modify_Node;
  3459.        
  3460.  
  3461.  
  3462.     --**************************************************************
  3463.     function Name_Of_Node(    Node  : in NodeDef) return NodeName is
  3464.     begin
  3465.       return Node.Node_Name;
  3466.     end Name_Of_Node;
  3467.  
  3468.     --**************************************************************
  3469.  
  3470.     function Node_Complete   (Node: in NodeDef) return Boolean is
  3471.  
  3472.     begin
  3473.  
  3474.       return Node.Complete;
  3475.  
  3476.     end Node_Complete;
  3477.  
  3478.     --**************************************************************
  3479.     function Node_Serv_Disc(   Node : in NodeDef) return ServDisc is
  3480.     begin
  3481.       return Node.Serv_Disc;
  3482.     end Node_Serv_Disc;
  3483.  
  3484.     --**************************************************************
  3485.     function Node_Num_Servers ( Node : in NodeDef) return NumServers is
  3486.     begin
  3487.        return Node.Serv_Disc.Num_Servers;
  3488.     end Node_Num_Servers;
  3489.  
  3490.     --**************************************************************
  3491.     function Node_Serv_Mode   ( Node : in NodeDef) return ServMode is
  3492.     begin
  3493.        return Node.Serv_Disc.Serv_Mode;
  3494.     end Node_Serv_Mode;
  3495.  
  3496.     --**************************************************************
  3497.     function Node_Serv_Funct(   Node : in NodeDef)return ServFunct is
  3498.     begin
  3499.       return Node.Serv_Disc.Serv_Funct;
  3500.     end Node_Serv_Funct;
  3501.  
  3502.     --**************************************************************
  3503.     function Node_Cox_Dist(    Node : in NodeDef) return CoxianDist is
  3504.       Serv_Disc    : ServDisc renames Node.Serv_Disc;
  3505.       Serv_Mode : ServMode renames Serv_Disc.Serv_Mode;
  3506.       
  3507.     begin
  3508.       case Serv_Mode is
  3509.          when FCFS =>
  3510.            raise Node_Access_Exception;
  3511.          when P_Share .. NQ=>
  3512.            case Node.Serv_Disc.Serv_Funct.Serv_Dist is
  3513.              when Coxian =>
  3514.                return Node.Serv_Disc.Serv_Funct.Coxian_Dist; 
  3515.              when others =>
  3516.                 raise Node_Access_Exception;
  3517.            end case;
  3518.       end case;
  3519.     end Node_Cox_Dist;
  3520.  
  3521.     --**************************************************************
  3522.     function Node_Connect_Prob(Node : in NodeDef) return RealVector is
  3523.     begin
  3524.        return Node.Connect_Probs;
  3525.     end  Node_Connect_Prob;
  3526.  
  3527.  
  3528.  end Node_Servicer;
  3529. with Global_types;use Global_types;
  3530. with Node_Servicer; use Node_Servicer;
  3531. --***********************************************
  3532. package Network is
  3533. --====================================================================
  3534. -- Provides a storage facility for the MMI subsystem. Nodes are stored
  3535. -- as a linked list('Network'). Facilities are provided to access this
  3536. -- network(i.e., insert, delete, and replace nodes). Movement along
  3537. -- list can be done by position or by searching for a node_name. 
  3538. --====================================================================
  3539.  
  3540.      type BeforeAfter is (Before,After);
  3541.  
  3542.      procedure Set_Up_New_Network;
  3543.  
  3544.      procedure Move_To ( Find_Node : in NodeName; Found: out Boolean );
  3545.  
  3546.      procedure Move_To_First_Node(End_Of_Network : out Boolean); 
  3547.  
  3548.      procedure Move_To_Next_Node ( End_Of_Network: out Boolean); 
  3549.        -- Note: above movement routines will ignore empty networks.
  3550.  
  3551.      -- ****  Service Function at current Node. 
  3552.  
  3553.      procedure Insert_Node  ( New_Node : in NodeDef ; 
  3554.                               Where    : in BeforeAfter);
  3555.  
  3556.      procedure Replace_Node ( New_Node : in NodeDef );
  3557.  
  3558.      procedure Remove_Node  ;
  3559.  
  3560.      procedure Get_Node     ( Node : out NodeDef);
  3561.  
  3562.      function Insert_Node ( Find_Node       : in NodeName ;
  3563.                             New_Node        : in NodeDef;
  3564.                             Where : BeforeAfter   ) return Boolean ;
  3565.  
  3566.      function Replace_Node ( Find_Node  : in NodeName;
  3567.                              New_Node   : in NodeDef )return Boolean;
  3568.  
  3569.      function Remove_Node (Find_Node : in NodeName) return Boolean; 
  3570.  
  3571.      procedure Get_Node ( Find_Node : in NodeName;
  3572.                           Node      : out NodeDef;
  3573.                           Found     : out Boolean );
  3574.  
  3575.      procedure Get_Node ( Find_Node : in NodeName;
  3576.                           Node      : out NodeDef);
  3577.  
  3578.       --**** Network Attributes
  3579.      function Node_Is_Complete (Find_Node: in NodeName) return Boolean;
  3580.      function Is_Empty_Network return Boolean;
  3581.      function Is_Last_Node     return Boolean; 
  3582.      function Count_Nodes      return NumNodes ;
  3583.  
  3584.      Network_Access_Exception : Exception;
  3585. end Network; 
  3586.  
  3587. with Text_Io; use Text_Io;
  3588. with Unchecked_deallocation;
  3589. package body Network is
  3590.  
  3591.      type NodeCell;
  3592.  
  3593.      type NodePointer is access NodeCell;  
  3594.  
  3595.      type NodeCell is
  3596.         record
  3597.           Node : NodeDef;
  3598.           Next_Node : NodePointer;
  3599.           Prev_Node : NodePointer;
  3600.         end record;
  3601.  
  3602.  
  3603.      Num_Nodes : NumNodes := 0;
  3604.      First_Node      : NodePointer ;
  3605.      Current_Node    : NodePointer ;
  3606.  
  3607.      The_Network : NodePointer;
  3608.  
  3609.       procedure Free is new Unchecked_Deallocation(
  3610.                                       NodeCell, NodePointer);
  3611.  
  3612.  
  3613.     --**************************************************************     
  3614.      function Locate_Name (Search_Name : NodeName) return Boolean is
  3615.        Ref_Node : NodePointer:= Current_Node;
  3616.        Walker   : NodePointer:= First_Node;
  3617.      begin
  3618.        if First_Node = null then
  3619.            return False;
  3620.        end if;
  3621.        while Walker /= null loop
  3622.          if Search_Name = Name_Of_Node(Walker.Node) then
  3623.            Current_Node := Walker;
  3624.            return True;
  3625.          end if;
  3626.          Walker := Walker.Next_Node;
  3627.        end loop;
  3628.        Current_Node := Ref_Node;
  3629.        return False;
  3630.      end Locate_Name;
  3631.  
  3632.     --****************************************
  3633.      function Count_Nodes return NumNodes  is
  3634.        Ref_Node : NodePointer := Current_Node;
  3635.        Walker   : NodePointer := First_Node;
  3636.        Num_Nodes : NumNodes :=0;
  3637.     begin
  3638.       while Walker /= null loop
  3639.          Num_Nodes := Num_Nodes + 1;
  3640.          Walker := Walker.Next_Node;
  3641.       end loop;
  3642.       Current_Node := Ref_Node;
  3643.       return Num_Nodes;
  3644.     end Count_Nodes;
  3645.     
  3646.     --******************************
  3647.      procedure Set_Up_New_Network is
  3648.      begin
  3649.          if First_Node = null  then   -- Handle No nodes
  3650.             return;
  3651.          elsif First_Node.Next_Node = null then  -- Handle only one node
  3652.             free(First_Node);
  3653.             return;
  3654.          end if;
  3655.  
  3656.          Current_Node := First_Node.Next_Node;    -- Handle two or more
  3657.          while Current_Node/= null loop
  3658.            Free(Current_Node.Prev_Node);
  3659.            Current_Node := Current_Node.Next_Node;
  3660.          end loop;
  3661.  
  3662.          Free(Current_Node);
  3663.          Free(First_Node);
  3664.          Num_Nodes := 0;
  3665.      end Set_Up_New_Network;
  3666.  
  3667.      -- ****  Movement Operators
  3668.  
  3669.      --********************************************************
  3670.      procedure Move_To ( Find_Node : in NodeName; 
  3671.                          Found     : out Boolean ) is
  3672.         Walker : NodePointer;
  3673.      begin
  3674.         Current_Node := First_Node;
  3675.         loop
  3676.           if Current_Node = null then
  3677.               Found := False;
  3678.               exit;
  3679.           elsif  Find_Node = Name_Of_Node(Current_Node.Node) then
  3680.               Found := True;
  3681.               exit;
  3682.           else
  3683.              Current_Node := Current_Node.Next_Node; 
  3684.           end if;
  3685.         end loop;
  3686.         return;
  3687.      end Move_To;
  3688.  
  3689.      --********************************************************
  3690.      procedure Move_To_First_Node( End_Of_Network : out Boolean) is
  3691.      begin
  3692.         if First_Node = null then
  3693.            End_Of_Network := True; 
  3694.         else
  3695.            Current_Node := First_Node;
  3696.            End_Of_Network := False;
  3697.         end if;
  3698.      end Move_To_First_Node;
  3699.  
  3700.      --********************************************************
  3701.      procedure Move_To_Next_Node ( End_Of_Network: out Boolean) is
  3702.      begin
  3703.         End_Of_Network := False;
  3704.         if Current_Node.Next_Node = null then
  3705.            End_Of_Network := True;
  3706.            return;
  3707.         end if;
  3708.         Current_Node := Current_Node.Next_Node;         
  3709.      end Move_To_Next_Node;
  3710.  
  3711.      -- ****  Service Functions at current Node. 
  3712.  
  3713.      --********************************************************
  3714.      procedure Insert_Node  ( New_Node : in NodeDef ;
  3715.                               Where : in BeforeAfter) is
  3716.         Temp_Node : NodePointer;
  3717.      begin
  3718.         if First_Node = null  then
  3719.            First_Node := new NodeCell'(New_Node,null,null);
  3720.            First_Node.Node := New_Node;
  3721.            Current_Node := First_Node;
  3722.            Num_Nodes := 1;
  3723.  
  3724.                        -- Handle Single Node Case
  3725.         elsif First_Node.Next_Node = null then
  3726.           case Where is
  3727.              when Before =>
  3728.                  Temp_Node := First_Node;
  3729.                  First_Node := new NodeCell'( New_Node,
  3730.                                               Next_Node => First_Node,
  3731.                                               Prev_Node => null); 
  3732.                  First_Node.Next_Node := Temp_Node;
  3733.                  Current_Node := First_Node;
  3734.  
  3735.              when After =>
  3736.                  Temp_Node := Current_Node;
  3737.                  Current_Node:= new NodeCell'( New_Node , 
  3738.                                               Next_Node => null,
  3739.                                               Prev_Node => First_Node);
  3740.                       -- Aggragate Assignment doesnt work properly
  3741.                       -- Discriminant records of Node and Prev_Node 
  3742.                       -- pointer are not working
  3743.                  Current_Node.Node:= New_Node;
  3744.                  Current_Node.Next_Node := null;
  3745.                  Current_Node.Prev_Node := First_Node; 
  3746.                  Current_Node.Prev_Node.Next_Node := Current_Node;
  3747.            end case;
  3748.            Num_Nodes := 2;
  3749.  
  3750.         else    -- Multi-Nodes
  3751.                        -- Handle case where current node is first node
  3752.            if Current_Node.Prev_Node = null then
  3753.                case Where is
  3754.                  when Before =>
  3755.                     Temp_Node := First_Node;
  3756.                     First_Node := new NodeCell'(New_Node,
  3757.                                                 Next_Node => First_Node,
  3758.                                                 Prev_Node => null);
  3759.                     First_Node.Node:= New_Node;
  3760.                     First_Node.Next_Node := Temp_Node;
  3761.                     Current_Node := First_Node;
  3762.                     Current_Node.Next_Node.Prev_Node := Current_Node;
  3763.                  when After =>
  3764.                     Temp_Node := Current_Node;
  3765.                     Current_Node := new NodeCell'(
  3766.                                     Node      => New_Node,
  3767.                                     Next_Node => Current_Node.Next_Node,
  3768.                                     Prev_Node => Current_Node);
  3769.                     Current_Node.Node := New_Node;
  3770.                     Current_Node.Next_Node:=Temp_Node.Next_Node; 
  3771.                     Current_Node.Prev_Node:=Temp_Node; 
  3772.                     Current_Node.Prev_Node.Next_Node := Current_Node;
  3773.                     Current_Node.Next_Node.Prev_Node := Current_Node;
  3774.                  end case;
  3775.                        -- Handle case where current node is last node
  3776.             elsif  Current_Node.Next_Node = null then
  3777.                 case Where is
  3778.                   when Before =>
  3779.                     Temp_Node := Current_Node;
  3780.                     Current_Node := new NodeCell'(
  3781.                                     Node      => New_Node,
  3782.                                     Next_Node => Current_Node,  
  3783.                                     Prev_Node => Current_Node.Prev_Node);
  3784.                     Current_Node.Node := New_Node;
  3785.                     Current_Node.Next_Node := Temp_Node;
  3786.                     Current_Node.Prev_Node := Temp_Node.Prev_Node;
  3787.                     Current_Node.Prev_Node.Next_Node := Current_Node;
  3788.                     Current_Node.Next_Node.Prev_Node := Current_Node;
  3789.                   when After =>
  3790.                     Temp_Node := Current_Node;
  3791.                     Current_Node := new NodeCell'(
  3792.                                        Node      => New_Node,
  3793.                                        Next_Node => null,  -- see note
  3794.                                        Prev_Node => Current_Node);
  3795.                     Current_Node.Node:= New_Node;
  3796.                     Current_Node.Next_Node := null;
  3797.                     Current_Node.Prev_Node := Temp_Node; 
  3798.                     Current_Node.Prev_Node.Next_Node := Current_Node;
  3799.                 end case;
  3800.                 
  3801.                      -- Handle case where current node is middle 
  3802.              else
  3803.                 case Where is
  3804.                    when Before =>
  3805.                      Temp_Node := Current_Node;
  3806.                      Current_Node := new NodeCell'(
  3807.                                     Node      => New_Node,
  3808.                                     Next_Node => Current_Node,
  3809.                                     Prev_Node => Current_Node.Prev_Node);
  3810.                      Current_Node.Node:= New_Node;
  3811.                      Current_Node.Next_Node := Temp_Node;
  3812.                      Current_Node.Prev_Node := Temp_Node.Prev_Node;
  3813.                      Current_Node.Prev_Node.Next_Node := Current_Node;
  3814.                      Current_Node.Next_Node.Prev_Node := Current_Node;
  3815.                    when After =>
  3816.                      Temp_Node := Current_Node;
  3817.                      Current_Node := new NodeCell'(
  3818.                                     Node      => New_Node,
  3819.                                     Next_Node => Current_Node.Next_Node,
  3820.                                     Prev_Node => Current_Node);
  3821.                      Current_Node.Node:= New_Node;
  3822.                      Current_Node.Next_Node := Temp_Node.Next_Node;
  3823.                      Current_Node.Prev_Node := Temp_Node;
  3824.                      Current_Node.Prev_Node.Next_Node := Current_Node;
  3825.                      Current_Node.Next_Node.Prev_Node := Current_Node;
  3826.                 end case;
  3827.              end if;
  3828.              Num_Nodes := Num_Nodes + 1;
  3829.          end if;
  3830.      end Insert_Node;
  3831.  
  3832.      --********************************************************
  3833.      procedure Replace_Node (New_Node: in NodeDef) is
  3834.      begin
  3835.         if Current_Node = null then
  3836.             raise Network_Access_Exception;
  3837.         else
  3838.            Current_Node.Node := New_Node;
  3839.         end if;
  3840.      end Replace_Node;
  3841.  
  3842.      --********************************************************
  3843.      procedure Remove_Node   is
  3844.        Temp_Pointer : NodePointer;
  3845.      begin
  3846.  
  3847.        if (Current_Node = null) or (First_Node = null) then
  3848.           null;
  3849.  
  3850.        elsif First_Node.Next_Node = null then  
  3851.                                   --Remove first in list (1 node)
  3852.           First_Node := null;
  3853.           Free(Current_Node);
  3854.  
  3855.        elsif Current_Node = First_Node then   
  3856.                                   --Remove first in list (>1 nodes)
  3857.           First_Node := First_Node.Next_Node;
  3858.           First_Node.Prev_Node := null;
  3859.           Free(Current_Node);
  3860.           Current_Node := First_Node;
  3861.  
  3862.        elsif Current_Node.Next_Node = null then 
  3863.                                   --Remove last in list (>1 nodes)
  3864.           Current_Node := Current_Node.Prev_Node;
  3865.           Free(Current_Node.Next_Node);
  3866.           Current_Node.Next_Node := null;
  3867.  
  3868.        else                       -- Remove from middle of list
  3869.           Current_Node.Prev_Node.Next_Node := Current_node.Next_Node;
  3870.           Current_Node.Next_Node.Prev_Node := Current_Node.Prev_Node;
  3871.           Temp_Pointer  := Current_Node.Next_Node;
  3872.           Free(Current_Node);
  3873.           Current_Node := Temp_Pointer;
  3874.        end if;
  3875.  
  3876.        if Num_Nodes /=0 then
  3877.           Num_Nodes := Num_Nodes - 1;
  3878.        end if;   
  3879.      end Remove_Node;
  3880.  
  3881.      --*****************************************
  3882.      procedure Get_Node ( Node : out NodeDef) is
  3883.      begin
  3884.        if (First_Node = null)  or ( Current_Node = null)  then
  3885.           raise Network_Access_Exception ;
  3886.        end if;
  3887.        Node := Current_Node.Node;
  3888.      end Get_Node;
  3889.  
  3890.  
  3891.       -- **** Search and Service Functions
  3892.  
  3893.      --************************************************
  3894.      function Insert_Node ( Find_Node   : in NodeName ;
  3895.                             New_Node    : in NodeDef;
  3896.                             Where : BeforeAfter   ) return Boolean is 
  3897.         Found : Boolean := False;
  3898.      begin
  3899.         Found := Locate_Name (Find_Node);
  3900.         if Found then
  3901.            Insert_Node ( New_Node , Where);
  3902.         end if;
  3903.         return Found;
  3904.      end Insert_Node;
  3905.  
  3906.      --********************************************************
  3907.      function Replace_Node ( Find_Node  : in NodeName;
  3908.                              New_Node   : in NodeDef ) return Boolean is
  3909.         Found : Boolean := False;
  3910.      begin
  3911.         Found := Locate_Name ( Find_Node);
  3912.         if Found then
  3913.            Replace_Node (New_Node);
  3914.         end if;
  3915.         return Found;
  3916.      end Replace_Node;
  3917.  
  3918.      --********************************************************
  3919.      function Remove_Node (Find_Node : in NodeName) return Boolean is
  3920.         Found : Boolean := False;
  3921.      begin
  3922.         Found := Locate_Name( Find_Node);
  3923.         if Found then
  3924.            Remove_Node ;
  3925.         end if;
  3926.         return Found;
  3927.      end Remove_Node;
  3928.  
  3929.      --******************************************
  3930.      procedure Get_Node ( Find_Node : in NodeName;
  3931.                           Node      : out NodeDef;
  3932.                           Found     : out Boolean ) is
  3933.      begin
  3934.         Found := False;
  3935.         if Locate_Name( Find_Node) then
  3936.            Get_Node( Node);
  3937.            Found := True;
  3938.         end if;
  3939.      end Get_Node;
  3940.  
  3941.      --*******************************************
  3942.  
  3943.      procedure Get_Node ( Find_Node : in NodeName;
  3944.                           Node      : out NodeDef) is
  3945.      begin
  3946.         if Locate_Name( Find_Node) then
  3947.            Get_Node( Node);
  3948.         else
  3949.            raise Network_Access_Exception;
  3950.         end if;
  3951.      end Get_Node;
  3952.  
  3953.      --********************************************************
  3954.  
  3955.      function Node_Is_Complete (Find_Node: NodeName) return Boolean is
  3956.  
  3957.      ND   : NodeDef;
  3958.      Found: Boolean;
  3959.  
  3960.      begin
  3961.  
  3962.         Get_Node (Find_Node, ND, Found);
  3963.         if Found then
  3964.            return Node_Complete(ND) = True;
  3965.         else
  3966.            return False;
  3967.         end if;
  3968.  
  3969.      end Node_Is_Complete;
  3970.  
  3971.       --**** Network Attributes
  3972.  
  3973.      --*****************************************
  3974.      function Is_Empty_Network return Boolean is
  3975.      begin
  3976.        return First_Node = null;
  3977.      end Is_Empty_Network;
  3978.  
  3979.      --*************************************
  3980.  
  3981.      function Is_Last_Node return Boolean is
  3982.      begin
  3983.       return Current_Node.Next_Node = null;
  3984.      end Is_Last_Node;
  3985.  end Network;
  3986. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  3987. --qsap2.ada
  3988. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  3989. --===========================================================
  3990. -- Source:     Division Software Technology and Support
  3991. --             Western Development Laboratories
  3992. --             Ford Aerospace & Communications Corporation
  3993. --             ATTN:  Ada Tools Group
  3994. -- Date   : June 1985
  3995. --===========================================================
  3996.  
  3997.  
  3998.  
  3999. with Text_Handler; use Text_Handler;
  4000. with Global_Types;
  4001.  
  4002. package Mmi_Io is
  4003.  
  4004. ------------------------------------------------------------------------
  4005. -- Input/Output package servicing MMI package and Edit procedure.
  4006. -- Command input can be either the terminal or a file via IOmedia
  4007. -- type. If input is from a file, then it is echoed on the terminal.
  4008. -- Report  output can also be either directed to the terminal,
  4009. -- a file, or both.
  4010. --
  4011. -- The command input line is all characters between consequtive
  4012. -- carriage returns.
  4013. --
  4014. -- A token is all characters of the command input line between
  4015. -- consequetive spaces after the characters, ",", "=", ";" are
  4016. -- converted to spaces. A token cannot be null.
  4017. --
  4018. -- Objects are arranged in alphabetical order by class where possible.
  4019. ------------------------------------------------------------------------
  4020.  
  4021.  
  4022. type      IOmedia          is (Terminal, File);
  4023. type      IOmode           is (Help, Input, Report, Save, Terminal_Out);
  4024. subtype   TerminalFileMode is IOmode range Input  .. Report;
  4025. subtype   OutMode          is IOmode range Report .. Terminal_Out;
  4026. subtype   FileMode         is IOmode range Help   .. Save;
  4027.  
  4028. EOF:      exception;      -- End Of File
  4029.  
  4030. procedure Closef       (Mode    : FileMode);
  4031.  
  4032. function  Delimit      (From    : Text)            return Text;
  4033.   ----------------------------------------------------------------------
  4034.   -- Lets \ act as a character delete. Example, Delimit(`abc\`)= `ab`
  4035.   ----------------------------------------------------------------------
  4036.  
  4037. procedure Flush_Input;
  4038.   ----------------------------------------------------------------------
  4039.   -- Empties out the current command input line.
  4040.   ----------------------------------------------------------------------
  4041.  
  4042. procedure Flush_Next_Token;
  4043.   ----------------------------------------------------------------------
  4044.   -- Removes the next token from the command input line.
  4045.   ----------------------------------------------------------------------
  4046. --LINEFEED
  4047. function  Get_Media    (Mode    : TerminalFileMode) return IOmedia;
  4048.   ----------------------------------------------------------------------
  4049.   -- Returns the current media setting (terminal or file) for Mode.
  4050.   ----------------------------------------------------------------------
  4051.  
  4052. function Input_Line return Text;
  4053.   ----------------------------------------------------------------------
  4054.   -- Returns the current remainder of the input command line.
  4055.   ----------------------------------------------------------------------
  4056.  
  4057. function Line_Number return Positive;
  4058.   ----------------------------------------------------------------------
  4059.   -- Returns the current line number.
  4060.   ----------------------------------------------------------------------
  4061.  
  4062. procedure Openf        (Mode    : FileMode;
  4063.                         Name    : String);
  4064.   ----------------------------------------------------------------------
  4065.   -- Opens file 'Name' according to Mode.
  4066.   ----------------------------------------------------------------------
  4067.  
  4068. procedure New_Page;
  4069.   ----------------------------------------------------------------------
  4070.   -- Puts a new page mark onto a report output file. Puts a new
  4071.   -- page mark onto the terminal if Terminal_Paging is set.
  4072.   ----------------------------------------------------------------------
  4073.  
  4074. function  Next_Token_Exists  return Boolean;
  4075.   ----------------------------------------------------------------------
  4076.   -- Returns True if there is another token in the current command
  4077.   -- input line.
  4078.   ----------------------------------------------------------------------
  4079.  
  4080. function  Page_Length return Positive;
  4081.   ----------------------------------------------------------------------
  4082.   -- Returns variable Length_Of_Page if either the report output media
  4083.   -- is a file or if the variable Terminal_Paging is true. Otherwise it
  4084.   -- returns Positive'Last.
  4085.   ----------------------------------------------------------------------
  4086.  
  4087. function  Page_Number return Positive;
  4088.   ----------------------------------------------------------------------
  4089.   -- Returns variable Number_Of_Page if either the report output media
  4090.   -- is a file or if the variable Terminal_Paging is true. Otherwise it
  4091.   -- returns Positive'Last.
  4092.   ----------------------------------------------------------------------
  4093.  
  4094. procedure Read (Line: out String);
  4095.   ----------------------------------------------------------------------
  4096.   -- Reads the next line of the Help file.
  4097.   ----------------------------------------------------------------------
  4098.  
  4099. procedure Replace_Token(Token   : Text);
  4100.   ----------------------------------------------------------------------
  4101.   -- Puts back a Token into the current command input line.
  4102.   ----------------------------------------------------------------------
  4103. --LINEFEED
  4104. procedure Set_Column   (Column  : Positive);
  4105.   ----------------------------------------------------------------------
  4106.   -- Sets the Column on the output file and/or the terminal.
  4107.   ----------------------------------------------------------------------
  4108.  
  4109. procedure Set_Report_Echo (Setting: Boolean);
  4110.   ----------------------------------------------------------------------
  4111.   -- Sets the Echoing of reports to the terminal in addition to
  4112.   -- writing them to the report file.
  4113.   ----------------------------------------------------------------------
  4114.  
  4115. procedure Set_Media    (Mode    : TerminalFileMode;
  4116.                         Media   : IOmedia);
  4117.   ----------------------------------------------------------------------
  4118.   -- Sets the media to either terminal or file.
  4119.   ----------------------------------------------------------------------
  4120.  
  4121. procedure Set_Terminal_Paging (On_Off: in Boolean);
  4122.   ----------------------------------------------------------------------
  4123.   -- Sets the boolean Terminal_Paging which determines whether or not
  4124.   -- output to the terminal is to have a paged format.
  4125.   ----------------------------------------------------------------------
  4126.  
  4127. function  Token         return String;
  4128.   ----------------------------------------------------------------------
  4129.   -- Returns the next Token wherever it can get it, either the current
  4130.   -- command input line or the next one.
  4131.   ----------------------------------------------------------------------
  4132.  
  4133. procedure Write        (Message : String;
  4134.                         Mode    : OutMode := Terminal_Out;
  4135.                         Spacing : Natural := 0);
  4136.   ----------------------------------------------------------------------
  4137.   -- Outputs 'Message' to the output stream identified by Mode.
  4138.   ----------------------------------------------------------------------
  4139.  
  4140. end MMI_IO;
  4141.  
  4142.  
  4143. with Text_Io;      use Text_Io;
  4144. package body Mmi_Io is
  4145.  
  4146.    Blank         :  constant Text := Txt(" ");
  4147.    Blank_Line    :  constant String(1 .. 240) := (others => ' ');
  4148.    Help_File     :           File_Type;
  4149.    Input_File    :           File_Type;
  4150.    Input_Text    :           Text := Txt("");
  4151.    Input_Media   :           IOmedia;
  4152.    Length_Of_Page:  constant Positive:= 60;
  4153.    Mark          :           Natural;
  4154.    Report_File   :           File_Type;
  4155.    Report_Echo   :           Boolean;
  4156.    Report_Media  :           IOmedia;
  4157.    Save_File     :           File_Type;
  4158.    Terminal_Paging:          Boolean:= False;
  4159. --LINEFEED
  4160. procedure Closef       (Mode: FileMode) is
  4161.  
  4162. begin
  4163.  
  4164.    if    Mode = Input then
  4165.       Close (Input_File);
  4166.    elsif Mode = Report then
  4167.       Close (Report_File);
  4168.    elsif Mode = Save then
  4169.       Close (Save_File);
  4170.    elsif Mode = Help then
  4171.       Close (Help_File);
  4172.    end if;
  4173.  
  4174. end Closef;
  4175.  
  4176. ------------------------------------------------------------------------
  4177. ------------------------------------------------------------------------
  4178.  
  4179. function Delimit (From: Text)   return Text is
  4180.  
  4181.    To  : Text    := From & Txt(" ");   -- add a blank for ease of use
  4182.    Idx : Integer := 1;
  4183.  
  4184. begin
  4185.  
  4186.    loop
  4187.       exit when Idx > Length(To);
  4188.  
  4189.       if Substr (To,Idx,1) = Txt('\') then
  4190.          if Idx = 1 then
  4191.             To := Substr (To,2);
  4192.          elsif Idx = 2 then
  4193.             To := Substr (To,3);
  4194.             Idx := 1;
  4195.          else
  4196.             To  := Substr (To,1,Idx-2) & Substr (To,Idx+1);
  4197.             Idx := Idx - 1;
  4198.          end if;
  4199.       else
  4200.          Idx := Idx + 1;
  4201.       end if;
  4202.  
  4203.    end loop;
  4204.  
  4205.    return Substr (To,1,Length(To)-1);       -- don't include that blank
  4206.  
  4207. end Delimit;
  4208. --LINEFEED
  4209. procedure Flush_Next_Token is
  4210.  
  4211.    Dummy : Text := Txt(Token);
  4212.  
  4213. begin
  4214.  
  4215.    null;
  4216.  
  4217. end Flush_Next_Token;
  4218.  
  4219. ------------------------------------------------------------------------
  4220. ------------------------------------------------------------------------
  4221.  
  4222. procedure Flush_Input is
  4223.  
  4224. begin
  4225.  
  4226.    Input_Text := Txt("");
  4227.  
  4228. end Flush_Input;
  4229.  
  4230. ------------------------------------------------------------------------
  4231. ------------------------------------------------------------------------
  4232.  
  4233. function  Get_Media    (Mode : TerminalFileMode) return IOmedia is
  4234.  
  4235. begin
  4236.  
  4237.    if Mode = Input then
  4238.       return Input_Media;
  4239.    else
  4240.       return Report_Media;
  4241.    end if;
  4242.  
  4243. end Get_Media;
  4244. --LINEFEED
  4245. function Input_Line return Text is
  4246.  
  4247.    Value: Text := Input_Text;
  4248.  
  4249. begin
  4250.  
  4251.    Flush_Input;
  4252.    return Value;
  4253.  
  4254. end Input_Line;
  4255.  
  4256. ------------------------------------------------------------------------
  4257. ------------------------------------------------------------------------
  4258.  
  4259. function Line_Number return Positive is
  4260.  
  4261. begin
  4262.  
  4263.    if Report_Media = File then
  4264.       return Positive(Text_IO.Line(Report_File));
  4265.    else
  4266.       return Positive(Text_IO.Line(Standard_Output));
  4267.    end if;
  4268.  
  4269. end Line_Number;
  4270. --LINEFEED
  4271. procedure New_Page is
  4272.  
  4273. begin
  4274.  
  4275.    if Report_Media = File then
  4276.       Text_Io.New_Page (Report_File);
  4277.    end if;
  4278.  
  4279.    if Report_Echo then
  4280.       if Terminal_Paging then
  4281.          Text_io.New_Page (Standard_Output);
  4282.       else
  4283.          New_Line (Standard_Output, 2);
  4284.       end if;
  4285.    end if;
  4286.  
  4287. end New_Page;
  4288.  
  4289. ------------------------------------------------------------------------
  4290. ------------------------------------------------------------------------
  4291.  
  4292. function  Next_Token_Exists return Boolean is
  4293.  
  4294. begin
  4295.  
  4296.    return not (Remove_Leading (Input_Text, " ") = Txt(""));
  4297.  
  4298. end Next_Token_Exists;
  4299. --LINEFEED
  4300. procedure Openf        (Mode    : FileMode;
  4301.                         Name    : String) is
  4302.  
  4303. begin
  4304.  
  4305.    if    Mode = Input then
  4306.       open   (Input_File, In_File, Name);
  4307.    elsif Mode = Report then
  4308.       create (Report_File, Out_File, Name);
  4309.       Set_Page_Length (Report_File, Count(Length_Of_Page));
  4310.    elsif Mode = Save then
  4311.       create (Save_File, Out_File, Name);
  4312.    elsif Mode = Help then
  4313.       open   (Help_File, In_File, Name);
  4314.    end if;
  4315.  
  4316. end Openf;
  4317.  
  4318. ------------------------------------------------------------------------
  4319. ------------------------------------------------------------------------
  4320.  
  4321. function Page_Length return Positive is
  4322.  
  4323. begin
  4324.  
  4325.    if (Report_Media = File) or Terminal_Paging then
  4326.       return Length_Of_Page;
  4327.    else
  4328.       return Positive'Last;
  4329.    end if;
  4330.  
  4331. end Page_Length;
  4332.  
  4333. ------------------------------------------------------------------------
  4334. ------------------------------------------------------------------------
  4335.  
  4336. function Page_Number return Positive is
  4337.  
  4338. begin
  4339.  
  4340.    if Report_Media = File then
  4341.       return Positive(Text_IO.Page(Report_File));
  4342.    else
  4343.       return Positive(Text_IO.Page(Standard_Output));
  4344.    end if;
  4345.  
  4346. end Page_Number;
  4347. --LINEFEED
  4348. procedure Read (Line: out String) is
  4349.  
  4350. begin
  4351.  
  4352.    if End_Of_File (Help_File) then
  4353.       raise EOF;
  4354.    end if;
  4355.  
  4356.    Get_Line (Help_File, Line, Mark);
  4357.  
  4358. end Read;
  4359.  
  4360. ------------------------------------------------------------------------
  4361. ------------------------------------------------------------------------
  4362.  
  4363. procedure Replace_Token (Token : Text) is
  4364.  
  4365. begin
  4366.  
  4367.    Input_Text := Token & Txt(" ") & Input_Text;
  4368.  
  4369. end Replace_Token;
  4370.  
  4371. ------------------------------------------------------------------------
  4372. ------------------------------------------------------------------------
  4373.  
  4374. procedure Set_Column (Column: in Positive) is
  4375.  
  4376. begin
  4377.  
  4378.    if Report_Media = File then
  4379.       Set_Col (Report_File, Positive_Count(Column));
  4380.    end if;
  4381.  
  4382.    if Report_Echo then
  4383.       Set_Col (Standard_Output, Positive_Count(Column));
  4384.    end if;
  4385.  
  4386. end Set_Column;
  4387. --LINEFEED
  4388. procedure Set_Report_Echo (Setting: Boolean) is
  4389.  
  4390. begin
  4391.  
  4392.    Report_Echo := Setting;
  4393.    if Report_Media = File and Terminal_Paging then
  4394.       Set_Line (Standard_Output, Count(Line_Number));
  4395.    end if;
  4396.  
  4397. end Set_Report_Echo;
  4398.  
  4399. ------------------------------------------------------------------------
  4400. ------------------------------------------------------------------------
  4401.  
  4402. procedure Set_Media    (Mode    : TerminalFileMode;
  4403.                         Media   : IOmedia) is
  4404.  
  4405. begin
  4406.  
  4407.    if Mode = Input then
  4408.       if Media = Terminal then
  4409.          Set_Input (Standard_Input);
  4410.          Input_Media := Terminal;
  4411.       else
  4412.          Set_Input (Input_File);
  4413.          Input_Media := File;
  4414.       end if;
  4415.    else
  4416.       if Media = Terminal then
  4417.          Report_Media := Terminal;
  4418.       else
  4419.          if Report_Echo and Terminal_Paging then
  4420.             Set_Line (Report_File, Count(Line_Number));
  4421.          end if;
  4422.          Report_Media := File;
  4423.       end if;
  4424.    end if;
  4425.  
  4426. end Set_Media;
  4427. --LINEFEED
  4428. procedure Set_Terminal_Paging (On_Off: in Boolean) is
  4429.  
  4430. begin
  4431.  
  4432.    Terminal_Paging := On_Off;
  4433.  
  4434.    if On_Off then
  4435.       Set_Page_Length (Standard_Output, Count(Length_Of_Page));
  4436.       if Report_Media = File and Report_Echo then
  4437.          Set_Line (Standard_Output, Count(Line_Number));
  4438.       end if;
  4439.    else
  4440.       Set_Page_Length (Standard_Output, 0);
  4441.    end if;
  4442.  
  4443. end Set_Terminal_Paging;
  4444. --LINEFEED
  4445. function Token  return String is
  4446.  
  4447.    Input_String:  String (1 .. 240) := (others => ' ');
  4448.    Result      :  Text;
  4449.    Leng        :  Integer;
  4450.  
  4451. begin
  4452.  
  4453.    Input_Text := Remove_Leading (Input_Text, " ");
  4454.  
  4455.    while Length(Input_Text) = 0 loop
  4456.       if Input_Media = File and then End_Of_File  then
  4457.          raise EOF;
  4458.       end if;
  4459.  
  4460.       Input_String := Blank_Line;
  4461.       Get_Line (Input_String, Mark);
  4462.  
  4463.       if Mark > 0 then
  4464.          Input_Text := Delimit (Translate (Remove_Leading (
  4465.             Remove_Trailing(Substr(Txt (Input_String),1,Mark), " "),
  4466.             " "),Txt("  "), Txt(",=")));
  4467.       end if;
  4468.  
  4469.       if Input_Media = File then
  4470.          Put_Line (Standard_Output, Strng(Input_Text));
  4471.       end if;
  4472.  
  4473.    end loop;
  4474.  
  4475.    Result := Before (Input_Text, Blank);
  4476.    Leng   := Length(Result);
  4477.  
  4478.    if Leng > 1 then
  4479.       if    Substr(Result,1,1) = Txt("(") then
  4480.          Result := Txt("(");
  4481.       elsif Substr(Result,Leng,1) = Txt(")")  then
  4482.          Result := Substr(Result,1,Leng-1);
  4483.       end if;
  4484.    end if;
  4485.  
  4486.    Input_Text := After  (Input_Text, Result);
  4487.    return Strng(Up_Case(Result));
  4488.  
  4489. end Token;
  4490. --LINEFEED
  4491. procedure Write        (Message : String;
  4492.                         Mode    : OutMode := Terminal_Out;
  4493.                         Spacing:  Natural := 0) is
  4494.  
  4495.    procedure Write_It (F: in out File_Type) is
  4496.  
  4497.    begin
  4498.  
  4499.       Put (F, Message);
  4500.       if Spacing > 0 then
  4501.          New_line (F, Positive_Count(Spacing));
  4502.       end if;
  4503.  
  4504.    end Write_It;
  4505.  
  4506.    ---------------------------------------------------------------------
  4507.  
  4508.    procedure Write_It_Standard is
  4509.  
  4510.    begin
  4511.  
  4512.       Put (Standard_Output, Message);
  4513.       if Spacing > 0 then
  4514.          New_line (Standard_Output, Positive_Count(Spacing));
  4515.       end if;
  4516.  
  4517.    end Write_It_Standard;
  4518.  
  4519. ------------------------------------------------------------------------
  4520.  
  4521. begin
  4522.  
  4523.    if    Mode = Save then
  4524.       Write_It (Save_File);
  4525.    elsif Mode = Terminal_Out then
  4526.       Write_It_Standard;
  4527.    elsif Mode = Report then
  4528.       if Report_Media = File then
  4529.          Write_It (Report_File);
  4530.       end if;
  4531.       if Report_Echo then
  4532.          Write_It_Standard;
  4533.       end if;
  4534.    end if;
  4535.  
  4536. end Write;
  4537.  
  4538. end MMI_IO;
  4539. with Global_Types; use Global_Types;
  4540. with Real_Mat_Pak; use Real_Mat_Pak;
  4541. package  Report_Types is
  4542. --=======================================================
  4543. --   Data Types passed to and used by Report procedures.
  4544. --======================================================= 
  4545.  
  4546.     type PBranchData is
  4547.        record
  4548.           Node_Name  : NodeName;
  4549.           PBranch    : RealVector;
  4550.        end record;
  4551.  
  4552.     type QLengthDistData is
  4553.        record
  4554.           Node_Name  : NodeName;
  4555.           Queue_Dist : RealVector;
  4556.        end record;
  4557.  
  4558.      type RoutingData is
  4559.         record
  4560.           By_Node         : NodeName;
  4561.           Node_Mean_Tours : Real;
  4562.           Node_Var_Tours  : Real;
  4563.         end record;
  4564.  
  4565.      type  ServiceData is
  4566.         record
  4567.           By_Node        : NodeName;
  4568.           Serv_Reqt_Mean : Real;
  4569.           Serv_Reqt_Var  : Real;
  4570.           Mean_Residence : Real;
  4571.         end record; 
  4572.  
  4573.      type ArrivalData is
  4574.         record
  4575.           Node_Name        : NodeName;
  4576.           Num_Servers      : NumServers;
  4577.           Serv_Mode        : ServMode;
  4578.           Rel_Arrival_Freq : Real;
  4579.         end record;
  4580.  
  4581.       type ServTimeData is
  4582.          record
  4583.             Node_Name       : NodeName;
  4584.             Mean_Serv_Time  : Real;
  4585.             Serv_Time_Var   : Real;
  4586.             Coeff_Var       : Real; 
  4587.             Serv_Funct      : ServFunct;
  4588.          end record;
  4589.  
  4590. --LINEFEED 
  4591.       type QLengthData is
  4592.          record
  4593.             Node_Name        : NodeName;
  4594.             Q_Length_Mean    : Real;
  4595.             Q_Length_Var     : Real;
  4596.             Coeff_Var        : Real;
  4597.             Thru_Put         : Real;
  4598.             Util             : Real;
  4599.          end record;
  4600.  
  4601.        type ServResponseTime(Serv_Mode: ServMode:=FCFS) is
  4602.           record
  4603.              Node_Name        : NodeName;
  4604.              Resp_Time_Mean   : Real;
  4605.              case Serv_Mode is
  4606.                 when FCFS | NQ =>
  4607.                    Resp_Time_Var    : Real;
  4608.                    Coeff_Var        : Real;
  4609.                 when others    =>
  4610.                    null;
  4611.              end case;
  4612.           end record;
  4613.  
  4614.        type ResponseTimeData is
  4615.           record
  4616.              Value : ServResponseTime;
  4617.           end record;
  4618.  
  4619. end Report_Types;
  4620. with Gen_List_Handler;
  4621. with Report_Types; use Report_Types;
  4622. package Report_Lists is
  4623. --===========================================================
  4624. --  Instantiations of List Handler packages order to process
  4625. --  varying amount of data sent to the Report procedures.
  4626. --============================================================ 
  4627.  
  4628.      --********** Procedure Report_PBranch *************************
  4629.     package PBranch_List_Handler is new Gen_List_Handler(PBranchData);
  4630.     type PBranchList is new PBranch_List_Handler.ListType;
  4631.  
  4632.      --********** Procedure Report_Q_Length_Dists ***************
  4633.     package Q_Length_Dist_List_Handler is new Gen_List_Handler(QLengthDistData);
  4634.     type QLengthDistList is new Q_Length_Dist_List_Handler.ListType;
  4635.  
  4636.      --********** Procedure Report_Routing **********************
  4637.      package Routing_List_Handler is new Gen_List_Handler(RoutingData);
  4638.      type RoutingList  is new Routing_List_Handler.ListType;
  4639.  
  4640.      --********** Procedure Report_Service **********************
  4641.      package Service_List_Handler is new Gen_List_Handler(ServiceData);
  4642.      type ServiceList is new Service_List_Handler.ListType;
  4643.  
  4644.      --********** Procedure Report_Arrival_Freqs ****************
  4645.      package Arrival_List_Handler is new Gen_List_Handler(ArrivalData);
  4646.      type ArrivalList is new Arrival_List_Handler.ListType;
  4647.  
  4648.      --********** Procedure Report_Serv_Times *******************
  4649.      package Serv_Time_List_Handler is new
  4650.                                       Gen_List_Handler(ServTimeData);
  4651.      type ServTimeList is new Serv_Time_List_Handler.ListType;
  4652.  
  4653.      --********** Procedure Report_Q_Lengths ********************
  4654.      package Q_Length_List_Handler is new Gen_List_Handler(QLengthData);
  4655.      type QLengthList is new Q_Length_List_Handler.ListType;
  4656.  
  4657.      --********** Procedure Report_Response_Times ***************
  4658.      package Response_List_Handler is new 
  4659.                                Gen_List_Handler(ResponseTimeData);
  4660.      type ResponseTimeList is new Response_List_Handler.ListType;
  4661.       
  4662. end Report_Lists;
  4663. --LINEFEED
  4664. with MMI_IO       ; use MMI_IO;
  4665. with Report_Lists ; use Report_Lists;
  4666. with Global_Types ; use Global_Types;
  4667. with Real_Mat_Pak ; use Real_Mat_Pak;
  4668. with Calendar     ; use Calendar;
  4669.  
  4670. package Reports is
  4671.  
  4672.  
  4673.    procedure Print_Title (Report_Title: String;
  4674.                           Page_Info   : String;
  4675.                           T           : Time);
  4676.  
  4677.    procedure Report_Arrival_Freqs  (List      : in out ArrivalList);
  4678.  
  4679.    procedure Report_GNorms         (GNorms    : in RealVector);
  4680.  
  4681.    procedure Report_PBranch        (List      : in out PbranchList);
  4682.  
  4683.    procedure Report_Q_Length_Dists (List      : in out QLengthDistList);
  4684.  
  4685.    procedure Report_Q_Lengths  (List      : in out QLengthList);
  4686.  
  4687.    procedure Report_Response_Times (List     : in out ResponseTimeList);
  4688.  
  4689.    procedure Report_Routing     (Starting_Name: in     NodeName;
  4690.                                  Return_Name  : in     NodeName;
  4691.                                  Mean_Tours   : in     Real;
  4692.                                  Var_Tours    : in     Real;
  4693.                                  List         : in out RoutingList;
  4694.                                  Page_It      : in     Boolean:= False);
  4695.  
  4696.    procedure Report_Service     (Starting_name: in     NodeName;
  4697.                                  Return_Name  : in     NodeName;
  4698.                                  Tot_Mean_Serv: in     Real;
  4699.                                  Tot_Residence: in     Real;
  4700.                                  List         : in out ServiceList;
  4701.                                  Page_It      : in     Boolean:=False);
  4702.  
  4703.    procedure Report_Serv_Times  (List         : in out ServTimeList);
  4704.  
  4705.    procedure Set_Title          (Title        : in String);
  4706.  
  4707. end Reports;
  4708. --LINEFEED
  4709. with Report_Types ; use Report_Types;
  4710. with Text_Handler ; use Text_Handler;
  4711. with Gen_Text_Handler;
  4712.  
  4713. package body Reports is
  4714.  
  4715.  
  4716.    Model_Title   : Text := Txt("");
  4717.    Single        : Positive := 1;
  4718.    Double        : Positive := 2;
  4719.    Report_Width  : constant Positive := 80;
  4720.  
  4721. ------------------------------------------------------------------------
  4722. ------------------------------------------------------------------------
  4723.  
  4724.    procedure Header_Separator (Length: in Positive) is
  4725.  
  4726.    begin
  4727.  
  4728.       Write (Strng(Duplicate("_",Length)), Report, Double);
  4729.  
  4730.    end Header_Separator;
  4731.  
  4732. ------------------------------------------------------------------------
  4733. ------------------------------------------------------------------------
  4734.  
  4735.    function Page_Number (Starting_Page: Positive) return Natural is
  4736.  
  4737.    begin
  4738.  
  4739.       return MMI_IO.Page_Number - Starting_Page;
  4740.  
  4741.    end Page_Number;
  4742. --LINEFEED
  4743. function Pretty_Natural (Int_Value: Natural) return String is
  4744.  
  4745. -- Makes a string of length 4 with Int_Value right justified, if it can.
  4746.  
  4747. begin
  4748.  
  4749.    if Int_Value < 10000 then
  4750.       return (Strng(Txt(Int_Value,4)));
  4751.    else
  4752.       return Strng(Txt(Int_Value));
  4753.    end if;
  4754.  
  4755. end Pretty_Natural;
  4756.  
  4757. ------------------------------------------------------------------------
  4758. ------------------------------------------------------------------------
  4759.  
  4760. function Pretty_Float (Float_Value: Real) return String is
  4761.  
  4762.    -- Makes a string of length 12 with the decimal point in pos 5.
  4763.  
  4764.    type        ReportFloat is digits 4;
  4765.    package     RText       is new Gen_Text_Handler(ReportFloat); use RText;
  4766.    Val:        RText.Text;
  4767.    Idx:        Integer;
  4768.  
  4769. begin
  4770.  
  4771.    if Float_Value < 1.0e-10 then
  4772.       Val := RText.Txt(ReportFloat(0.0));
  4773.    else
  4774.       Val := RText.Txt(ReportFloat(Float_Value));
  4775.    end if;
  4776.  
  4777.    Idx := RText.Index(Val,RText.Txt("."));
  4778.  
  4779.    return RText.Strng(RText.Duplicate(" ", 5 - Idx) & Val
  4780.       & RText.Duplicate(" ", 7 + Idx - RText.Length(Val)));
  4781.  
  4782. end Pretty_Float;
  4783.  
  4784. ------------------------------------------------------------------------
  4785. ------------------------------------------------------------------------
  4786.  
  4787. function Pretty_Prob (Prob_Value  : in Probs) return String is
  4788.  
  4789.    -- returns a prob string with the decimal point in position 3
  4790.  
  4791.    package    RText is new Gen_Text_Handler(Probs); use RText;
  4792.  
  4793. begin
  4794.  
  4795.    if    Prob_Value = 1.0 then
  4796.       return " 1.0  ";
  4797.    elsif Prob_Value < 0.001 then
  4798.       return " 0.0  ";
  4799.    else
  4800.       return "  ." & Strng(After(RText.Txt(Prob_Value),RText.Txt(".")));
  4801.    end if;
  4802.  
  4803. end Pretty_Prob;
  4804. --LINEFEED
  4805. procedure Print_Title (Report_Title: String;
  4806.                        Page_Info   : String;
  4807.                        T           : Time) is
  4808.  
  4809.    Title1_Col: Integer:= Abs(Report_Width/2 - (Length(Model_Title)/2));
  4810.    Title2_Col: Integer := Abs(Report_Width/2 - (Report_Title'Length/2));
  4811.    Date      : Text:= Substr(Txt(Year(T)),3,2) & Txt("/") &
  4812.                Txt(Month(T)) & Txt("/") & Txt(Day(T));
  4813.    Mil_Time  : Text:= Translate (Txt(Integer(Seconds(T))/3600,2),
  4814.                Txt("0"),Txt(" ")) & Txt(":") & Translate (
  4815.        Txt((Integer(Seconds(T)) mod 3600) /60,2),Txt("0"),Txt(" "));
  4816.  
  4817. begin
  4818.  
  4819.    Set_Column (1);
  4820.    Write (Page_Info, Report);
  4821.    Set_Column (Title1_Col);
  4822.    Write (Strng(Model_Title), Report);
  4823.    Set_Column (Report_Width - 8);
  4824.    Write (Strng(Date), Report);
  4825.  
  4826.    Set_Column (Title2_Col);
  4827.    Write (Report_Title, Report);
  4828.    Set_Column (Report_Width - 8);
  4829.    Write (Strng(Mil_Time), Report, Double);
  4830.  
  4831. end Print_Title;
  4832.  
  4833. ------------------------------------------------------------------------
  4834. ------------------------------------------------------------------------
  4835.  
  4836. function Short (Node_Name: NodeName) return String is
  4837.  
  4838. begin
  4839.  
  4840.    return Strng(Remove_Trailing(Txt(Node_Name)," "));
  4841.  
  4842. end Short;
  4843. --LINEFEED
  4844. procedure Report_Arrival_Freqs (List: in out ArrivalList) is
  4845.  
  4846.    Rec            : ArrivalData;
  4847.    Leng_NumServers: Integer := Length(Txt(NumServers'Last))+1;
  4848.    Within_List    : Boolean;
  4849.    T              : Time := Clock;
  4850.    Start_Page     : Positive := Positive(MMI_IO.Page_Number);
  4851.  
  4852. ------------------------------------------------------------------------
  4853.  
  4854. procedure Header is
  4855.  
  4856. begin
  4857.  
  4858.    Print_Title ("Relative Arrival Frequencies", "Page " &
  4859.       Strng(Txt(Page_Number(Start_Page))), T);
  4860.    Write ("Node             Number of           Queue      " &
  4861.           "     Relative Arrival", Report, Single);
  4862.    Write ("Name              Servers          Discipline   " &
  4863.           "        Frequency    ", Report, Single);
  4864.    Header_Separator (69);
  4865.  
  4866. end Header;
  4867.  
  4868. begin
  4869.  
  4870.    New_Page;
  4871.    Header;
  4872.  
  4873.    Move_To_First_Item (List, Within_List);
  4874.    while Within_List loop
  4875.       Get (List, Rec);
  4876.  
  4877.       if Line_Number < 5 then
  4878.          Header;
  4879.       end if;
  4880.  
  4881.       Set_Column (1);
  4882.       Write (Rec.Node_Name, Report);
  4883.  
  4884.       Set_Column (18);
  4885.       Write (Strng(Txt(Integer(Rec.Num_Servers),Leng_NumServers)),
  4886.              Report);
  4887.       Set_Column (38);
  4888.       Write (ServMode'Image(Rec.Serv_Mode), Report);
  4889.  
  4890.       Set_Column (57);
  4891.       Write (Pretty_Float(Rec.Rel_Arrival_Freq), Report, Single);
  4892.  
  4893.       Move_To_Next_Item (List, Within_List);
  4894.    end loop;
  4895.  
  4896.    Write ("", Report, Double);
  4897.  
  4898. end Report_Arrival_Freqs;
  4899. --LINEFEED
  4900. procedure Report_GNorms        (GNorms: in RealVector) is
  4901.  
  4902.    T              : Time := Clock;
  4903.    Start_Page     : Positive := Positive(MMI_IO.Page_Number);
  4904.  
  4905. ------------------------------------------------------------------------
  4906.  
  4907.    procedure Header is
  4908.  
  4909.    begin
  4910.  
  4911.       Print_Title ("Normalization Constants", "Page " &
  4912.          Strng(Txt(Page_Number(Start_Page))), T);
  4913.       Write ("   m              G (m)", Report, Single);
  4914.       Header_Separator (23);
  4915.  
  4916.    end Header;
  4917.  
  4918. begin
  4919.  
  4920.    New_Page;
  4921.    Header;
  4922.  
  4923.    for Idx in 1 .. Last_Index_Of(Gnorms) loop
  4924.       if Line_Number < 5 then
  4925.          Header;
  4926.       end if;
  4927.  
  4928.       Set_Column (1);
  4929.       Write (Pretty_Natural(Idx-1), Report);
  4930.  
  4931.       Set_Column (17);
  4932.       Write (Pretty_Float(Value_Of(GNorms,Idx)), Report, Single);
  4933.    end loop;
  4934.  
  4935.    Write ("", Report, Double);
  4936.  
  4937. end Report_GNorms;
  4938.  
  4939. --LINEFEED
  4940. procedure Report_PBranch    (List: in out PBranchList) is
  4941.  
  4942.   v_length    : Mindex;
  4943.   maxval1     : constant integer := 4;
  4944.   maxval2     : constant integer := 6;
  4945.   rvalue      : real;
  4946.   Within_List : Boolean;
  4947.   node        : PBranchData;
  4948.   T           : Time := clock;
  4949.   k           : integer;
  4950.   Start_Page  : Positive := Positive(MMI_IO.Page_Number);
  4951.  
  4952.   procedure header is
  4953.  
  4954.   begin
  4955.     Print_Title ("Branch Probabilities", "Page " &
  4956.        Strng(Txt(Page_Number(Start_Page))),T);
  4957.     Write ("  ------------------------------------------------" &
  4958.         "-------------------------", report,single);
  4959.     Write ("  ",report,double);
  4960.   end header;
  4961.  
  4962.   function mult_of_val(i: in integer; val: in integer) return Boolean is
  4963.  
  4964.      m,n,j : real;
  4965.  
  4966.   begin
  4967.     m := real(i);
  4968.     n := real(val);
  4969.     j := m - ( (real(integer(m/n))) *n);
  4970.     
  4971.     if j = real(0.0) then
  4972.       return TRUE;
  4973.     else
  4974.       return FALSE;
  4975.     end if;
  4976.   end mult_of_val;
  4977.  
  4978.   procedure print_legend(size : in integer) is
  4979.  
  4980.   begin
  4981.     Write("   LEGEND ",report,double);
  4982.     Move_To_First_Item(List,Within_List);
  4983.     for i in 1..size loop
  4984.     Get (List,node);
  4985.       Write(Pretty_Natural(i) & "=" & node.Node_Name, Report);
  4986.       if mult_of_val(i,maxval1) then
  4987.          Set_Column(1);
  4988.       end if;
  4989.           Move_To_Next_Item (List, Within_List);
  4990.     end loop;
  4991.     Write(" ",report,single);
  4992.     Write ("  ------------------------------------------------" &
  4993.         "-------------------------", report,single);
  4994.     Write(" ",report,double);
  4995.   end print_legend;
  4996. --LINEFEED
  4997.     -- Report_PBranch begin
  4998.  
  4999. begin
  5000.  
  5001.   Move_To_First_Item(List,Within_List);
  5002.   Get (List,node);
  5003.   v_length := Last_Index_Of(node.PBranch);
  5004.  
  5005.   New_Page;
  5006.   header;
  5007.   print_legend(integer(v_length));
  5008.  
  5009.   Move_To_First_Item(List,Within_List);
  5010.  
  5011.   while Within_List loop
  5012.     Get (List,node);
  5013.     if Line_Number <= 5 then
  5014.     header;
  5015.     end if;
  5016.     Set_Column(1);
  5017.     Write (node.Node_Name,report,single);
  5018.  
  5019.     k := 1;
  5020.     for i in 1..v_length loop
  5021.     rvalue := Value_Of(node.PBranch,mindex(i));
  5022.         if Line_Number <= 5 then
  5023.        k := 1;
  5024.        Set_Column(1);
  5025.        header;
  5026.          Write (node.Node_Name,report,single);
  5027.     end if;
  5028.     Write(Pretty_Natural(i) & ")" & Pretty_Prob(rvalue),report);
  5029.     Set_Column(k*13);
  5030.     k := k+1;
  5031.     if mult_of_val(i,maxval2) then
  5032.        k := 1;
  5033.        Set_Column(1);
  5034.     end if;
  5035.     end loop;
  5036.  
  5037.     Move_To_Next_Item(List, Within_List);
  5038.   end loop;
  5039. end Report_PBranch;
  5040.  
  5041. --LINEFEED
  5042. procedure Report_Q_Length_Dists (List   : in out QLengthDistList) is
  5043.  
  5044.    T           : Time := Clock;
  5045.    Rec         : QLengthDistData;
  5046.    Within_List : Boolean;
  5047.    Report_Start: Constant Positive := 7;
  5048.    Last_Index  : Positive;
  5049.    First_Time  : Boolean := True;
  5050.    Start_Page  : Positive := Positive(MMI_IO.Page_Number);
  5051.  
  5052. ------------------------------------------------------------------------
  5053.  
  5054.    procedure Sub_Header is
  5055.  
  5056.    begin
  5057.  
  5058.       Write ("   m           P {Q = m}      Node: " & Rec.Node_Name,
  5059.          Report, Single);
  5060.       Header_Separator (24);
  5061.  
  5062.    end Sub_Header;
  5063.  
  5064. ------------------------------------------------------------------------
  5065.  
  5066.    procedure Header is
  5067.  
  5068.    begin
  5069.  
  5070.       Print_Title ("Queue Length Distributions", "Page " &
  5071.          Strng(Txt(Page_Number(Start_Page))), T);
  5072.       Sub_Header;
  5073.  
  5074.    end Header;
  5075. --LINEFEED
  5076. begin
  5077.  
  5078.    New_Page;
  5079.  
  5080.    Move_To_First_Item (List, Within_List);
  5081.    While Within_List loop
  5082.       Get (List, Rec);
  5083.       Last_Index := Last_Index_Of(Rec.Queue_Dist);
  5084.  
  5085.       if Line_Number < 5 or First_Time then
  5086.          Header;
  5087.          First_Time := False;
  5088.       elsif Line_Number+10 > Page_Length then
  5089.          New_Page;
  5090.          Header;
  5091.       else
  5092.          Sub_Header;
  5093.       end if;
  5094.  
  5095.       for Idx in 1 .. Last_Index loop
  5096.          if Line_Number < 5 then
  5097.             Header;
  5098.          end if;
  5099.  
  5100.          Set_Column (1);
  5101.          Write (Pretty_Natural(Idx-1), Report);
  5102.  
  5103.          Set_Column (17);
  5104.          Write (Pretty_Float(Value_Of(Rec.Queue_Dist,Idx)), Report,
  5105.             Single);
  5106.       end loop;
  5107.  
  5108.       Move_To_Next_Item (List, Within_List);
  5109.  
  5110.       Write ("", Report, Double);
  5111.    end loop;
  5112.  
  5113. end Report_Q_Length_Dists;
  5114. --LINEFEED
  5115. procedure Report_Q_Lengths  (List: in out QLengthList) is
  5116.  
  5117.    Rec            : QLengthData;
  5118.    Within_List    : Boolean;
  5119.    T              : Time := Clock;
  5120.    Start_Page     : Positive := Positive(MMI_IO.Page_Number);
  5121.  
  5122. ------------------------------------------------------------------------
  5123.  
  5124.    procedure Header is
  5125.  
  5126.    begin
  5127.  
  5128.       Print_Title ("Queue Lengths", "Page " &
  5129.          Strng(Txt(Page_Number(Start_Page))), T);
  5130.       Write ("Node          Mean Queue  Queue Length  " &
  5131.              "Coefficient of  Throughput  Utilization", Report, Single);
  5132.       Write ("Name            Length      Variance    " &
  5133.              "  Variation", Report, Single);
  5134.       Header_Separator (79);
  5135.  
  5136.    end Header;
  5137.  
  5138. begin
  5139.  
  5140.    New_Page;
  5141.    Header;
  5142.  
  5143.    Move_To_First_Item (List, Within_List);
  5144.    while Within_List loop
  5145.       Get (List, Rec);
  5146.  
  5147.       if Line_Number < 5 then
  5148.          Header;
  5149.       end if;
  5150.  
  5151.       Set_Column (1);
  5152.       Write (Rec.Node_Name, Report);
  5153.  
  5154.       Set_Column (16);
  5155.       Write (Pretty_Float(Rec.Q_Length_Mean), Report);
  5156.  
  5157.       Set_Column (29);
  5158.       Write (Pretty_Float(Rec.Q_Length_Var), Report);
  5159.  
  5160.       Set_Column (43);
  5161.       Write (Pretty_Float(Rec.Coeff_Var), Report);
  5162.  
  5163.       Set_Column (57);
  5164.       Write (Pretty_Float(Rec.Thru_Put), Report);
  5165.  
  5166.       Set_Column (69);
  5167.       Write (Pretty_Float(Rec.Util), Report, Single);
  5168.  
  5169.       Move_To_Next_Item (List, Within_List);
  5170.    end loop;
  5171.    Write ("", Report, Double);
  5172. end Report_Q_Lengths;
  5173. --LINEFEED
  5174. procedure Report_Response_Times (List: in out ResponseTimeList) is
  5175.  
  5176.    Rec            : ResponseTimeData;
  5177.    Within_List    : Boolean;
  5178.    T              : Time := Clock;
  5179.    Start_Page     : Positive := Positive(MMI_IO.Page_Number);
  5180.  
  5181. ------------------------------------------------------------------------
  5182.  
  5183.    procedure Header is
  5184.  
  5185.    begin
  5186.  
  5187.       Print_Title ("Response Times", "Page " &
  5188.          Strng(Txt(Page_Number(Start_Page))), T);
  5189.       Write ("Node            Mean Response    Response Time" &
  5190.              "     Coefficient of", Report, Single);
  5191.       Write ("Name                Time           Variance   " &
  5192.              "       Variation", Report, Single);
  5193.       Header_Separator (65);
  5194.  
  5195.    end Header;
  5196. --LINEFEED
  5197. begin
  5198.  
  5199.    New_Page;
  5200.    Header;
  5201.  
  5202.    Move_To_First_Item (List, Within_List);
  5203.    while Within_List loop
  5204.       Get (List, Rec);
  5205.  
  5206.       Set_Column (1);
  5207.       if Line_Number < 5 then
  5208.          Header;
  5209.       end if;
  5210.       Write (Rec.Value.Node_Name, Report);
  5211.  
  5212.       Set_Column (18);
  5213.       Write (Pretty_Float(Rec.Value.Resp_Time_Mean), Report);
  5214.  
  5215.       Set_Column (35);
  5216.       case Rec.Value.Serv_Mode is
  5217.          when FCFS | NQ =>
  5218.             Write (Pretty_Float(Rec.Value.Resp_Time_Var), Report);
  5219.          when others    =>
  5220.             null;
  5221.       end case;
  5222.  
  5223.       Set_Column (53);
  5224.       case Rec.Value.Serv_Mode is
  5225.          when FCFS | NQ =>
  5226.             Write (Pretty_Float(Rec.Value.Coeff_Var), Report);
  5227.          when others    =>
  5228.             null;
  5229.       end case;
  5230.  
  5231.       Move_To_Next_Item (List, Within_List);
  5232.    end loop;
  5233.  
  5234.    Write ("", Report, Double);
  5235.  
  5236. end Report_Response_Times;
  5237. --LINEFEED
  5238. procedure Report_Routing  (Starting_Name: in     NodeName;
  5239.                            Return_Name  : in     NodeName;
  5240.                            Mean_Tours   : in     Real;
  5241.                            Var_Tours    : in     Real;
  5242.                            List         : in out RoutingList;
  5243.                            Page_It      : in     Boolean:= False) is
  5244.  
  5245.    T           : Time := Clock;
  5246.    Rec         : RoutingData;
  5247.    Within_List : Boolean;
  5248.    Start_Page  : Positive := Positive(MMI_IO.Page_Number);
  5249.  
  5250. ------------------------------------------------------------------------
  5251.  
  5252.    procedure Sub_Header is
  5253.  
  5254.    begin
  5255.  
  5256.       Write ("Start At Node: " & Short(Starting_Name) &
  5257.          "  Return To Node: " & Short(Return_Name), Report, Double);
  5258.       Write ("Node              Service Tour Mean    " &
  5259.       " Service Tour Variance", Report, Single);
  5260.       Header_Separator (61);
  5261.  
  5262.    end Sub_Header;
  5263.  
  5264. ------------------------------------------------------------------------
  5265.  
  5266.    procedure Header is
  5267.  
  5268.    begin
  5269.  
  5270.       Print_Title ("Routing Behavior", "Page " &
  5271.          Strng(Txt(Page_Number(Start_Page))), T);
  5272.       Sub_Header;
  5273.  
  5274.    end Header;
  5275. --LINEFEED
  5276. begin
  5277.  
  5278.    if Page_It or Line_Number+10 > Page_Length then
  5279.       New_Page;
  5280.       Header;
  5281.    else
  5282.       Sub_Header;
  5283.    end if;
  5284.  
  5285.    Move_To_First_Item (List, Within_List);
  5286.    While Within_List loop
  5287.       Get (List, Rec);
  5288.  
  5289.       if Line_Number < 5 then
  5290.          Header;
  5291.       end if;
  5292.  
  5293.       Set_Column (1);
  5294.       Write (Rec.By_Node, Report);
  5295.  
  5296.       Set_Column (23);
  5297.       Write (Pretty_Float(Rec.Node_Mean_Tours), Report);
  5298.  
  5299.       Set_Column (47);
  5300.       Write (Pretty_Float(Rec.Node_Var_Tours), Report, Single);
  5301.  
  5302.       Move_To_Next_Item (List, Within_List);
  5303.    end loop;
  5304.  
  5305.    Write ("", Report, Single);
  5306.  
  5307.    Set_Column (1);
  5308.    Write ("Total", Report);
  5309.  
  5310.    Set_Column (23);
  5311.    Write (Pretty_Float(Mean_Tours), Report);
  5312.  
  5313.    Set_Column (47);
  5314.    Write (Pretty_Float(Var_Tours), Report);
  5315.  
  5316.    Write (" ", Report, Double);
  5317.  
  5318. end Report_Routing;
  5319. --LINEFEED
  5320. procedure Report_Service  (Starting_name  : in     NodeName;
  5321.                            Return_Name    : in     NodeName;
  5322.                            Tot_Mean_Serv  : in     Real;
  5323.                            Tot_Residence  : in     Real;
  5324.                            List           : in out ServiceList;
  5325.                            Page_It        : Boolean:= False) is
  5326.  
  5327.    T           : Time := Clock;
  5328.    Rec         : ServiceData;
  5329.    Within_List : Boolean;
  5330.    Start_Page  : Positive := Positive(MMI_IO.Page_Number);
  5331.  
  5332. ------------------------------------------------------------------------
  5333.  
  5334.    procedure Sub_Header is
  5335.  
  5336.    begin
  5337.  
  5338.       Write ("Start At Node: " & Short(Starting_Name) &
  5339.          "  Return To Node: " & Short(Return_Name), Report, Double);
  5340.       Write ("Node            Service Requirement   " &
  5341.          " Service Requirement   Residence Time", Report, Single);
  5342.       Write ("Name                   Mean           " &
  5343.          "      Variance              Mean     ", Report, Single);
  5344.       Header_Separator (75);
  5345.  
  5346.    end Sub_Header;
  5347.  
  5348. ------------------------------------------------------------------------
  5349.  
  5350.    procedure Header is
  5351.  
  5352.    begin
  5353.  
  5354.       Print_Title ("Service Requirements", "Page " &
  5355.          Strng(Txt(Page_Number(Start_Page))), T);
  5356.       Sub_Header;
  5357.  
  5358.    end Header;
  5359. --LINEFEED
  5360. begin
  5361.  
  5362.    if Page_It or Line_Number+10 > Page_Length then
  5363.       New_Page;
  5364.       Header;
  5365.    else
  5366.       Sub_Header;
  5367.    end if;
  5368.  
  5369.    Move_To_First_Item (List, Within_List);
  5370.    While Within_List loop
  5371.       Get (List, Rec);
  5372.  
  5373.       if Line_Number < 5 then
  5374.          Header;
  5375.       end if;
  5376.  
  5377.       Set_Column (1);
  5378.       Write (Rec.By_Node, Report);
  5379.  
  5380.       Set_Column (21);
  5381.       Write (Pretty_Float(Rec.Serv_Reqt_Mean), Report);
  5382.  
  5383.       Set_Column (44);
  5384.       Write (Pretty_Float(Rec.Serv_Reqt_Var), Report);
  5385.  
  5386.       Set_Column (64);
  5387.       Write (Pretty_Float(Rec.Mean_Residence), Report, Single);
  5388.  
  5389.       Move_To_Next_Item (List, Within_List);
  5390.    end loop;
  5391.  
  5392.    Write ("", Report, Single);
  5393.  
  5394.    Set_Column (1);
  5395.    Write ("Total", Report);
  5396.  
  5397.    Set_Column (21);
  5398.    Write (Pretty_Float(Tot_Mean_Serv), Report);
  5399.  
  5400.    Set_Column (64);
  5401.    Write (Pretty_Float(Tot_Residence), Report);
  5402.  
  5403.    Write (" ", Report, Double);
  5404.  
  5405. end Report_Service;
  5406. --LINEFEED
  5407. procedure Report_Serv_Times  (List: in out ServTimeList) is
  5408.  
  5409.    Rec            : ServTimeData;
  5410.    Within_List    : Boolean;
  5411.    T              : Time := Clock;
  5412.    C              : CoxianDist;
  5413.    type             IntArray is array (1 .. 3) of Integer;
  5414.    Coxian_Col     : IntArray := (61, 35, 48);
  5415.    Start_Page     : Positive := Positive(MMI_IO.Page_Number);
  5416.  
  5417. ------------------------------------------------------------------------
  5418.  
  5419.    procedure Header is
  5420.  
  5421.    begin
  5422.  
  5423.       Print_Title ("Service Time", "Page " &
  5424.          Strng(Txt(Page_Number(Start_Page))), T);
  5425.       Write ("Node              Service        Mean Service  " &
  5426.              "  Service Time    Coefficient of", Report, Single);
  5427.       Write ("Name            Distribution         Time       " &
  5428.           "    Variance        Variation", Report, Single);
  5429.       Header_Separator (79);
  5430.  
  5431.    end Header;
  5432. --LINEFEED
  5433. begin
  5434.  
  5435.    New_Page;
  5436.    Header;
  5437.  
  5438.    Move_To_First_Item (List, Within_List);
  5439.    while Within_List loop
  5440.       Get (List, Rec);
  5441.  
  5442.       if Rec.Serv_Funct.Serv_Dist = Coxian and then
  5443.          ((Rec.Serv_Funct.Coxian_Dist.Num_Coxian_Stages/3)+1)*2 +
  5444.          3 + Line_Number >= Page_Length then
  5445.             New_Page;
  5446.       elsif Line_Number + 4 >= Page_Length then
  5447.             New_Page;
  5448.       end if;
  5449.  
  5450.       if Line_Number < 5 then
  5451.          Header;
  5452.       end if;
  5453.  
  5454.       Set_Column (1);
  5455.       Write (Rec.Node_Name, Report);
  5456.  
  5457.       Set_Column (17);
  5458.       Write (ServDist'Image(Rec.Serv_Funct.Serv_Dist), Report);
  5459.  
  5460.       Set_Column (35);
  5461.       Write (Pretty_Float(Rec.Mean_Serv_Time), Report);
  5462.  
  5463.       Set_Column (52);
  5464.       Write (Pretty_Float(Rec.Serv_Time_Var), Report);
  5465.  
  5466.       Set_Column (68);
  5467.       Write (Pretty_Float(Rec.Coeff_Var), Report, Double);
  5468. --LINEFEED      
  5469.     Set_Column (17);
  5470.       case Rec.Serv_Funct.Serv_Dist is
  5471.          when Exponential =>
  5472.             Write ("Service Rate:", Report);
  5473.             Set_Column (35);
  5474.             Write (Pretty_Float(Real(Rec.Serv_Funct.Expon_Rate)),
  5475.                    Report, Single);
  5476.          when Erlang      =>
  5477.             Write ("Number of Stages:", Report);
  5478.  
  5479.             Set_Column (35);
  5480.             Write (Pretty_Natural(Rec.Serv_Funct.Num_Erlang_Stages),
  5481.                    Report, Single);
  5482.             Set_Column (17);
  5483.             Write ("Service Rate    :", Report);
  5484.  
  5485.             Set_Column (35);
  5486.             Write (Pretty_Float(Real(Rec.Serv_Funct.Erlang_Rate)),
  5487.                    Report, Single);
  5488.          when Coxian      =>
  5489.             C := Rec.Serv_Funct.Coxian_Dist;
  5490.             Write ("Number of Stages:", Report);
  5491.  
  5492.             Set_Column (35);
  5493.             Write (Pretty_Natural(C.Num_Coxian_Stages), Report, Single);
  5494.  
  5495.             Set_Column (17);
  5496.             Write ("Service Rates   :", Report);
  5497.             For Stagex in 1 .. C.Num_Coxian_Stages loop
  5498.                Set_Column (Coxian_Col((Stagex Mod 3)+1));
  5499.                Write (Pretty_Float(Real(C.Coxian_Rates(Stagex))),
  5500.                       Report);
  5501.                if (Stagex mod 3) = 0 then
  5502.                   Write (" ", Report, Single);
  5503.                end if;
  5504.             end loop;
  5505.  
  5506.             Set_Column (17);
  5507.             Write ("Cbranch Probs   :", Report);
  5508.             For Stagex in 1 .. C.Num_Coxian_Stages-1 loop
  5509.                Set_Column (Coxian_Col((Stagex Mod 3)+1)+2);
  5510.                Write (Pretty_Prob(C.Contin_Probs(Stagex)), Report);
  5511.                if (Stagex mod 3) = 0 then
  5512.                   Write (" ", Report, Single);
  5513.                end if;
  5514.             end loop;
  5515.  
  5516.       end case;
  5517.  
  5518.       Write ("", Report, Double);
  5519.       Move_To_Next_Item (List, Within_List);
  5520.  
  5521.    end loop;
  5522.  
  5523.    Write ("", Report, Double);
  5524.  
  5525. end Report_Serv_Times;
  5526. --LINEFEED
  5527. procedure Set_Title  (Title : in String) is
  5528.  
  5529. begin
  5530.  
  5531.    Model_Title := Txt(Title);
  5532.  
  5533. end Set_Title;
  5534.  
  5535. end Reports;
  5536. --LINEFEED
  5537. with Gen_List_Handler;
  5538. with Global_Types; use Global_Types;
  5539. --**********************************************************************
  5540. package Net_Stats is 
  5541. --======================================================================
  5542. --     ****    CLOSED MODEL STATISTICAL PACKAGE  ****
  5543. -- Computational and Display Modules for the QSAP program. Calculate_Stats
  5544. --  must be invoked prior to calling any of the Display Modules in order
  5545. --  to setup intermediate results required by these display Modules. 
  5546. --  Each Display module will perform further calculations and then
  5547. --======================================================================
  5548.  
  5549.   UNSTABLE_SOLUTION : exception;
  5550. --=====================================================================
  5551. --   UNSTABLE_SOLUTION exception is raised when any equation produces
  5552. --     a result that is unrealistic or causes a numeric_error. Many
  5553. --     equations will produce very small or very large numbers. If these
  5554. --     numbers are beyond the machines capability, then no corrective 
  5555. --     action is attempted. Decreasing Num_Jobs or changing Serv_Rates 
  5556. --     seem to help avoid these situations. 
  5557. --=====================================================================
  5558.  
  5559.     package Node_List_Handler is new Gen_List_Handler(NodeName);
  5560.     type NodeList is new Node_List_Handler.ListType; 
  5561.         -- Creates a Linked-List of Node_Names that are passed to
  5562.         --   several of the Display routines. 
  5563.  
  5564.     --**********************************************************
  5565.     procedure Calculate_Stats( Num_Jobs : NumJobs);
  5566.          -- Restructures and Copies model data from package Network to
  5567.          -- package Net_Data_Pak (Global Data Storage). Calculates
  5568.          -- intermediate results which are stored in Net_Data_Pak.
  5569.  
  5570.     --*********************************************************
  5571.     procedure Display_PBranch;
  5572.          -- Displays Branching Probabilities.
  5573.  
  5574.     --*********************************************************
  5575.     procedure Display_Arrival_Freqs ( Node_List : NodeList);
  5576.       -- Calculates and displays Arrival Freqs for nodes specified in
  5577.       -- Nodelist.
  5578.  
  5579.     --********************************************************
  5580.     procedure Display_Serv_Times( Node_List : NodeList);
  5581.       -- Calculate and displays Service Times Report for nodes specified
  5582.       -- in NodeList.
  5583.  
  5584.     --*******************************************************
  5585.     procedure Display_Response_Times (Node_List : NodeList);
  5586.       -- Calculates and displays Response Times for nodes specified in
  5587.       -- Nodelist.
  5588. --LINEFEED
  5589.  
  5590.     --******************************************************
  5591.     procedure Display_Q_Lengths ( Node_List : NodeList);
  5592.       -- Calculates and displays Q_Lengths, thru_put, and Util.
  5593.  
  5594.     --*****************************************************
  5595.     procedure Display_GNorms;
  5596.       -- Displays all calculated normalization constants.
  5597.  
  5598.     --****************************************************
  5599.     procedure Display_Q_Length_Dists( Node_List : NodeList);
  5600.       -- Calculates and displays Q Length Distributions for nodes 
  5601.       -- specified in Nodelist.
  5602.  
  5603.     --***************************************************
  5604.     procedure Display_Routing (From: NodeList; 
  5605.                                 To : NodeList; 
  5606.                                 By : NodeList);
  5607.       --  Calculates and displays routing behavior between nodes
  5608.       --  specified in the FROM list to nodes specified in the TO 
  5609.       --  list and traveling by nodes specified in the BY list.
  5610.  
  5611.     --**************************************************
  5612.     procedure Display_Service(From : NodeList;
  5613.                               To   : NodeList; 
  5614.                               By   : NodeList);
  5615.       --  Calculates and displays service behavior between nodes
  5616.       --  specified in the FROM list to nodes specified in the 
  5617.       --  TO list and traveling by nodes specified in the BY list.
  5618. end Net_Stats;
  5619. --LINEFEED
  5620.     with Global_Types; use Global_Types;
  5621.     with Real_Mat_Pak; use Real_Mat_Pak;
  5622.     with Node_Servicer; use Node_Servicer;
  5623.     package Net_Data_Pak is
  5624.  
  5625.       -- Global Data used by Statistics and Display Packages
  5626.  
  5627.        type NodeStats is
  5628.           record
  5629.              Node_Def      : Nodedef;
  5630.              Moments       : NodeMoments(1..Nth_Order);
  5631.              Alpha         : Real      ;          -- Job Flow at Node
  5632.              Psi           : RealVector;          -- Equil Probability
  5633.              Aux           : RealVector;          -- Auxiliary Distribution
  5634.              Phi           : RealVector;          -- Queue Length Distribution 
  5635.              Thru_Put      : Real;                -- ThroughPut
  5636.              Util          : Real ;               -- Utilization
  5637.              Mean_Response : Real;
  5638.           end record;
  5639.  
  5640.        type NodesVector is array(NumNodes range <>) of NodeStats;
  5641.  
  5642.        type DynNetwork(Num_Nodes : NumNodes := 1) is
  5643.           record
  5644.             Nodes : NodesVector(1..Num_Nodes); 
  5645.           end record; 
  5646.  
  5647.       -- *** Network Global Data used in Statiscal Modules.
  5648.  
  5649.        Num_Jobs    : NumJobs;     -- Current Number of Jobs.
  5650.        Num_Nodes   : NumNodes;    -- Current Number of Nodes.
  5651.        PB          : RealMatrix;  -- RealMatrix of Branching Probs.
  5652.        Net         : DynNetwork;  -- Dyn Array of Nodal Data.
  5653.        GNorm       : RealVector;  -- RealVector of Normalization Consts.
  5654.  
  5655.        Scal_K      : Real := 0.0; -- Const. used for Betas and Thru_Put. 
  5656.  
  5657.        procedure Allocate_PB;
  5658.        procedure Allocate_GNorm ;
  5659.        procedure Allocate_Net ;
  5660.  
  5661. --LINEFEED
  5662.  
  5663.        function Node_Def_Of(At_Index : NumNodes) return NodeDef;
  5664.        procedure Assign_Node_Def (At_Index : NumNodes; Value : NodeDef);
  5665.  
  5666.        function Alpha  (At_Index : NumNodes) return Real;
  5667.        procedure Assign_Alpha(At_Index : NumNodes; Value : Real);
  5668.  
  5669.        function Psi        (At_Index : NumNodes ;
  5670.                             At_Job   : JobIndex) return Real;
  5671.        procedure Assign_Psi(At_Index : NumNodes;
  5672.                             At_Job   : JobIndex;
  5673.                             Value    : Real);
  5674.  
  5675.  
  5676.        function Aux ( At_Index   : NumNodes ;
  5677.                       At_Job     : JobIndex) return Real;
  5678.        procedure Assign_Aux(At_Index : NumNodes;
  5679.                             At_Job   : JobIndex;
  5680.                             Value    : Real);
  5681.  
  5682.        function Phi (At_Index    : NumNodes ;
  5683.                      At_Job      : JobIndex) return Real;
  5684.        procedure Assign_Phi(At_Index : NumNodes;
  5685.                             At_Job   : JobIndex;
  5686.                             Value    : Real);
  5687.  
  5688.        function Thru_Put        (At_Index : NumNodes) return Real;
  5689.        procedure Assign_Thru_Put(At_Index : NumNodes;
  5690.                              Value        : Real);
  5691.  
  5692.        function Util   (At_Index : NumNodes) return Real;
  5693.        procedure Assign_Util(At_Index : NumNodes;
  5694.                              Value    : Real);
  5695.  
  5696.        function Mean_Response (At_Index : NumNodes) return Real;
  5697.        procedure Assign_Mean_Response(At_Index : NumNodes;
  5698.                                       Value    : Real);
  5699.       
  5700.        function Index_To_Name ( Ith_Node  : NumNodes) return NodeName; 
  5701.        function Name_To_Index ( Node_Name : NodeName) return NumNodes;
  5702.  
  5703.        function GNorm_Value  ( At_Index : JobIndex) return Real;
  5704.        procedure Assign_GNorm( At_Index : JobIndex; Value : in Real);
  5705.  
  5706.        pragma InLine (Node_Def_Of,Assign_Node_Def);
  5707.        pragma InLine (Alpha,Assign_Alpha);
  5708.        pragma InLine (Psi,Assign_Psi);
  5709.        pragma InLine (Phi,Assign_Phi);
  5710.        pragma InLine (Aux,Assign_Aux);
  5711.        pragma InLine (Thru_Put,Assign_Thru_Put);
  5712.        pragma InLine (Util,Assign_Util);
  5713.        pragma InLine (Mean_Response,Assign_Mean_Response);
  5714.        pragma InLine (GNorm_Value,Assign_GNorm);
  5715.  
  5716.        Nodes_Array_Access_Exception : exception; 
  5717.     end Net_Data_Pak;
  5718.       
  5719.     --************************************************************
  5720. --LINEFEED
  5721.     with Text_IO; use Text_IO;
  5722.     package body Net_Data_Pak is 
  5723.        Net_Index : NumNodes;
  5724.  
  5725.        --******************************************************
  5726.        procedure Allocate_PB is
  5727.        begin
  5728.          PB := Allocate(Num_Nodes,Num_Nodes);
  5729.        end Allocate_PB;
  5730.           
  5731.        --******************************************************
  5732.        procedure Allocate_GNorm is 
  5733.        begin
  5734.          GNorm :=  Allocate(Map(Num_Jobs));
  5735.        end Allocate_Gnorm;
  5736.  
  5737.        --******************************************************
  5738.        procedure Allocate_Net is
  5739.          Dummy_Node : NodeDef;
  5740.          Empty_Node_Stats: NodeStats :=(Node_Def => Dummy_Node,
  5741.                                         Moments  => (1..Nth_Order => 0.0),
  5742.                                         Alpha    => 0.0,
  5743.                                         Psi      => Allocate(Map(Num_Jobs)),
  5744.                                         Aux      => Allocate(Map(Num_Jobs)),
  5745.                                         Phi      => Allocate(Map(Num_Jobs)),
  5746.                                         Thru_Put => 0.0,
  5747.                                         Util     => 0.0,
  5748.                                         Mean_Response => 0.0);
  5749.        begin
  5750.            Net := (Num_Nodes,(1..Num_Nodes => Empty_Node_Stats));
  5751.        end Allocate_Net;
  5752.  
  5753.        --******************************************************
  5754.        function Node_Def_Of(At_Index : NumNodes) return NodeDef is
  5755.        begin
  5756.          return Net.Nodes(At_Index).Node_Def;
  5757.        end Node_Def_Of;
  5758.  
  5759.        --******************************************************
  5760.        procedure Assign_Node_Def (At_Index : NumNodes; Value : NodeDef) is
  5761.        begin
  5762.          Net.Nodes(At_Index).Node_Def := Value;
  5763.        end Assign_Node_Def;
  5764.  
  5765.        --******************************************************
  5766.        function Alpha  (At_Index : NumNodes) return Real is
  5767.        begin
  5768.           return Net.Nodes(At_Index).Alpha;
  5769.        end Alpha;
  5770.  
  5771.        --******************************************************
  5772.        procedure Assign_Alpha(At_Index : NumNodes; Value : Real) is
  5773.        begin
  5774.           Net.Nodes(At_Index).Alpha := Value;
  5775.        end Assign_Alpha;
  5776.  
  5777.        --******************************************************
  5778.        function Psi    (At_Index : NumNodes ;
  5779.                         At_Job   : JobIndex) return Real is
  5780.        begin
  5781.           return Net.Nodes(At_Index).Psi.Vec(At_Job);
  5782.        end Psi;
  5783.  
  5784.        --******************************************************
  5785.        procedure Assign_Psi(At_Index : NumNodes;
  5786.                             At_Job   : JobIndex;
  5787.                             Value    : Real) is
  5788.        begin
  5789.           Net.Nodes(At_Index).Psi.Vec(At_Job) := Value;
  5790.        end Assign_Psi;
  5791.  
  5792.        --******************************************************
  5793.        function Phi (At_Index    : NumNodes ;
  5794.                      At_Job      : JobIndex) return Real is
  5795.        begin
  5796.           return Net.Nodes(At_Index).Phi.Vec(At_Job);
  5797.        end Phi;
  5798.  
  5799.        --******************************************************
  5800.        procedure Assign_Phi(At_Index : NumNodes;
  5801.                             At_Job   : JobIndex;
  5802.                             Value    : Real) is
  5803.        begin
  5804.           Net.Nodes(At_Index).Phi.Vec(At_Job) := Value;
  5805.        end Assign_Phi;
  5806. --LINEFEED
  5807.  
  5808.        --******************************************************
  5809.        function Aux ( At_Index   : NumNodes ;
  5810.                       At_Job     : JobIndex) return Real is
  5811.        begin
  5812.           return Net.Nodes(At_Index).Aux.Vec(At_Job);
  5813.        end Aux;
  5814.  
  5815.        --******************************************************
  5816.        procedure Assign_Aux(At_Index : NumNodes;
  5817.                             At_Job   : JobIndex;
  5818.                             Value    : Real) is
  5819.        begin
  5820.           Net.Nodes(At_Index).Aux.Vec(At_Job) := Value;
  5821.        end Assign_Aux;
  5822.  
  5823.        --******************************************************
  5824.        function Thru_Put        (At_Index : NumNodes) return Real is
  5825.        begin
  5826.           return Net.Nodes(At_Index).Thru_Put;
  5827.        end Thru_Put;
  5828.  
  5829.        --******************************************************
  5830.        procedure Assign_Thru_Put(At_Index : NumNodes;
  5831.                              Value        : Real) is
  5832.        begin
  5833.           Net.Nodes(At_Index).Thru_Put := Value;
  5834.        end Assign_Thru_Put;
  5835.  
  5836.        --******************************************************
  5837.        function Util   (At_Index : NumNodes) return Real is
  5838.        begin
  5839.           return Net.Nodes(At_Index).Util;
  5840.        end Util;
  5841.  
  5842.        --******************************************************
  5843.        procedure Assign_Util(At_Index : NumNodes;
  5844.                              Value    : Real) is
  5845.        begin
  5846.           Net.Nodes(At_Index).Util := Value;
  5847.        end Assign_Util;
  5848. --LINEFEED
  5849.  
  5850.        --******************************************************
  5851.        function Mean_Response (At_Index : NumNodes) return Real is
  5852.        begin
  5853.           return Net.Nodes(At_Index).Mean_Response;
  5854.        end Mean_Response;
  5855.  
  5856.        --******************************************************
  5857.        procedure Assign_Mean_Response(At_Index : NumNodes;
  5858.                                       Value    : Real) is
  5859.        begin
  5860.           Net.Nodes(At_Index).Mean_Response := Value;
  5861.        end Assign_Mean_Response;
  5862.                                                       
  5863.  
  5864.        --******************************************************
  5865.        function GNorm_Value  ( At_Index : JobIndex) return Real is
  5866.        begin
  5867.           return Value_Of(GNorm,At_Index);
  5868.        end GNorm_Value;
  5869.  
  5870.        --******************************************************
  5871.        procedure Assign_GNorm ( At_Index : JobIndex; Value : in Real) is
  5872.        begin
  5873.           Assign(GNorm, At_Index, Value);
  5874.        end Assign_GNorm;
  5875. --LINEFEED
  5876.  
  5877.        --******************************************************
  5878.        procedure Move_To_Next_Index is
  5879.        begin
  5880.          if Net_Index in Net.Nodes'first .. Net.Nodes'Last -1 then
  5881.            Net_Index := Net_Index + 1;
  5882.          else
  5883.            Net_Index := Net.Nodes'first;
  5884.          end if;
  5885.        end Move_To_Next_Index;
  5886.  
  5887.        --******************************************************
  5888.        function Index_To_Name ( Ith_Node : NumNodes) return NodeName is 
  5889.        begin
  5890.          return Name_Of_Node(Net.Nodes(Ith_Node).Node_Def);
  5891.        end Index_To_Name;
  5892.  
  5893.  
  5894.        --******************************************************
  5895.        function Name_To_Index ( Node_Name : NodeName) return NumNodes is
  5896.          Old_Index : NumNodes := Net_Index;
  5897.        begin 
  5898.          if Net_Index not in Net.Nodes'range then
  5899.            Net_Index := Net.Nodes'first;
  5900.          end if;
  5901.          for I in 1 .. Num_Nodes loop
  5902.            if Name_Of_Node(Node_Def_Of(Net_Index)) = Node_Name then
  5903.               return Net_Index;
  5904.            end if;
  5905.            Move_To_Next_Index;
  5906.          end loop;
  5907.          Net_Index := Old_Index;
  5908.          Put("Node_Name : "); Put(Node_Name); Put_Line("not found in Network");
  5909.          raise Constraint_Error;
  5910.        end Name_To_Index;
  5911.    end Net_Data_Pak;
  5912. --LINEFEED
  5913. with Network;use Network;
  5914. with Node_Servicer; use Node_Servicer;
  5915. with Report_Types ; use Report_Types;
  5916. with Report_Lists; use Report_Lists;
  5917. with Reports; use Reports;
  5918. with Net_Data_Pak; use Net_Data_Pak;
  5919. with Gen_Math; 
  5920. with Gen_Factorials;
  5921. with Text_IO; use Text_Io;
  5922. with Real_Mat_Pak; use Real_Mat_Pak;
  5923. --************************************************************
  5924. package body Net_Stats is
  5925.  
  5926.  
  5927.  
  5928.     package Math_Pak is new Gen_Math(Real,Integer); use Math_Pak;
  5929.     package Fact_Pak is new Gen_Factorials(Real,Integer); use Fact_Pak;
  5930.  
  5931.     -- Many routines receive a list of Node_Names. The following type
  5932.     -- and associated routines provide a quick matching mechanism 
  5933.     -- between the Node_Names and the corresponding Indices of the
  5934.     -- array Nodes (stored in Net_Data_Pak).
  5935.  
  5936.     type NodeIndexData is
  5937.         record
  5938.            Node_Name  : NodeName;
  5939.            Index      : NumNodes;
  5940.         end record;
  5941.  
  5942.      package Node_Index_List_Handler is new Gen_List_Handler(NodeIndexData);
  5943.      type NodeIndexList is new Node_Index_List_Handler.ListType;
  5944.  
  5945.     --**************************************************************
  5946.     function Make_Index_List ( Node_List : NodeList)
  5947.                                    return NodeIndexList is separate;
  5948.                                              
  5949.     --**************************************************************
  5950.     function Is_Match (Search_The_List: NodeIndexList ; 
  5951.                        For_Node_Index : NumNodes) 
  5952.                                         return Boolean is separate;  
  5953.  
  5954.               -- Special SUMMATION Routines
  5955.     --************************************************************
  5956.     function Queue_Sigma ( Start_Index : NumJobs;
  5957.                            End_Index   : NumJobs;
  5958.                            Order       : NumMoments;
  5959.                            Q_Lengths   : RealVector)
  5960.                                            return Real is separate;
  5961.  
  5962.  
  5963.  
  5964.     --************************************************************
  5965.     function FCFS_Sigma1 (Jobs        : NumJobs;
  5966.                           Num_Servers : NumServers ; 
  5967.                           FCFS_Phi    : RealVector )
  5968.                                          return Real is separate;
  5969.  
  5970.     --************************************************************
  5971.     function FCFS_Sigma2 (Jobs        : NumJobs;
  5972.                           Num_Servers : NumServers ; 
  5973.                           FCFS_Phi    : RealVector )
  5974.                                           return Real is separate;
  5975.  
  5976.     --************************************************************
  5977.     function Calculate_FCFS_Phi(Ith_Node: NumNodes ; Jobs: NumJobs ) 
  5978.                                      return RealVector is separate;
  5979.   
  5980.                  -- Bodies for Visible Subprograms
  5981.  
  5982.     procedure Calculate_Stats( Num_Jobs:NumJobs) is separate;
  5983.  
  5984.     procedure Display_Pbranch is separate;
  5985.  
  5986.     procedure Display_Arrival_Freqs ( Node_List : NodeList) 
  5987.                                                    is separate;
  5988.  
  5989.     procedure Display_Serv_Times(Node_List: NodeList) is separate;
  5990.  
  5991.     procedure Display_GNorms is separate;
  5992.  
  5993.     procedure Display_Response_Times (Node_List : NodeList)
  5994.                                                     is separate;
  5995.  
  5996.     procedure Display_Q_Length_Dists( Node_List : NodeList)
  5997.                                                     is separate;
  5998.  
  5999.     procedure Display_Q_Lengths(Node_List: NodeList) is separate; 
  6000.  
  6001.     procedure Display_Routing (From: NodeList;
  6002.                                 To : NodeList;
  6003.                                 By : NodeList) is separate;
  6004.  
  6005.     procedure Display_Service(From: NodeList;
  6006.                                To : NodeList;
  6007.                                By : NodeList) is separate;
  6008.  
  6009.     
  6010. end Net_Stats; 
  6011. --LINEFEED
  6012. separate (Net_Stats)
  6013. --**************************************************************
  6014. function Is_Match (Search_The_List: NodeIndexList ; 
  6015.                    For_Node_Index : NumNodes) return Boolean is    
  6016.    --=============================================================
  6017.    -- Searchs the NodeIndexList for a match between For_Node_Index
  6018.    -- and the list of indices stored in NodeIndexList. 
  6019.    --=============================================================
  6020.  
  6021.      Is_Within_List  : Boolean;
  6022.      Node_Index_Data : NodeIndexData;
  6023.      Local_Node_List : NodeIndexList := Search_The_List;
  6024.      --==========================
  6025.      use Node_Index_List_Handler;
  6026.   begin
  6027.      Move_To_First_Item(Local_Node_List,Is_Within_List);
  6028.      while Is_Within_List loop
  6029.        Get(From => Local_Node_List , The_Value => Node_Index_Data); 
  6030.        if For_Node_Index = Node_Index_Data.Index then
  6031.           return True;
  6032.        end if;
  6033.        Move_To_Next_Item(Local_Node_List,Is_Within_List);
  6034.      end loop;
  6035.      return False;
  6036. end Is_Match;
  6037. --LINEFEED
  6038.  
  6039. separate (Net_Stats)
  6040.  --*********************************************************
  6041. function Make_Index_List ( Node_List : NodeList) 
  6042.                                      return NodeIndexList is
  6043.    --=======================================================
  6044.    -- Makes a NodeIndexList containing Node_Names and the 
  6045.    -- Corresponding indices of the array Nodes.
  6046.    --======================================================
  6047.      Node_Index_Data : NodeIndexData;
  6048.      Node_Index_List : NodeIndexList;
  6049.      Is_Within_List  : Boolean;
  6050.      Node_Name       : NodeName;
  6051.      Ith_Node        : NumNodes;
  6052.      Local_Node_List : NodeList := Node_List;
  6053.    --=========================
  6054.    use Node_Index_List_Handler;
  6055. begin
  6056.            
  6057.     Move_To_First_Item(Local_Node_List,Is_Within_List);
  6058.     while Is_Within_List loop
  6059.       Get(From => Local_Node_List, The_Value =>Node_Name);
  6060.       Ith_Node       := Name_To_Index(Node_Name);
  6061.       Node_Index_Data := (Node_Name , Ith_Node);
  6062.  
  6063.       Insert (Onto         => Node_Index_List, 
  6064.               The_Value    => Node_Index_Data,
  6065.               Where        => After);
  6066.  
  6067.  
  6068.       Move_To_Next_Item ( On           => Local_Node_List,
  6069.                           Within_List  => Is_Within_List);
  6070.    end loop;
  6071.    return Node_Index_List;
  6072. end Make_Index_List;
  6073. --LINEFEED
  6074. separate (Net_Stats)
  6075. --************************************************************
  6076. function Queue_Sigma ( Start_Index : NumJobs;
  6077.                        End_Index   : NumJobs;
  6078.                        Order       : NumMoments;
  6079.                        Q_Lengths   : RealVector) return Real is
  6080.    --=========================================================
  6081.    -- Summation Operator used in calculating Mean Queue
  6082.    -- Length (Eq. 1.2.0.12).
  6083.    --=========================================================
  6084.    Sum : Real := 0.0;
  6085.    Kth : NumMoments renames Order;
  6086.    --===============
  6087.    use Net_Data_Pak;
  6088. begin
  6089.    for Mth_Job  in Start_Index .. End_Index loop
  6090.        Sum := Sum+ Real(Mth_Job** Kth) * 
  6091.                           Value_Of(Q_Lengths,Map(Mth_Job)); 
  6092.    end loop;
  6093.    return Sum;
  6094. end Queue_Sigma;
  6095.  
  6096. separate (Net_Stats)
  6097. --***************************************************************
  6098. function FCFS_Sigma1 (Jobs         : NumJobs;
  6099.                        Num_Servers : NumServers ; 
  6100.                        FCFS_Phi    : RealVector ) return Real is
  6101.    --====================================================
  6102.    -- Summation Operator used in calculating First Moment 
  6103.    -- Response time (Eq. 1.2.0.18)
  6104.    --====================================================
  6105.  
  6106.     Sum : Real:=0.0;
  6107.     --=====================
  6108.     use Net_Data_Pak;
  6109. begin
  6110.      for  Ith_Job in 0 .. (Jobs -  Num_Servers) loop  
  6111.         Sum := Sum + Real(Ith_Job + 1) /Real(Num_Servers) *
  6112.                    Value_Of(FCFS_Phi, Map(Ith_Job + Num_Servers));
  6113.      end loop;
  6114.      return Sum;
  6115. end FCFS_Sigma1; 
  6116.  
  6117. separate (Net_Stats)
  6118. --******************************************************
  6119. function FCFS_Sigma2 (Jobs         : NumJobs;
  6120.                        Num_Servers : NumServers ; 
  6121.                        FCFS_Phi    : RealVector ) return Real is
  6122.    --=====================================================
  6123.    -- Summation Operator used in calculating Second Moment 
  6124.    --   Response  1.2.0.19)
  6125.    --====================================================
  6126.  
  6127.     Sum : Real:=0.0;
  6128.     --======================
  6129.     use Net_Data_Pak;
  6130. begin
  6131.     for  Ith_Job in 0 .. (Jobs - Num_Servers) loop  
  6132.        Sum := Sum + Real(Ith_Job + 1) /Real(Num_Servers) *
  6133.                 Value_Of(FCFS_Phi,Map(Ith_Job + Num_Servers)) *
  6134.                 (Real(Ith_Job + 2)/ Real(Num_Servers) + 2.0);
  6135.     end loop;
  6136.     return Sum;
  6137. end FCFS_Sigma2; 
  6138. --LINEFEED
  6139. separate (Net_Stats)
  6140. --*******************************************************
  6141. function Calculate_FCFS_Phi(Ith_Node : NumNodes ;
  6142.                              Jobs    : NumJobs ) 
  6143.                                     return RealVector is
  6144. --==================================================
  6145. --   Calculates Phis used in Eq. 1.2.0.18
  6146. --==================================================
  6147.    FCFS_Phi: RealVector(Map(Jobs));
  6148.    Psi_Value : Real;
  6149.    Aux_Value : Real;
  6150.    G_Value   : Real;
  6151.    --=======================
  6152.    use Net_Data_Pak;
  6153. begin
  6154.    for Ith_Job in 0 .. Jobs loop
  6155.       Psi_Value := Psi(Ith_Node,Map(Ith_Job));
  6156.       Aux_Value := Aux(Ith_Node,Map(Jobs - Ith_Job)); 
  6157.       G_Value := GNorm_Value(Map(Jobs));
  6158.       begin
  6159.          FCFS_Phi.Vec(Map(Ith_Job)) := Psi_Value* Aux_Value/ G_Value;
  6160.       exception
  6161.          when others =>
  6162.             FCFS_Phi.Vec(Map(Ith_Job)):= Psi_Value/G_Value*Aux_Value;
  6163.       end;
  6164.    end loop;
  6165.    return FCFS_Phi;
  6166. end Calculate_FCFS_Phi;
  6167. --LINEFEED
  6168. separate (Net_Stats)
  6169. --***************************************************************
  6170. procedure Display_PBranch is
  6171.   --=============================================================
  6172.   -- Extracts Branching Probs from Net_Data_Pak and sends results 
  6173.   -- to Reports.Report_Arrival_Freqs. 
  6174.   --=============================================================
  6175.    PBranch_List : PBranchList;
  6176.    PBranch_Data : PBranchData;
  6177.    --=======================
  6178.    use PBranch_List_Handler;
  6179.    use Net_Data_Pak;
  6180.    
  6181. begin
  6182.    for Ith_Node in 1 .. Num_Nodes loop
  6183.      PBranch_Data.Node_Name := Index_To_Name(Ith_Node);
  6184.      PBranch_Data.PBranch := Extract_Row(PB,Ith_Node);
  6185.  
  6186.      Insert ( Onto      => PBranch_List ,
  6187.               The_Value => PBranch_Data ,
  6188.               Where     => After);
  6189.    end loop;
  6190.  
  6191.    Reports.Report_PBranch(PBranch_List);
  6192.    Dispose (PBranch_List);
  6193. end Display_PBranch;
  6194. --LINEFEED
  6195.  separate (Net_Stats)
  6196. --***************************************************************
  6197.  procedure Display_Arrival_Freqs ( Node_List : NodeList) is 
  6198.   --==============================================================
  6199.   -- Extracts Alphas from Net_Data_Pak, calculates Relative Arrival
  6200.   -- Frequencies and sends results to Reports.Report_Arrival_Freqs. 
  6201.   --===============================================================
  6202.    Node_Name        : NodeName;
  6203.    Node_Def         : NodeDef;
  6204.    Ith_Node         : NumNodes;
  6205.    Serv_Disc        : ServDisc;
  6206.    Arrival_List     : ArrivalList;
  6207.    Arrival_Data     : ArrivalData;
  6208.    Is_Within_List   : Boolean;
  6209.    Alpha_Sum        : Real;
  6210.    Local_Node_List  : NodeList := Node_List; 
  6211.    --=============================
  6212.    use Arrival_List_Handler;
  6213.    use Net_Data_Pak;
  6214.  
  6215.    function Sum_Alphas(N_Nodes:NumNodes) return Real is separate; 
  6216.  
  6217.  begin
  6218.  
  6219.     Move_To_First_Item(Local_Node_List,Is_Within_List);
  6220.     while Is_Within_List loop
  6221.         Get(From => Local_Node_List, The_Value =>Node_Name);
  6222.         Ith_Node  := Name_To_Index( Node_Name );
  6223.         Node_Def  := Node_Def_Of(Ith_Node);
  6224.         Serv_Disc := Node_Serv_Disc(Node_Def);
  6225.  
  6226.         Alpha_Sum := Sum_Alphas(Num_Nodes);
  6227.  
  6228.         Arrival_Data:=(Node_Name        => Node_Name,
  6229.                        Num_Servers      => Serv_Disc.Num_Servers,
  6230.                        Serv_Mode        => Serv_Disc.Serv_Mode,
  6231.                        Rel_Arrival_Freq => Alpha(Ith_Node)/ Alpha_Sum ); 
  6232.  
  6233.         Insert ( Onto      => Arrival_List ,
  6234.                  The_Value => Arrival_Data,
  6235.                  Where     => After);
  6236.  
  6237.         Move_To_Next_Item (On          => Local_Node_List,
  6238.                            Within_List => Is_Within_List);
  6239.    end loop;
  6240.    Report_Arrival_Freqs( Arrival_List);
  6241.    Dispose(Arrival_List);
  6242. exception
  6243.     when Numeric_Error =>
  6244.        Put_Line("Numeric Error raised in Display_Arrival_Freqs");
  6245.        raise UNSTABLE_SOLUTION;
  6246.     when others =>
  6247.        Put_Line("Exception raised in Display_Arrival_Freqs");
  6248.        raise;
  6249. end Display_Arrival_Freqs;
  6250.  
  6251.  
  6252.  separate (Net_Stats.Display_Arrival_Freqs)
  6253.  --*****************************************
  6254.  function Sum_Alphas(N_Nodes:NumNodes) return Real is 
  6255.    Sum : Real := 0.0;
  6256.    --==================== 
  6257.      use Net_Data_Pak;
  6258.  begin
  6259.    for Ith_Node in 1 .. N_Nodes loop
  6260.       Sum := Sum + Alpha(Ith_Node);
  6261.    end loop;
  6262.    return Sum;
  6263.  end Sum_Alphas;
  6264. --LINEFEED
  6265.  separate (Net_Stats)
  6266. --***************************************************************
  6267.  procedure Display_Serv_Times( Node_List : NodeList) is 
  6268.   --=============================================================
  6269.   -- Extracts Service Times for requested nodes and sends results 
  6270.   -- to Reports.Report_Serv_Times. 
  6271.   --=============================================================
  6272.     Is_Within_List :  Boolean;
  6273.     Node_Name      : NodeName;
  6274.     Node_Def       : NodeDef;
  6275.     Ith_Node       : NumNodes;
  6276.     Serv_Funct     : ServFunct;
  6277.     M1,M2,Var      : Real;
  6278.     Serv_Time_List : ServTimeList;
  6279.     Serv_Time_Data : ServTimeData;
  6280.     Local_Node_List: NodeList := Node_List;
  6281.     --=========================
  6282.     use Serv_Time_List_Handler;
  6283.     use Net_Data_Pak;
  6284.  begin
  6285.     Move_To_First_Item(Local_Node_List,Is_Within_List);
  6286.     while Is_Within_List loop
  6287.        Get(From => Local_Node_List, The_Value =>Node_Name);
  6288.        Ith_Node       := Name_To_Index(Node_Name);
  6289.        Node_Def       := Node_Def_Of(Ith_Node);
  6290.        Serv_Funct     := Node_Serv_Funct(Node_Def);
  6291.        M1             := Net.Nodes(Ith_Node).Moments(1);
  6292.        M2             := Net.Nodes(Ith_Node).Moments(2);
  6293.        Var            := M2 - M1 * M1;
  6294.  
  6295.        Serv_Time_Data := (Node_Name       => Node_Name,
  6296.                           Serv_Funct      => Serv_Funct,
  6297.                           Mean_Serv_Time  => M1,
  6298.                           Serv_Time_Var   => Var,
  6299.                           Coeff_Var       => Sqrt(Var)/M1); 
  6300.  
  6301.        Insert (Onto         => Serv_Time_List,  
  6302.                The_Value    => Serv_Time_Data,
  6303.                Where        => After);
  6304.  
  6305.        Move_To_Next_Item ( On           => Local_Node_List,
  6306.                            Within_List  => Is_Within_List);
  6307.     end loop;
  6308.     Report_Serv_Times( Serv_Time_List );
  6309.     Dispose(Serv_Time_List); 
  6310. exception
  6311.     when Numeric_Error =>
  6312.        Put_Line("Numeric Error raised in Display_Serv_Times");
  6313.        raise UNSTABLE_SOLUTION;
  6314.     when others =>
  6315.        Put_Line("Exception raised in Display_Serv_Times");
  6316.        raise;
  6317. end Display_Serv_Times;
  6318. --LINEFEED
  6319.  separate (Net_Stats)
  6320.  --**********************************************************
  6321.  procedure Display_Q_Lengths( Node_List : NodeList) is 
  6322.   --===========================================================
  6323.   -- Calculates Q_Lengths (Mean and Variance) and sends results 
  6324.   -- to Reports.Report_Q_Lengths. 
  6325.   --===========================================================
  6326.    Is_Within_List   : Boolean;
  6327.    Ith_Node         : NumNodes;
  6328.    Node_Name        : NodeName;
  6329.    Phi_Values       : RealVector;
  6330.    Q_L1, Q_L2,Q_Var : Real;
  6331.    Q_Length_Data    : QLengthData;
  6332.    Q_Length_List    : QLengthList;
  6333.    Local_Node_List  : NodeList := Node_List ;
  6334.    --==============================
  6335.    use Q_Length_List_Handler;
  6336.    use Net_Data_Pak;
  6337. begin
  6338.     Move_To_First_Item(Local_Node_List,Is_Within_List);
  6339.     while Is_Within_List loop
  6340.        Get(From => Local_Node_List, The_Value =>Node_Name);
  6341.        Ith_Node       := Name_To_Index(Node_Name);
  6342.        Phi_Values     := Net.Nodes(Ith_Node).Phi;
  6343.                                 --**************           1 
  6344.                                 -- Eq. 1.2.1.12   E([Q (M)] )
  6345.                                 --**************      i
  6346.        Q_L1           := Queue_Sigma ( Start_Index=> 1 ,   
  6347.                                        End_Index  => Num_Jobs ,
  6348.                                        Order      => 1,
  6349.                                        Q_Lengths  => Phi_Values); 
  6350.        
  6351.                                 --**************           2 
  6352.                                 -- Eq. 1.2.1.12   E([Q (M)] )
  6353.                                 --**************      i
  6354.        Q_L2           := Queue_Sigma ( Start_Index=> 1 ,
  6355.                                        End_Index  => Num_Jobs ,
  6356.                                        Order      => 2,
  6357.                                        Q_Lengths  => Phi_Values);
  6358.  
  6359.                                 --**************     
  6360.                                 -- Eq. 1.2.1.13   Var([Q (M)] )
  6361.                                 --**************        i
  6362.        Q_Var          := Q_L2 - Q_L1 * Q_L1; 
  6363.  
  6364.        Q_Length_Data := ( Node_Name     => Node_Name ,
  6365.                           Q_Length_Mean => Q_L1 ,
  6366.                           Q_Length_Var  => Q_Var,
  6367.                           Coeff_Var     => Sqrt(Abs(Q_Var))/Q_L1, 
  6368.                           Thru_Put      => Thru_Put(Ith_Node),
  6369.                           Util          => Util(Ith_Node));
  6370.        Insert (Onto         => Q_Length_List,  
  6371.                The_Value    => Q_Length_Data,
  6372.                Where        => After);
  6373.  
  6374.        Move_To_Next_Item ( On           => Local_Node_List,
  6375.                            Within_List  => Is_Within_List);
  6376.     end loop;
  6377.     Report_Q_Lengths( Q_Length_List);
  6378.     Dispose(Q_Length_List); 
  6379. exception
  6380.     when Numeric_Error =>
  6381.        Put_Line("Numeric Error raised in Display_Q_Lengths");
  6382.        raise UNSTABLE_SOLUTION;
  6383.     when others =>
  6384.        Put_Line("Exception raised in Display_Q_Lengths");
  6385.        raise;
  6386. end Display_Q_Lengths;
  6387. --LINEFEED
  6388. separate (Net_Stats)
  6389. --**********************************************************
  6390. procedure Display_Response_Times (Node_List : NodeList) is 
  6391.   --========================================================
  6392.   -- Calculates Response Times (Mean and Variance) and sends 
  6393.   -- results to Reports.Report_Response_Times. 
  6394.   --========================================================
  6395.     Is_Within_List : Boolean;
  6396.     Node_Name      : NodeName;
  6397.     Node_Def       : NodeDef;
  6398.     Ith_Node       : NumNodes;
  6399.     Serv_Funct     : ServFunct;
  6400.     Serv_Mode      : ServMode;
  6401.     Num_Servers    : Numservers;
  6402.     M1,M2,Var      : Real;
  6403.     FCFS_Phi       : RealVector;
  6404.     QL_1           : Real;
  6405.     Mean           : Real; 
  6406.     Resp_M1        : Real;
  6407.     Resp_M2        : Real;
  6408.     Jobs           : NumJobs;
  6409.     Response_Time_Data : ResponseTimeData;
  6410.     Response_Time_List : ResponseTimeList;
  6411.     Local_Node_List    : NodeList := Node_List;
  6412.     --=======================
  6413.     use Response_List_Handler;
  6414.     use Net_Data_Pak;
  6415.  
  6416. --LINEFEED 
  6417.  begin           
  6418.     Move_To_First_Item(Local_Node_List,Is_Within_List);
  6419.     while Is_Within_List loop
  6420.        Get(From => Local_Node_List, The_Value =>Node_Name);
  6421.        Ith_Node       := Name_To_Index(Node_Name);
  6422.        Node_Def       := Node_Def_Of(Ith_Node);
  6423.        Serv_Mode      := Node_Serv_Mode(Node_Def);
  6424.  
  6425.        case Serv_Mode is
  6426.          when P_Share | PR_LCFS => 
  6427.  
  6428.                                 --**************           k 
  6429.                                 -- Eq. 1.2.1.12   E([Q (M)] )
  6430.                                 --**************      i
  6431.             QL_1      := Net_Stats.Queue_Sigma
  6432.                            ( Start_Index=> 1 , 
  6433.                              End_Index  => Num_Jobs ,
  6434.                              Order      => 1,
  6435.                              Q_Lengths  => Net.Nodes(Ith_Node).Phi);
  6436.  
  6437.                                 --**************          
  6438.                                 -- Eq. 1.2.1.15   E[T ] 
  6439.                                 --**************     i
  6440.             Mean      := QL_1 /Thru_Put(Ith_Node);  
  6441.  
  6442.             if Serv_Mode = P_Share then
  6443.                   Response_Time_Data.Value := 
  6444.                                  ( Serv_Mode      => P_Share,
  6445.                                    Node_Name      => Node_Name,
  6446.                                    Resp_Time_Mean => Mean   ); 
  6447.             elsif Serv_Mode = PR_LCFS then
  6448.                   Response_Time_Data.Value :=
  6449.                                  ( Serv_Mode      => PR_LCFS,
  6450.                                    Node_Name      => Node_Name,
  6451.                                    Resp_Time_Mean => Mean   ); 
  6452.             end if;
  6453.          when  NQ =>
  6454.  
  6455.                                 --**************        r  
  6456.                                 -- Eq. 1.2.1.17   E[(T ) ] 
  6457.                                 --**************      i
  6458.             Resp_M1 := Net.Nodes(Ith_Node).Moments(1);
  6459.             Resp_M2 := Net.Nodes(Ith_Node).Moments(2);
  6460.             Var := Resp_M2 - Resp_M1 * Resp_M1;
  6461.  
  6462.             Response_Time_Data.Value :=
  6463.                           ( Serv_Mode     => NQ,
  6464.                             Node_Name     => Node_Name,
  6465.                             Resp_Time_Mean=> Resp_M1,
  6466.                             Resp_Time_Var => Var,
  6467.                             Coeff_Var     => Sqrt(Var)/ Resp_M1);
  6468.           when FCFS =>
  6469.             Jobs := Num_Jobs - 1 ;
  6470.             FCFS_Phi := Calculate_FCFS_Phi(Ith_Node, Jobs );
  6471.             M1 := Net.Nodes(Ith_Node).Moments(1);
  6472.             Num_Servers := Node_Num_Servers(Node_Def); 
  6473.  
  6474.                                 --**************          
  6475.                                 -- Eq. 1.2.1.18   E[T ] 
  6476.                                 --**************     i
  6477.             Resp_M1 := M1 * (1.0 + FCFS_Sigma1(Jobs, 
  6478.                                                Num_Servers,
  6479.                                                FCFS_Phi   ));
  6480.  
  6481.                                 --**************        2   
  6482.                                 -- Eq. 1.2.1.19   E[(T )  ] 
  6483.                                 --**************      i
  6484.             Resp_M2 := M1 * M1 * (2.0+ FCFS_Sigma2(
  6485.                                                 Jobs, 
  6486.                                                 Num_Servers,
  6487.                                                 FCFS_Phi  ));
  6488.             Var := Resp_M2 - Resp_M1 * Resp_M1;
  6489.  
  6490.             Response_Time_Data.Value :=
  6491.                           ( Serv_Mode     => FCFS, 
  6492.                             Node_Name     => Node_Name,
  6493.                             Resp_Time_Mean=> Resp_M1, 
  6494.                             Resp_Time_Var => Var, 
  6495.                             Coeff_Var     => Sqrt(Var)/ Resp_M1);
  6496.        end case;
  6497.        Insert ( Onto           => Response_Time_List ,
  6498.                 The_Value      => Response_Time_Data ,
  6499.                 Where          => After); 
  6500.  
  6501.        Move_To_Next_Item ( On           => Local_Node_List,
  6502.                            Within_List  => Is_Within_List);
  6503.     end loop;
  6504.     Report_Response_Times( Response_Time_List );
  6505.     Dispose(Response_Time_List);
  6506. exception
  6507.     when Numeric_Error =>
  6508.        Put_Line("Numeric Error raised in Display_Response_Times");
  6509.        raise UNSTABLE_SOLUTION;
  6510.     when others =>
  6511.        Put_Line("Exception raised in Display_Response_Times");
  6512.        raise;
  6513. end Display_Response_Times;
  6514. --LINEFEED
  6515.  
  6516. separate (Net_Stats)
  6517. --*************************************************************
  6518. procedure Display_GNorms is
  6519.   --===========================================================
  6520.   -- Extracts  Normalization Constants (GNorm) from 
  6521.   -- Net_Data_Pak and sends results to Reports.Report_Q_Length.
  6522.   --==========================================================
  6523.   --==================
  6524.     use Net_Data_Pak;
  6525. begin
  6526.     Report_GNorms ( GNorms => GNorm);
  6527. end Display_GNorms;
  6528. --LINEFEED
  6529.  
  6530. separate (Net_Stats)
  6531. --***************************************************************
  6532. procedure Display_Q_Length_Dists( Node_List : NodeList) is 
  6533.   --=============================================================
  6534.   -- Extracts  Q_Length_Distribution (Phi)for selected nodes from 
  6535.   -- Net_Data_Pak and sends results to Reports.Report_Q_Length.
  6536.   --=============================================================
  6537.     Is_Within_List : Boolean; 
  6538.     Node_Name      : NodeName;
  6539.     Ith_Node       : NumNodes;
  6540.     Q_Length_Dist_Data : QLengthDistData;
  6541.     Q_Length_Dist_List : QLengthDistList;
  6542.     Local_Node_List     : NodeList := Node_List;
  6543.     --=============================
  6544.     use Q_Length_Dist_List_Handler;
  6545.     use Net_Data_Pak;
  6546.  
  6547.  begin
  6548.     Move_To_First_Item(Local_Node_List,Is_Within_List);
  6549.     while Is_Within_List loop
  6550.        Get(From => Local_Node_List, The_Value =>Node_Name);
  6551.        Ith_Node       := Name_To_Index(Node_Name);
  6552.  
  6553.        Q_Length_Dist_Data := (Node_Name  => Node_Name, 
  6554.                               Queue_Dist => Net.Nodes(Ith_Node).Phi);
  6555.  
  6556.        Insert (Onto         => Q_Length_Dist_List, 
  6557.                The_Value    => Q_Length_Dist_Data, 
  6558.                Where        => After);
  6559.  
  6560.        Move_To_Next_Item ( Local_Node_List, Is_Within_List);
  6561.     end loop;
  6562.     Report_Q_Length_Dists( Q_Length_Dist_List);
  6563.     Dispose(Q_Length_Dist_List); 
  6564.  end Display_Q_Length_Dists;
  6565. --LINEFEED
  6566. separate (Net_Stats)
  6567. --***************************************************************
  6568. procedure Display_Routing (From : NodeList;
  6569.                             To  : NodeList;
  6570.                              By : NodeList) is 
  6571.   --============================================================
  6572.   --   Calculates Routing quantities:
  6573.   --          m(i,k) [m(i,j)*] :   mean[variance] service tours 
  6574.   --
  6575.   --          M(i,j) [V (i,j)] :   mean[variance] number of visits
  6576.   --                               by a job starting at i ending at
  6577.   --                               k and traveling thru j. 
  6578.  
  6579.   --   Results  are sent to procedure Reports.Report_Service.
  6580.   --===========================================================
  6581.  
  6582.      By_Node_Index_List   : NodeIndexList;
  6583.      From_List            : NodeList := From;
  6584.      To_List              : NodeList := To;
  6585.      By_List              : NodeList := By;
  6586.  
  6587.      Page_It              : Boolean := True;
  6588.      Is_Within_To_List    : Boolean;
  6589.      Is_Within_From_List  : Boolean;
  6590.      Node_Name            : NodeName;
  6591.      To_Name         : NodeName;
  6592.      To_Index        : NumNodes;
  6593.   
  6594.      From_Name       : NodeName;
  6595.      From_Index      : NumNodes;
  6596.      By_Index        : NumNodes;
  6597.      Col_Vec         : RealVector ;
  6598.      B               : RealMatrix;
  6599.      Mean_Tours      : RealVector:=Allocate(Num_Nodes);
  6600.      Routing_Data    : RoutingData;
  6601.      Routing_List    : RoutingList;
  6602.      Node_Mean_Tours : Real;
  6603.      Mean_Tours_Value: Real;
  6604.      Serv_Tours_Var  : Real;
  6605.      Sum             : Real; 
  6606.      Var             : Real;
  6607.      --==========================
  6608.      use Routing_List_Handler;
  6609.      use Real_Mat_Pak;
  6610.      use Net_Data_Pak;
  6611. begin
  6612.     By_Node_Index_List := Make_Index_List(By_List); 
  6613.    
  6614.     Move_To_First_Item(On          => From_List,
  6615.                        Within_List => Is_Within_From_List);
  6616.     Move_To_First_Item(On          => To_List,   
  6617.                        Within_List => Is_Within_To_List);
  6618.  
  6619.     while Is_Within_From_List loop
  6620.        Get(From => From_List, The_Value =>From_Name);
  6621.        From_Index     := Name_To_Index(From_Name);
  6622. --LINEFEED
  6623.  
  6624.        while Is_Within_To_List loop
  6625.           Get(From => To_List, The_Value =>To_Name);
  6626.           To_Index    := Name_To_Index(To_Name);
  6627.           
  6628.           Col_Vec     := Extract_Col ( PB, To_Index);
  6629.  
  6630.           Replace_Col( PB, To_Index,
  6631.                        Value=> RealVector'(Num_Nodes,
  6632.                                           (1..Num_Nodes => 0.0)));
  6633.  
  6634.                                 --**************          
  6635.                                 -- Eq. 1.2.1.21   B(k)
  6636.                                 --**************
  6637.           B:= Invert_Mat(Unit_Mat(Num_Nodes) - PB );
  6638.  
  6639.           for Jth_Row in 1 .. Num_Nodes loop 
  6640.  
  6641.                                 --**************          
  6642.                                 -- Eq. 1.2.1.22   m (i,k)  
  6643.                                 --**************
  6644.              Mean_Tours_Value := Sum_Mat_By_Row(B,Row=> Jth_Row); 
  6645.              Assign(Mean_Tours, At_Index => Jth_Row,
  6646.                     Value => Mean_Tours_Value); 
  6647.           end loop;
  6648.           for Jth_Col in 1 .. Num_Nodes loop       
  6649.  
  6650.                                 --**************   k       
  6651.                                 -- Eq. 1.2.1.25   V (i,j)  
  6652.                                 --**************
  6653.              Var := Value_Of(B , From_Index , Jth_Col) *
  6654.                      (2.0 * Value_Of(B , Jth_Col , Jth_Col)
  6655.                        - 1.0 - Value_Of (B, From_Index, Jth_Col));
  6656.  
  6657.              if Jth_Col /= To_Index and then 
  6658.                           Is_Match (By_Node_Index_List,Jth_Col) then 
  6659.  
  6660.                 Node_Mean_Tours := Value_Of(B, From_Index, Jth_Col); 
  6661.  
  6662.                 Routing_Data :=
  6663.                        ( By_Node         => Index_To_Name(Jth_Col) ,
  6664.                          Node_Mean_Tours => Node_Mean_Tours, 
  6665.                          Node_Var_Tours  => Var ); 
  6666.  
  6667.                 Insert (Onto            => Routing_List, 
  6668.                         The_Value       => Routing_Data,
  6669.                         Where           => After);
  6670.              end if;
  6671.           end loop;
  6672. --LINEFEED
  6673.           Replace_Col (PB, To_Index, Value => Col_Vec);
  6674.  
  6675.                                 --**************   *
  6676.                                 -- Eq. 1.2.1.23   m (i,k) 
  6677.                                 --**************
  6678.           Serv_Tours_Var := 0.0;
  6679.           for J in 1 .. Num_Nodes loop
  6680.              Sum := 0.0;
  6681.              for L in 1 .. Num_Nodes loop
  6682.                  if (L /= To_Index) then 
  6683.                     Sum := Sum + Value_Of(PB, J, L) * 
  6684.                                  Value_Of( Mean_Tours, L);
  6685.                  end if;
  6686.              end loop;
  6687.              Sum := 1.0 + 2.0 * Sum;  
  6688.              Serv_Tours_Var := Serv_Tours_Var +
  6689.                                  Value_Of(B,From_Index,J) * Sum;
  6690.           end loop;
  6691.           Node_Mean_Tours:= Value_Of (Mean_Tours , From_Index); 
  6692.           Report_Routing (Starting_Name  => From_Name ,
  6693.                            Return_Name   => To_Name   ,
  6694.                            Mean_Tours    => Node_Mean_Tours,
  6695.                            Var_Tours     => Serv_Tours_Var,
  6696.                            List          => Routing_List ,
  6697.                            Page_It       => Page_It);
  6698.           Page_It := False;
  6699.  
  6700.           Dispose( Routing_List);
  6701.           Move_To_Next_Item (On          => To_List, 
  6702.                              Within_List => Is_Within_To_List);
  6703.                               
  6704.        end loop;
  6705.        exit when Is_Last_Item(From_List);
  6706.        Move_To_First_Item( On          => To_List,   
  6707.                            Within_List => Is_Within_To_list);
  6708.        Move_To_Next_Item ( On          => From_List, 
  6709.                            Within_List => Is_Within_From_List);
  6710.    end loop;
  6711.    Dispose (By_Node_Index_List);
  6712. exception
  6713.      when Numeric_Error =>
  6714.          Put_Line("Numeric_Error raised in Display_Routing"); 
  6715.          raise UNSTABLE_SOLUTION;
  6716.      when others => 
  6717.          Put_Line("Exception raised in Display_Routing");
  6718.          raise;
  6719. end Display_Routing;
  6720. --LINEFEED
  6721. separate (Net_Stats)
  6722. --***************************************************************
  6723. procedure Display_Service ( From: NodeList;
  6724.                               To: NodeList;
  6725.                               By: NodeList) is 
  6726.   --==========================================================
  6727.   --   Calculates Service Requirements S, S*, R, R* and sends 
  6728.   --   results to procedure Reports.Report_Service.
  6729.   --==========================================================
  6730.      Page_It             : Boolean := True;
  6731.      Is_Within_From_List : Boolean;
  6732.      Is_Within_To_List   : Boolean;
  6733.      From_List           : NodeList := From;
  6734.      To_List             : NodeList := To;
  6735.      By_List             : NodeList := By;
  6736.      By_Node_Index_List  : NodeIndexList;
  6737.      To_Name         : NodeName;
  6738.      To_Index        : NumNodes;
  6739.      From_Name       : NodeName;
  6740.      From_Index      : NumNodes;
  6741.      By_Index        : NumNodes;
  6742.      Col_Vec         : RealVector ;
  6743.      B               : RealMatrix;
  6744.      Service_Data    : ServiceData;
  6745.      Service_List    : ServiceList;
  6746.      M1,M2,Var       : Real;
  6747.      Serv_Reqt_Mean  : Real;
  6748.      Tot_Mean_Serv_Reqt : Real;
  6749.      Serv_Reqt_Var   : Real;
  6750.      Mean_Residence  : Real;                        
  6751.      Tot_Residence   : Real;
  6752.  
  6753.      --========================== 
  6754.      use Service_List_Handler;    
  6755.      use Real_Mat_Pak;
  6756.      use Net_Data_Pak;
  6757.  
  6758. --LINEFEED
  6759. begin
  6760.  
  6761.     By_Node_Index_List := Make_Index_List(By_List); 
  6762.    
  6763.     Move_To_First_Item(On          => From_List, 
  6764.                        Within_List => Is_Within_From_List);
  6765.  
  6766.     Move_To_First_Item(On          => To_List,   
  6767.                        Within_List => Is_Within_To_List);
  6768.  
  6769.     while Is_Within_From_list loop
  6770.        Get(From => From_List, The_Value =>From_Name);
  6771.        From_Index     := Name_To_Index(From_Name);
  6772.        Tot_Mean_Serv_Reqt := 0.0;
  6773.        while Is_Within_To_list loop
  6774.           Get(From => To_List, The_Value =>To_Name);
  6775.           To_Index    := Name_To_Index(To_Name);
  6776.           
  6777.           Col_Vec     := Extract_Col ( PB, To_Index);
  6778.           Replace_Col ( PB, To_Index, 
  6779.                         Value => RealVector'(Num_Nodes,
  6780.                                       (1..Num_Nodes => 0.0)));
  6781.  
  6782.                                 --**************
  6783.                                 -- Eq. 1.2.1.21   B(k) 
  6784.                                 --**************
  6785.           B := Invert_Mat ( Unit_Mat(Num_Nodes) - PB );
  6786.  
  6787.           Tot_Mean_Serv_Reqt := 0.0;
  6788.           Tot_Residence :=0.0;
  6789.           for J in 1 .. Num_Nodes loop         
  6790.             M1  := Net.Nodes(J).Moments(1);
  6791.             M2  := Net.Nodes(J).Moments(2);
  6792.  
  6793.                                 --**************
  6794.                                 -- Eq. 1.2.1.26   S(i,k)
  6795.                                 --**************
  6796.             Serv_Reqt_Mean     :=  Value_Of(B,From_Index,J) * M1;
  6797.  
  6798.                                 --**************        *
  6799.                                 -- Eq. 1.2.1.30   S(i,k)
  6800.                                 --**************
  6801.             Tot_Mean_Serv_Reqt := Tot_Mean_Serv_Reqt + Serv_Reqt_Mean;
  6802.  
  6803.                                 --**************   k
  6804.                                 -- Eq. 1.2.1.25   V (i,j)
  6805.                                 --**************
  6806.             Var := Value_Of(B,From_Index,J) * ( 2.0 * Value_Of(B,J,J)
  6807.                               - 1.0 - Value_Of(B,From_Index,J));
  6808.  
  6809.                                 --**************   k
  6810.                                 -- Eq. 1.2.1.27   W (i,j)
  6811.                                 --**************
  6812.             Serv_Reqt_Var  := Value_Of(B,From_Index,J) * (M2 - M1*M1)
  6813.                                 + Var * M1 * M1;  
  6814. --LINEFEED
  6815.  
  6816.                                 --**************   k
  6817.                                 -- Eq. 1.2.1.28   R (i,j)
  6818.                                 --**************
  6819.             Mean_Residence :=Value_Of(B,From_Index,J) *  
  6820.                                            Mean_Response(J);
  6821.  
  6822.                                 --**************   *    
  6823.                                 -- Eq. 1.2.1.30   R (i,j)
  6824.                                 --**************
  6825.             Tot_Residence  := Tot_Residence + Mean_Residence;
  6826.  
  6827.             if J /= To_Index and then 
  6828.                            Is_Match (By_Node_Index_List,J) then 
  6829.  
  6830.                 Service_Data :=
  6831.                           ( By_Node         => Index_To_Name(J) ,
  6832.                             Serv_Reqt_Mean  => Serv_Reqt_Mean,
  6833.                             Serv_Reqt_Var   => Serv_Reqt_Var,
  6834.                             Mean_Residence  => Mean_Residence);
  6835.  
  6836.                 Insert (Onto            => Service_List, 
  6837.                         The_Value       => Service_Data,
  6838.                         Where           => After);
  6839.              end if;
  6840.           end loop;
  6841.  
  6842.  
  6843.           Report_Service (Starting_Name => From_Name ,
  6844.                           Return_Name   => To_Name   ,
  6845.                           Tot_Mean_Serv => Tot_Mean_Serv_Reqt,
  6846.                           Tot_Residence => Tot_Residence,
  6847.                           List          => Service_List ,
  6848.                           Page_It       => Page_It);
  6849.  
  6850.           Page_It := False;
  6851.  
  6852.           Replace_Col ( PB, To_Index , Value => Col_Vec);
  6853.           Dispose( Service_List);
  6854.           Move_To_Next_Item ( On           => To_List,
  6855.                               Within_List  => Is_Within_To_List);
  6856.        end loop;
  6857.  
  6858.        Move_To_First_Item( On           => To_List,
  6859.                            Within_List  => Is_Within_To_List);
  6860.  
  6861.        Move_To_Next_Item ( On           => From_List,
  6862.                            Within_List  => Is_Within_From_List);
  6863.    end loop;
  6864.    Dispose (By_Node_Index_List);
  6865. exception
  6866.       when Numeric_Error =>
  6867.          Put_Line("Numeric_Error raised in Display_Service");
  6868.          raise UNSTABLE_SOLUTION;
  6869.      when others => 
  6870.          Put_Line("Exception raised in Display_Service");
  6871.          raise;
  6872. end Display_Service;
  6873. --LINEFEED
  6874.     separate (Net_Stats)
  6875.     --*****************************************************
  6876.     procedure Calculate_Stats( Num_Jobs:NumJobs) is
  6877.     --===============================================================
  6878.     --     Calculates Intermediate results and stores results in
  6879.     --     Net_Data_Pak. Must be Called prior to invoking the display
  6880.     --     routines.
  6881.     --===============================================================
  6882.         procedure Initialize_PB_Mat is separate;
  6883.         procedure Initialize_Node_Array  is separate;
  6884.         procedure Calculate_Network_Moments is separate;
  6885.         procedure Calculate_Steady_State_Flow is separate; 
  6886.         procedure Calculate_Equilb is separate;
  6887.         procedure Calculate_GNorms is separate;
  6888.         procedure Calculate_Aux_Array is separate;
  6889.         procedure Calculate_Q_Length_Dist is separate;
  6890.         procedure Calculate_Thru_Put is separate;
  6891.         procedure Calculate_Utilization is separate;
  6892.         procedure Calculate_Mean_Response is separate;
  6893.      
  6894.  
  6895.     begin
  6896.  
  6897.         -- Initialize global data in Net_Data_Pak
  6898.  
  6899.          Net_Data_Pak.Num_Nodes := Network.Count_Nodes;
  6900.          Net_Data_Pak.Num_Jobs  := Num_Jobs;
  6901.          Initialize_PB_Mat ;         -- Build PBranch Matrix 
  6902.          Initialize_Node_Array ;     -- Build Array of Nodes
  6903.                                             
  6904.          --  Intermediate Calculations  Stored in Net_Data_Pak 
  6905.  
  6906.          Calculate_Network_Moments ;          -- Moments
  6907.          Calculate_Steady_State_Flow ;        -- Alphas
  6908.          Calculate_Equilb ;                   -- PSIs 
  6909.          Calculate_GNorms ;                   -- GNorms  
  6910.          Calculate_Aux_Array ;                -- Auxs   
  6911.          Calculate_Q_Length_Dist ;            -- PHIs  
  6912.          Calculate_Thru_Put ;                 -- Thru_Put
  6913.          Calculate_Utilization ;              -- Util
  6914.          Calculate_Mean_Response ;           -- Mean_Response
  6915.   end Calculate_Stats;
  6916. --LINEFEED
  6917.    with Network; 
  6918.    with Node_Servicer; 
  6919.    separate (Net_Stats.Calculate_Stats)
  6920. --*****************************************************
  6921.    procedure Initialize_PB_Mat is
  6922.  --===============================================================
  6923.  --    Builds the Probability Branching Matrix which is stored in
  6924.  --    Net_Data_Pak. Branching Probabilities are obtained from the
  6925.  --    Network package.
  6926.  --===============================================================
  6927.         Row            : NumNodes;
  6928.         End_Of_Network : Boolean;
  6929.         Node           : NodeDef;
  6930.         Mat_Init_Exception : exception;
  6931.         --=============================================
  6932.         use Real_Mat_Pak , Node_Servicer, Net_Data_Pak;
  6933.    begin
  6934.         Allocate_PB;
  6935.         Move_To_First_Node(End_Of_Network);
  6936.         Row := 1;
  6937.         loop
  6938.            Get_Node(Node);
  6939.            if Last_Index_Of(Node_Connect_Prob(Node)) /= Num_Nodes then
  6940.              raise Mat_Init_Exception;
  6941.            end if;
  6942.            Replace_Row( In_Mat=> PB,
  6943.                         Row   => Row,
  6944.                         Value => RealVector(Node_Connect_Prob(Node)));
  6945.            exit when Row = Num_Nodes;
  6946.            if End_Of_Network then
  6947.              raise Mat_Init_Exception; 
  6948.            end if;
  6949.            Move_To_Next_Node(End_Of_Network);
  6950.            Row := Row + 1;
  6951.         end loop;
  6952.         if Row /= Num_Nodes then
  6953.            raise Mat_Init_Exception;
  6954.         end if;
  6955.      exception
  6956.         when Mat_Init_Exception =>
  6957.           Put_Line("Error in Initializing PB_Matrix");
  6958.           raise;
  6959.    end Initialize_PB_Mat;
  6960. --LINEFEED
  6961.  
  6962.    with Network; 
  6963.    with Node_Servicer;
  6964.    separate (Net_Stats.Calculate_Stats)
  6965. --*****************************************************
  6966.    procedure Initialize_Node_Array is 
  6967.  --===============================================================
  6968.  --    Builds the data structure 'Net' which is an array of Nodal
  6969.  --    data. Each array element contains the Node_Def and Intermediate
  6970.  --    Results for a node(see package Net_Data_Pak). This routine
  6971.  --    initializes each component with Node_Def obtained from the
  6972.  --    package Network.
  6973.  --================================================================ 
  6974.         use Network ; use Node_Servicer;
  6975.  
  6976.         Row            : NumNodes;
  6977.         End_Of_Network : Boolean;
  6978.         Node           : NodeDef;
  6979.    begin
  6980.         Allocate_Net;
  6981.         Move_To_First_Node(End_Of_Network);
  6982.         Row := 1;
  6983.         loop
  6984.            Get_Node(Node);
  6985.            Net.Nodes(Row).Node_Def := Node;
  6986.            exit when Row = Num_Nodes;
  6987.            if End_Of_Network then
  6988.              raise Network_Access_Exception; 
  6989.            end if;
  6990.            Move_To_Next_Node(End_Of_Network);
  6991.            Row := Row + 1;
  6992.         end loop;
  6993.         if Row /= Num_Nodes then
  6994.            raise Network_Access_Exception;
  6995.         end if;
  6996.    exception
  6997.         when Network_Access_Exception =>
  6998.           Put_Line("Error in Initializing Nodes_Array");
  6999.           raise;
  7000.    end Initialize_Node_Array;
  7001. --LINEFEED
  7002. separate (Net_Stats.Calculate_Stats)
  7003. --*****************************************************
  7004. procedure Calculate_Network_Moments is
  7005. --==============================================================
  7006. --      Calculates the Moments for all the nodes defined in the
  7007. --      array 'Net'. The results are stored in array 'Net'.
  7008. --============================================================== 
  7009.       use Node_Servicer; use Net_Data_Pak;
  7010.  
  7011.       Node : NodeDef;
  7012.  
  7013.       Moments : NodeMoments(1..Nth_Order);
  7014.  
  7015.       function  Exp_Moments(Node    : in NodeDef)
  7016.                                         return NodeMoments is separate; 
  7017.  
  7018.       function  Erlang_Moments(Node    : in NodeDef)
  7019.                                         return NodeMoments is separate; 
  7020.  
  7021.       function  Coxian_Moments(Node    : in NodeDef) return NodeMoments
  7022.                                                         is separate;
  7023.    begin
  7024.      for Ith_Node in 1.. Num_Nodes loop
  7025.         Node := Node_Def_Of(Ith_Node); 
  7026.          case Node_Serv_Disc(Node).Serv_Mode is 
  7027.             when FCFS =>
  7028.                Moments := Exp_Moments(Node);
  7029.             when others =>
  7030.                case Node_Serv_Funct(Node).Serv_Dist is
  7031.                    when Exponential =>
  7032.                        Moments := Exp_Moments(Node);
  7033.                    when Erlang =>
  7034.                        Moments := Erlang_Moments(Node);
  7035.                    when Coxian =>
  7036.                        Moments := Coxian_Moments(Node);
  7037.                end case;
  7038.          end case;
  7039.          Net.Nodes(Ith_Node).Moments := Moments; 
  7040.       end loop;
  7041.   end Calculate_Network_Moments;
  7042.  
  7043. --LINEFEED
  7044. separate (Net_Stats.Calculate_Stats.Calculate_Network_Moments)
  7045. --*****************************************************
  7046. function  Exp_Moments(Node    : in NodeDef)
  7047.                                    return NodeMoments is
  7048. --=============================================================
  7049. --     Calculate Moments for a node of Exponential Distribution
  7050. --      according --     to Eq. 1.1.1.1
  7051. --=============================================================
  7052.        use Node_Servicer ; 
  7053.  
  7054.  
  7055.        Node_Moments:NodeMoments(1..Nth_Order);
  7056.        Mu : Real;
  7057.  
  7058.  
  7059.     begin
  7060.          -- Get ServiceRate Mu from the node.
  7061.        if Node_Serv_Funct(Node).Serv_Dist = Exponential then
  7062.            Mu :=  Node_Serv_Funct(Node).Expon_Rate ;
  7063.        else
  7064.            raise Node_Access_Exception;
  7065.        end if;
  7066.        for Order in 1..Nth_Order loop
  7067.                 --*********************
  7068.                 --   Eq. 1.1.1.1
  7069.                 --*********************
  7070.           Node_Moments(NumMoments(Order)) := Fact(Order) *
  7071.                                                 Mu **(- Order);
  7072.        end loop;
  7073.        return Node_Moments;
  7074.    exception
  7075.        when Numeric_Error =>
  7076.           Put_Line("Numeric Error in Exp_Moments");
  7077.           raise UNSTABLE_SOLUTION;
  7078.        when others => 
  7079.           Put_Line("Exception raised in Exp_Moments");
  7080.           raise;
  7081.    end Exp_Moments;
  7082. --LINEFEED
  7083.     separate (Net_Stats.Calculate_Stats.Calculate_Network_Moments)
  7084. --*****************************************************
  7085.     function  Erlang_Moments(Node    : in NodeDef)
  7086.                                       return NodeMoments is
  7087. --=============================================================
  7088. --     Calculate Moments for a node of Erlang Distribution
  7089. --      according to Eq. 1.1.2.1
  7090. --=============================================================
  7091.        use Node_Servicer;
  7092.  
  7093.  
  7094.        Node_Moments : NodeMoments(1..Nth_Order);
  7095.        Mu           : Real ;
  7096.         R           : Integer;
  7097.  
  7098.  
  7099.     begin
  7100.        if Node_Serv_Funct(Node).Serv_Dist = Erlang then
  7101.           Mu :=  Node_Serv_Funct(Node).Erlang_Rate ;
  7102.           R  :=  Node_Serv_Funct(Node).Num_Erlang_Stages ;
  7103.        else
  7104.           raise Node_Access_Exception;
  7105.        end if;
  7106.  
  7107.        for Order in 1 .. Nth_Order loop
  7108.                 --*********************
  7109.                 --   Eq. 1.1.2.1
  7110.                 --*********************
  7111.           Node_Moments(Order) := Mu**(-Order) * 
  7112.                                    Fact(R+ Order- 1)/ Fact(R-1);
  7113.        end loop;
  7114.        return Node_Moments;
  7115.    exception
  7116.        when Numeric_Error =>
  7117.           Put_Line("Numeric Error in Erlang_Moments");
  7118.           raise UNSTABLE_SOLUTION;
  7119.        when others => 
  7120.           Put_Line("Exception raised in Erlang_Moments");
  7121.           raise;
  7122.    end Erlang_Moments;
  7123. --LINEFEED
  7124. separate (Net_Stats.Calculate_Stats.Calculate_Network_Moments)
  7125. --*****************************************************
  7126. function Coxian_Moments (Node        : in NodeDef)
  7127.                                          return NodeMoments is
  7128. --======================================================================
  7129. --     Computes Moments for a Node with a Coxian Distribution as defined
  7130. --     in Eq. 1.1.3.1
  7131. --====================================================================== 
  7132.    use Node_Servicer;
  7133.  
  7134.    type VectorOfStages is array(Natural range 0..Nth_Order) of RealVector;
  7135.  
  7136.    Coxian_Dist: CoxianDist               := Node_Cox_Dist(Node);
  7137.    R_Stages   : constant NumCoxianStages := Coxian_Dist.Num_Coxian_Stages;
  7138.    Col           : NumCoxianStages;
  7139.    V_Delta       : RealVector:= Allocate(R_Stages);
  7140.    P_Star        : RealMatrix;
  7141.    IMP_Inv       : RealMatrix;  -- [[I] - [P]] Inverted
  7142.    Node_Moments  : NodeMoments(1..Nth_Order);
  7143.    B             : VectorOfStages;
  7144.  
  7145.    function Make_V_Delta(Ith_Order : NumMoments)
  7146.                                  return RealVector is separate;
  7147.    function Coxian_Sigma ( N : NumMoments; B : VectorOfStages )
  7148.                                  return RealVector is separate;
  7149. begin   -- **** Coxian_Moments
  7150.    -- Build P_Star Matrix
  7151.    P_Star := Real_Matrix_Of((1..R_Stages => (1..R_stages => 0.0)));
  7152.    for Row in 1.. R_Stages - 1 loop
  7153.      Col := Row + 1;
  7154.      Assign(P_Star, Row , Col , Value  =>  Coxian_Dist.Contin_Probs(Row));
  7155.    end loop;
  7156.  
  7157.     -- Calculate [ [I] - [P*] ]
  7158.    IMP_Inv :=Invert_Mat ( Unit_Mat(R_Stages) - P_Star);
  7159.  
  7160.    B(0) := Real_Vector_Of((1..R_Stages => 1.0));
  7161.  
  7162.    for Ith_Order in NumMoments range 1.. Nth_Order loop
  7163.      V_Delta := Make_V_Delta(Ith_Order);
  7164.  
  7165.                 --*********************
  7166.                 --   Eq. 1.1.3.1
  7167.                 --*********************
  7168.      B(Ith_Order):= IMP_Inv * (V_Delta + Coxian_Sigma(Ith_Order, B));
  7169.    end loop;
  7170.       -- return  overall moments ( First row of B);
  7171.    for I in NumMoments(1) .. Nth_Order loop
  7172.        Node_Moments(I) := Value_Of(B(I),1);
  7173.    end loop;
  7174.    return Node_Moments; 
  7175.  exception
  7176.    when Numeric_Error =>
  7177.           Put_Line("Numeric Error in Erlang_Moments");
  7178.           raise UNSTABLE_SOLUTION;
  7179.    when Matrix_Inversion_Error =>
  7180.        Put_Line(" Trouble with Inverting Matrix in Coxian Moments"); 
  7181.        raise UNSTABLE_SOLUTION;
  7182.    when others =>
  7183.        Put_Line(" Exception raised in Coxian Moments Routine");
  7184.        raise;
  7185.  end Coxian_Moments;
  7186. --LINEFEED
  7187. separate (Net_Stats.Calculate_Stats.
  7188.                     Calculate_Network_Moments.Coxian_Moments)
  7189. --***********************************************************
  7190. function Make_V_Delta(Ith_Order : NumMoments) return RealVector is
  7191. --===========================================================
  7192. --     Function makes V_Delta as defined in Eq. 1.1.3.3 and used in
  7193. --         Eq. 1.1.3.3
  7194. --===========================================================
  7195.    Mu      : Real;
  7196.    V_Delta : RealVector(R_Stages);
  7197.    Temp    : Real;
  7198.    Q       : Real;
  7199. begin
  7200.      for I in 1..R_Stages loop
  7201.          Mu := Coxian_Dist.Coxian_Rates(I);
  7202.          if I = R_Stages then
  7203.              Q := 1.0;
  7204.          else
  7205.              Q  := 1.0 - Coxian_Dist.Contin_Probs(I);
  7206.          end if;
  7207.          Temp:= Fact(Ith_Order) * (Q) * Mu ** ( - Ith_Order);
  7208.          Assign (V_Delta, At_Index => I , Value => Temp);
  7209.      end loop;
  7210.      return V_Delta;
  7211.  end Make_V_Delta;
  7212.  
  7213. separate (Net_Stats.Calculate_Stats.Calculate_Network_Moments.Coxian_Moments)
  7214. --****************************************
  7215. function Coxian_Sigma ( N     : NumMoments;
  7216.                         B     : VectorOfStages ) return RealVector is
  7217. --=================================================
  7218. --     Function calculates Summation used in moments Eq. 1.1.3.1
  7219. --       for Coxian Distribution. 
  7220. --=================================================
  7221.  
  7222.    Sum : RealVector := Real_Vector_Of((1..R_Stages => 0.0));
  7223.  
  7224.    --**************************************************************
  7225.    function Make_D_Mat(Ith_Order : NumMoments) return RealMatrix is
  7226.    --==============================================================
  7227.    --    Builds Ith_Order D Matrix as defined in Eq. 1.1.3.4 and
  7228.    --       used in Eq. 1.1.3.1
  7229.    --==============================================================
  7230.         D : RealMatrix(R_Stages,R_Stages);
  7231.         Temp : Real;
  7232.         Mu   : Real;
  7233.    begin
  7234.       for I in 1.. R_Stages loop
  7235.          Mu := Coxian_Dist.Coxian_Rates(I);
  7236.          for J in 1.. R_Stages loop
  7237.             Temp := Fact(Ith_Order) * Value_Of(P_Star,I,J) *
  7238.                                           Mu **(-Ith_Order);
  7239.             Assign( D, At_Row=>I , At_Col=>J , Value => Temp);
  7240.          end loop;
  7241.       end loop;
  7242.       return D;
  7243.    end Make_D_Mat;
  7244.  
  7245. begin
  7246.    for I in 1.. N loop
  7247.      Sum := Sum  + Bin_Coeff(N , I)  * Make_D_Mat(I) * B(N - I);
  7248.    end loop;
  7249.    return Sum ;
  7250. end Coxian_Sigma;
  7251. --LINEFEED
  7252. separate (Net_Stats.Calculate_Stats)
  7253. --*****************************************************
  7254. procedure Calculate_Steady_State_Flow  is
  7255. --=====================================================
  7256. --     Calculates Steady_State_Flow (Alphas) as defined by
  7257. --     Homogenous equation 1.2.0.1  Alpha[I - P ] = 0 
  7258. --     (See user's manual for algorithm). Alphas are stored
  7259. --     in array 'Net'in package Net_Data_Pak.
  7260. --=====================================================
  7261.  
  7262.     PM_Star    : RealMatrix   := Allocate (Num_Nodes - 1,Num_Nodes - 1); 
  7263.     Alpha_Star : RealVector   := Allocate (Num_Nodes - 1);
  7264.     PV_Star    : RealVector   := Allocate (Num_Nodes - 1);
  7265.     Sum        : Real;
  7266.     --*********************************************************
  7267.     function Build_P_Star return RealMatrix is separate;
  7268.  
  7269. begin
  7270.    PM_Star    := Build_P_Star;
  7271.    PV_Star    := Real_Vector_Of(Vector_Of( RealVector'
  7272.                      (Extract_Row(PB, Num_Nodes))) (1..Num_Nodes-1));
  7273.  
  7274.    Alpha_Star := PV_Star * Invert_Mat(Unit_Mat(Num_Nodes-1) - PM_Star);
  7275.    
  7276.    Sum        := Sum_Vec(Alpha_Star);
  7277.  
  7278.    for Ith_Node in 1 .. Num_Nodes-1 loop 
  7279.        Assign_Alpha(Ith_Node,
  7280.             Value => Value_Of(Alpha_Star,Ith_Node)/(1.0 + Sum));
  7281.    end loop;
  7282.    Assign_Alpha(Num_Nodes, Value => 1.0/(1.0 + Sum) );
  7283.  exception
  7284.    when Numeric_Error =>
  7285.           Put_Line("Numeric Error in Calculate_Steady_State_Flow");
  7286.           raise UNSTABLE_SOLUTION;
  7287.    when Matrix_Inversion_Error =>
  7288.        Put_Line(" Trouble with Inverting Matrix in" & 
  7289.                    " Calculate_Steady_State_Flow"); 
  7290.        raise UNSTABLE_SOLUTION;
  7291.    when others =>
  7292.        Put_Line(" Exception raised in Calculate_Steady_State_Flow");
  7293.        raise;
  7294. end Calculate_Steady_State_Flow;
  7295.  
  7296. separate (Net_Stats.Calculate_Stats.Calculate_Steady_State_Flow)
  7297. --**************************************************************
  7298. function Build_P_Star return RealMatrix is
  7299. --==============================================================
  7300. --      Builds P_Star as defined in Eq. 1.1.3.2
  7301. --==============================================================
  7302.     PM_Star : RealMatrix (Num_Nodes - 1,Num_Nodes - 1);
  7303.     V       : Real_Mat_Pak.Vector(1..Num_Nodes - 1);
  7304. begin
  7305.     for Ith_Row in 1 .. Num_Nodes - 1 loop
  7306.        V := Vector_Of(
  7307.                 RealVector'(Extract_Row(PB,Ith_Row)))(1..Num_Nodes- 1);
  7308.     Replace_Row(PM_Star,
  7309.                 Row   => Ith_Row, 
  7310.                 Value => Real_Vector_Of(V));
  7311.     end loop;
  7312.     return PM_Star;
  7313. end Build_P_Star;
  7314. --LINEFEED
  7315.   separate (Net_Stats.Calculate_Stats)
  7316. --************************************************************
  7317.   procedure Calculate_Equilb is
  7318. --============================================================
  7319. --  Routine calculates the steady-state(equilibrium) probability PSI as
  7320. --    defined in Eq. 1.2.0.7.   Note: Logarithmic operations are defined
  7321. --    and used during the calculations in order to avoid numeric overflows.
  7322. --============================================================
  7323.  
  7324.      type LogReal is new Real;
  7325.      subtype LogInt is NumJobs;
  7326.  
  7327.      Scal_K    : Real renames Net_Data_Pak.Scal_K;
  7328.      Thetas    : RealVector(Num_Nodes);
  7329.      Mus       : RealVector(Num_Nodes) ;
  7330.      Alphas    : RealVector(Num_Nodes) ;
  7331.      Betas     : RealVector(Num_Nodes) ;
  7332.      Beta      : LogReal;
  7333.      Psi       : Real;
  7334.      Servers   : LogInt;
  7335.      Kth_Job   : LogInt;
  7336.  
  7337. --*****************************************************
  7338.    function Log_Factorial(I:LogInt) return LogReal is 
  7339.    begin
  7340.       return LogReal(Log_Fact(Integer(I)));
  7341.    end Log_Factorial;
  7342.  
  7343. --*****************************************************
  7344.    function "**"(Left:LogReal; Right: LogInt) return LogReal is 
  7345.              --  Performs Logarithmic Multiplication  -->   J * Log10(X)
  7346.    begin
  7347.       return LogReal(Real(Right) * Log(Real(Left)));
  7348.    end "**";
  7349.  
  7350. --*****************************************************
  7351.    function "/"  (Left: LogReal; Right: LogReal)return LogReal is 
  7352.              --  Exp(Log(Left) - Log10(Right))
  7353.    begin
  7354.         return LogReal( Left - Right);
  7355.    end "/";
  7356.  
  7357. --*****************************************************
  7358.    function "**"(Left: LogInt ; Right: LogInt) return LogReal is 
  7359.            -- Performs Logarithmic Multiplication --> Right * Log(Left)
  7360.    begin
  7361.     return LogReal(Real(Right) * Log(Real(Left))) ;
  7362.    end "**";
  7363.  
  7364.    --*****************************************************
  7365.     function "*" (Left: LogReal; Right: LogReal)return LogReal is 
  7366.            -- Performs Logarithmic Addition  --> Left + Right
  7367.     begin
  7368.        return LogReal(Real(Left + Right));
  7369.     end "*";
  7370. --LINEFEED 
  7371.     --******************************************************
  7372.     function "/"(Left,Right:RealVector) return RealVector is 
  7373.       -- Divides corresponding Components.
  7374.       Size : constant Natural := Last_Index_Of(Left);
  7375.       RV : RealVector(Size);
  7376.     begin
  7377.       for I in 1 .. Size  loop
  7378.          Assign (RV , I , Value_Of(Left,I) / Value_Of(Right,I)) ;
  7379.       end loop;
  7380.     return RV;
  7381.     end "/";
  7382.  
  7383. --******************************************************
  7384.     function "*"(Left,Right:RealVector) return RealVector is 
  7385.       -- Multiplies corresponding Components.
  7386.     Size : constant Natural := Last_Index_Of(Left);
  7387.         RV : RealVector(Size);
  7388.     begin
  7389.         for I in 1 .. Size loop 
  7390.           Assign (RV , I , (Value_Of(Left,I)) * Value_Of(Right,I) );
  7391.         end loop;
  7392.         return RV;
  7393.     end "*";
  7394.  
  7395.      function Sigma(DV:RealVector) return Real is separate; 
  7396.      function Select_Mus  return RealVector is separate; 
  7397.      function Select_Alphas return RealVector is separate; 
  7398.  
  7399.      pragma Inline("*", "/", "**",  Sigma);
  7400.  
  7401.    begin
  7402.       Mus    := Select_Mus;
  7403.       Alphas := Select_Alphas;
  7404.  
  7405.                 --*********************
  7406.                 --   Eq. 1.2.0.2
  7407.                 --*********************
  7408.       Thetas := Alphas / Mus;  
  7409.  
  7410.                 --*********************
  7411.                 --   Eq. 1.2.0.3
  7412.                 --*********************
  7413.       Scal_K := Sigma(Thetas) / Sigma(Thetas*Thetas);
  7414.  
  7415.                 --*********************
  7416.                 --   Eq. 1.2.0.4
  7417.                 --*********************
  7418.       Betas  := Scal_K * Thetas;         
  7419.       for Ith_Node in 1.. Num_Nodes loop
  7420.         for K in 0 .. Num_Jobs loop
  7421.           Kth_Job := LogInt(K);
  7422.           Servers := LogInt(Node_Serv_Disc(
  7423.                             Node_Def_Of(Ith_Node)).Num_Servers);
  7424.  
  7425.           Beta    := LogReal( Value_Of(Betas,Ith_Node));
  7426.  
  7427.                 --*********************
  7428.                 --   Eq. 1.2.0.7
  7429.                 --*********************
  7430.           if Kth_Job <= Servers then                 
  7431.  
  7432.                     -- Note: **,/,* perform Logarithmic operations
  7433.               Psi :=  Exp(Real (Beta** Kth_Job / Log_Factorial(Kth_Job)));
  7434.           else
  7435.               Psi :=  Exp(Real (Beta** Kth_Job /( Log_Factorial(Servers) *
  7436.                                   (Servers**(Kth_Job - Servers)))));
  7437.           end if;
  7438.           Assign_Psi(Ith_Node, Map(NumJobs(Kth_Job)), Value => Psi); 
  7439.        end loop;
  7440.      end loop;
  7441.  exception
  7442.    when others =>
  7443.        Put_Line(" Calculated steady_state probability is too small." &
  7444.                   " TRY reducing bottleneck or njobs:");
  7445.        raise;
  7446.  end Calculate_Equilb; 
  7447. --LINEFEED
  7448. separate (Net_Stats.Calculate_Stats.Calculate_Equilb)
  7449. --*****************************************************
  7450. function Sigma(DV : RealVector) return Real is
  7451. --========================================================
  7452. --       This Sigma reduces down to summing over a vector.
  7453. --========================================================
  7454. begin
  7455.    return  Sum_Vec(DV);
  7456. end Sigma;
  7457.  
  7458. separate (Net_Stats.Calculate_Stats.Calculate_Equilb)
  7459. --*****************************************************
  7460. function Select_Mus return RealVector is
  7461. --========================================================
  7462. --       Builds a RealVector of Mus from array 'Net'in Net_Data_Pak
  7463. --       . This Vector is used in Eq. 1.2.0.2 
  7464. --========================================================
  7465.   use Net_Data_Pak;
  7466.  
  7467.   Mus : RealVector := Allocate(Num_Nodes);
  7468.   M1  : Real;
  7469. begin
  7470.   for Ith_Node in 1..Num_Nodes loop
  7471.     M1 := Net.Nodes(Ith_Node).Moments(1);   
  7472.     Assign( Mus, Ith_Node, Value => 1.0 / M1); 
  7473.   end loop;
  7474.   return Mus;
  7475. end Select_Mus;
  7476.  
  7477. separate (Net_Stats.Calculate_Stats.Calculate_Equilb)
  7478. --*****************************************************
  7479. function Select_Alphas return RealVector is  
  7480. --========================================================
  7481. --       Builds a RealVector of Alphas  from array 'Net'in 
  7482. --       Net_Data_Pak . This Vector is used in Eq. 1.2.0.2 
  7483. --========================================================
  7484.   use Net_Data_Pak;
  7485.   Alphas : RealVector := Allocate(Num_Nodes);
  7486.   Alpha_Value : Real;
  7487. begin
  7488.   for Ith_Node in 1..Num_Nodes loop
  7489.     Alpha_Value := Alpha(Ith_Node);   
  7490.     Assign( Alphas, Ith_Node, Value => Alpha_Value ); 
  7491.   end loop;
  7492.   return Alphas;
  7493. end Select_Alphas;
  7494. --LINEFEED
  7495.  
  7496.   separate (Net_Stats.Calculate_Stats)
  7497. --*****************************************************
  7498.   procedure Calculate_GNorms is 
  7499. --========================================================
  7500. --     Calculates Normalizations Constants as defined in
  7501. --     Eq. 1.2.0.9. Results are stored in RealVector GNorm
  7502. --     in package Net_Data_Pak.
  7503. --========================================================
  7504.       use Net_Data_Pak;
  7505.  
  7506.       Sum : Real;
  7507.   begin
  7508.      Allocate_GNorm;
  7509.  
  7510.                 --*********************
  7511.                 --   Eq. 1.2.0.9
  7512.                 --*********************
  7513.      Assign_Gnorm( At_Index => (Map( 0)),
  7514.                     Value   =>  1.0);
  7515.  
  7516.      for Mth_Job in 1 .. Num_Jobs loop
  7517.         Assign_Gnorm( At_Index => Map(Mth_Job),
  7518.                       Value    => Psi(1, Map(Mth_Job))); 
  7519.      end loop;
  7520.  
  7521.      for Nth_Node in 2..Num_Nodes loop
  7522.        for Mth_Job in reverse 1 .. Num_Jobs loop
  7523.           Sum := 0.0;
  7524.           for K in 0 .. Mth_Job loop
  7525.             Sum:= Sum+ Psi(Nth_Node,Map(K))* GNorm_Value(Map(Mth_Job -K));
  7526.           end loop;
  7527.           Assign_GNorm(Map(Mth_Job), Value => Sum);
  7528.        end loop;
  7529.      end loop;
  7530.  exception
  7531.    when Numeric_Error =>
  7532.           Put_Line("Numeric Error in Calculate_GNorm");
  7533.           raise UNSTABLE_SOLUTION;
  7534.   end Calculate_GNorms; 
  7535. --LINEFEED      
  7536.         
  7537.   separate (Net_Stats.Calculate_Stats)
  7538. --*****************************************************
  7539.   procedure Calculate_Aux_Array is 
  7540. --============================================================
  7541. --     Calculates Aux_Array (l's) as defined in eq. 1.2.0.11. 
  7542. --     Results are stored in array 'Net' in package Net_Data_Pak.
  7543. --=============================================================
  7544.      use Net_Data_Pak;
  7545.      First_Time_For_Node : Boolean;
  7546.      Aux_Value           : Real;
  7547.      Sum                 : Real;
  7548.   begin
  7549.                 --*********************
  7550.                 --   Eq. 1.2.0.11
  7551.                 --*********************
  7552.      for Ith_Node in 1..Num_Nodes loop
  7553.        Assign_Aux(Ith_Node , Map(0) , Value => 1.0);
  7554.      end loop;
  7555.  
  7556.      for Ith_Node in 1.. Num_Nodes loop
  7557.        First_Time_For_Node := True;
  7558.        for Kth_Job in 1.. Num_Jobs loop
  7559.          Sum := 0.0;
  7560.          for J in 1.. Kth_Job loop
  7561.            Sum := Sum + Psi(Ith_Node, Map(J)) * 
  7562.                          Aux(Ith_Node,Map(Kth_Job-J));
  7563.          end loop;
  7564.  
  7565.          Aux_Value := GNorm_Value(Map(Kth_Job)) - Sum; 
  7566.          if Aux_Value < 0.0 then
  7567.             Aux_Value := 0.0;   -- Corrective Action
  7568.                if First_Time_for_Node then
  7569.                   Put("UNSTABLE_SOLUTION for (Eq.1.2.0.11) For Node: ");
  7570.                   Put_Line(Name_Of_Node(Node_Def_Of(Ith_Node))); 
  7571.                   Put_Line("[Type 'Help Fix_ql'] "); 
  7572.                   First_Time_For_Node := False;
  7573.                end if;
  7574.          end if;
  7575.  
  7576.          Assign_Aux(Ith_Node, Map(Kth_Job), 
  7577.                      Value => Aux_Value); 
  7578.        end loop;
  7579.      end loop;
  7580.  exception
  7581.    when Numeric_Error =>
  7582.           Put_Line("Numeric Error in Calculate_Aux_Array");
  7583.           raise UNSTABLE_SOLUTION;
  7584.    when others =>
  7585.        Put_Line(" Exception raised in Calculate_Aux_Array");
  7586.        raise;
  7587.  end Calculate_Aux_Array;
  7588. --LINEFEED
  7589.  
  7590.  separate (Net_Stats.Calculate_Stats)
  7591. --*****************************************************
  7592.  procedure Calculate_Q_Length_Dist is 
  7593. --================================================================
  7594. --      Calculates Phi for the Ith Node according to Eq. 1.2.0.10.
  7595. --      Results are stored in array 'Net' in package Net_data_Pak.
  7596. --================================================================
  7597.    use Net_Data_Pak;
  7598.  
  7599.    Aux_Value : Real;
  7600.    Psi_Value : Real;
  7601.  begin
  7602.     for Ith_Node in 1.. Num_Nodes loop
  7603.       for Ith_Job in 0 .. Num_Jobs loop
  7604.         Psi_Value := Psi(Ith_Node,Map(Ith_Job));
  7605.         Aux_Value := Aux(Ith_Node, Map(Num_Jobs - Ith_Job)); 
  7606.                 --*********************
  7607.                 --   Eq. 1.2.0.10
  7608.                 --*********************
  7609.         begin      
  7610.             Assign_Phi(Ith_Node, Map(Ith_Job), Value => 
  7611.                     Psi_Value/GNorm_Value(Map(Num_Jobs)) * Aux_Value);
  7612.         exception
  7613.             when numeric_error =>
  7614.                Assign_Phi(Ith_Node, Map(Ith_Job), Value => 
  7615.                     Psi_Value * Aux_Value /GNorm_Value(Map(Num_Jobs)) );
  7616.         end ;
  7617.       end loop;
  7618.     end loop;
  7619.  exception
  7620.    when Numeric_Error =>
  7621.           Put_Line("Numeric Error in Calculate_Q_Length_Dist");
  7622.           raise UNSTABLE_SOLUTION;
  7623.    when others =>
  7624.        Put_Line(" Exception raised in Calculate_Q_Length_Dist");
  7625.        raise;
  7626.  end Calculate_Q_Length_Dist;
  7627. --LINEFEED
  7628.  
  7629.  separate (Net_Stats.Calculate_Stats)
  7630. --*****************************************************
  7631.  procedure Calculate_Thru_Put is
  7632. --================================================================
  7633. --      Calculates Thru_Put for the Ith Node according to Eq. 1.2.0.16.
  7634. --      Results are stored in array 'Net' in package Net_data_Pak.
  7635. --================================================================
  7636.     use Net_Data_Pak;
  7637.  
  7638.    Scal_K  : Real renames Net_Data_Pak.Scal_K;
  7639.    G_Ratio : Real:= GNorm_Value(Map(Num_Jobs - 1)) /
  7640.                          GNorm_Value(Map(Num_Jobs));
  7641.    Tao     : Real ;
  7642.  begin
  7643.    for Ith_Node in 1 .. Num_Nodes loop
  7644.                 --*********************
  7645.                 --   Eq. 1.2.0.16
  7646.                 --*********************
  7647.      Tao := Scal_K * Alpha(Ith_Node) * G_Ratio;  
  7648.      Assign_Thru_Put(Ith_Node, Value => Tao);
  7649.    end loop;
  7650.  exception
  7651.    when Numeric_Error =>
  7652.           Put_Line("Numeric Error in Calculate_Thru_Put");
  7653.           raise UNSTABLE_SOLUTION;
  7654.  end Calculate_Thru_Put;
  7655. --LINEFEED    
  7656.  
  7657.  separate (Net_Stats.Calculate_Stats)
  7658. --*****************************************************
  7659.  procedure Calculate_Utilization is
  7660. --================================================================
  7661. --   Calculates Utilization for the Ith Node according to Eq. 1.2.0.14.
  7662. --   Results are stored in array 'Net' in package Net_data_Pak.
  7663. --================================================================
  7664.  
  7665.    Util_Value : Real;
  7666.  
  7667.  begin
  7668.    for Ith_Node in 1 .. Num_Nodes loop
  7669.                 --*********************
  7670.                 --   Eq. 1.2.0.14
  7671.                 --*********************
  7672.      Util_Value := 1.0 - Aux(Ith_Node,Map(Num_Jobs))/
  7673.                             GNorm_Value(Map(Num_Jobs));
  7674.      Assign_Util(Ith_Node , Value => Util_Value); 
  7675.      if Util_Value < 0.0 then
  7676.         raise Numeric_Error;
  7677.      end if;
  7678.    end loop;
  7679.  exception
  7680.    when Numeric_Error =>
  7681.           Put_Line("Numeric Error in Calculate_Utilization");
  7682.           raise UNSTABLE_SOLUTION;
  7683. end Calculate_Utilization;
  7684. --LINEFEED
  7685.  
  7686. separate (Net_Stats.Calculate_Stats)
  7687. --*****************************************************
  7688. procedure Calculate_Mean_Response  is
  7689. --================================================================
  7690. --   Calculates Mean_Response  for the Ith Node according to 
  7691. --   Eq. 1.2.0.14. Results are stored in array 'Net' in package 
  7692. --   Net_data_Pak.
  7693. --================================================================
  7694.     use Net_Data_Pak; use Node_Servicer;
  7695.  
  7696.     Node_Def     : NodeDef;
  7697.     Ith_Node     : NumNodes;
  7698.     Serv_Mode    : ServMode;
  7699.     Num_Servers  : Numservers;
  7700.     M1           : Real;
  7701.     FCFS_Phi     : RealVector;
  7702.     QL_1         : Real;
  7703.     Mean         : Real;
  7704.  
  7705.  begin           
  7706.     for Ith_Node in 1.. Num_Nodes loop
  7707.        Node_Def := Node_Def_Of(Ith_Node);
  7708.        Serv_Mode:= Node_Serv_Disc(Node_Def).Serv_Mode;
  7709.        case Serv_Mode is
  7710.          when P_Share | PR_LCFS => 
  7711.  
  7712.                 --*********************        k
  7713.                 --   Eq. 1.2.0.12       E[Q (M) ]
  7714.                 --*********************    i
  7715.             QL_1      := Queue_Sigma (
  7716.                              Start_Index=> 1 ,   
  7717.                              End_Index  => Num_Jobs ,
  7718.                              Order      => 1,
  7719.                              Q_Lengths  => Net.Nodes(Ith_Node).Phi); 
  7720.  
  7721.                 --*********************     
  7722.                 --   Eq. 1.2.0.15       E[T ]
  7723.                 --*********************    i
  7724.             Mean      := QL_1 /Thru_Put(Ith_Node);  
  7725.  
  7726.          when  NQ =>
  7727.  
  7728.                 --*********************      r
  7729.                 --   Eq. 1.2.0.17       E[(T) ]
  7730.                 --*********************      i
  7731.             Mean := Net.Nodes(Ith_Node).Moments(1);
  7732.           when FCFS =>
  7733.             FCFS_Phi := Calculate_FCFS_Phi(Ith_Node,Num_Jobs - 1);
  7734.             M1 := Net.Nodes(Ith_Node).Moments(1);
  7735.             Num_Servers := Node_Serv_Disc(Node_Def).Num_Servers; 
  7736.  
  7737.                 --*********************     
  7738.                 --   Eq. 1.2.0.18       E[T ]
  7739.                 --*********************    i
  7740.             Mean := M1 * (1.0 + FCFS_Sigma1(Num_Jobs-1, 
  7741.                                             Num_Servers, FCFS_Phi));
  7742.        end case;
  7743.        Assign_Mean_Response(Ith_Node, Value => Mean);
  7744.        if Mean < 0.0 then
  7745.            raise Numeric_Error;
  7746.        end if;
  7747.     end loop;
  7748.  exception
  7749.    when Numeric_Error =>
  7750.           Put_Line("Numeric Error in Calculate_Mean_Response");
  7751.           raise UNSTABLE_SOLUTION;
  7752. end Calculate_Mean_Response;
  7753. --LINEFEED
  7754. with Text_Handler; use Text_Handler;
  7755. package Help_Setup is
  7756. --===========================================================
  7757. --     Contains Help Facility Parameters Likely to be altered 
  7758. --     system installation. To avoid complete recompilation,
  7759. --     parameter values are located in the package body.
  7760. --============================================================ 
  7761.  
  7762.  
  7763.        --==========Setup Parameters ========================
  7764.  
  7765.     Help_Directory     : Text ; 
  7766.  
  7767.     Help_File_Name_Ext : Text; 
  7768.  
  7769. end Help_Setup;
  7770.  
  7771.  
  7772. package body Help_Setup is
  7773. begin
  7774.      Help_Directory := Txt("");
  7775.      Help_File_Name_Ext := Txt( ".hlp");
  7776. end Help_Setup;
  7777. with Text_Handler ; use Text_Handler;
  7778. with Global_Types ; use Global_Types;
  7779. with MMI_Io       ; use MMI_Io;
  7780. with Net_Stats    ; use Net_Stats;
  7781. with Node_Servicer ; use Node_Servicer;
  7782.  
  7783. package MMI  is
  7784.  
  7785. ------------------------------------------------------------------------
  7786. -- This Package contains constants, exceptions, types, functions
  7787. -- and procedures that are used by the procedure, Edit.
  7788. -- Each of these categories has its members arranged in
  7789. -- alphabetical order when possible.
  7790. --
  7791. ------------------------------------------------------------------------
  7792.  
  7793.  
  7794. ------------------------------------------------------------------------
  7795. --                       Constants
  7796. ------------------------------------------------------------------------
  7797.  
  7798. Double         :  Constant Natural := 2;
  7799. Is_Prompt_Mode :  Constant Boolean := True;
  7800. No_Query       :  Constant Text    := Txt("");
  7801. Single         :  Constant Natural := 1;
  7802.  
  7803. ------------------------------------------------------------------------
  7804. --                       Exceptions
  7805. ------------------------------------------------------------------------
  7806.  
  7807. Command_Error    : Exception;
  7808. Unstable_Solution: Exception renames Net_Stats.Unstable_Solution;
  7809.  
  7810. ------------------------------------------------------------------------
  7811. --                       Super Types - Those that other types depend on.
  7812. ------------------------------------------------------------------------
  7813.  
  7814. type    BooleanArray    is array (NumNodes range <>) of Boolean;
  7815.  
  7816. type    NodesArray      is array (NumNodes range <>) of NodeName;
  7817.  
  7818. type    NodesType (Number: NumNodes := NumNodes'First) is
  7819.    record
  7820.       Name    : NodesArray   (1 .. Number);
  7821.    end record;
  7822.  
  7823. type    One             is new Integer range 1 .. 1;
  7824.  
  7825. type    ProbArray       is array (NumNodes range <>) of Probs;
  7826.  
  7827. type    PbranchType (Number: NumNodes := NumNodes'First) is
  7828.    record
  7829.       Val:  ProbArray (1 .. Number);
  7830.    end record;
  7831.  
  7832. --LINEFEED
  7833. ------------------------------------------------------------------------
  7834. --                       Types
  7835. ------------------------------------------------------------------------
  7836.  
  7837. type    CommandType      is (Help, Run, Prompt, Njobs, Nnodes, Order,
  7838.                              Node, Discipline, Nservers, Distribution,
  7839.                              Endnode, Pbranch, Nstages, Rates, Cbranch,
  7840.                              Save, Show, Quit, Infile, Outfile, Reset,
  7841.                              Report, Title, Echo, Paging);
  7842.  
  7843. type    ExponRates       is array (One range <>) of ExponRate;
  7844.  
  7845. type    ErlangRates      is array (One range <>) of ErlangRate;
  7846.  
  7847. type    GlobalStatusType is
  7848.    record
  7849.       Title          : Boolean;
  7850.       N_Nodes        : Boolean;
  7851.       Order          : Boolean;
  7852.       N_Jobs         : Boolean;
  7853.    end record;
  7854.  
  7855. type    GlobalValueType is
  7856.    record
  7857.       N_Nodes        : NumNodes;
  7858.       Nodes          : NodesType;
  7859.       N_Jobs         : NumJobs;
  7860.       Title          : Text;
  7861.    end record;
  7862.  
  7863. type    MmiMode         is (Edit, Prompt, Infile);
  7864.  
  7865. subtype NodeSubcommandType is CommandType range Discipline .. Cbranch;
  7866.  
  7867. type    NodeStatusType  is
  7868.    record
  7869.       Node           : Boolean;
  7870.       P_Branch       : Boolean;
  7871.       Discip         : Boolean;
  7872.       Dist           : Boolean;
  7873.       N_Servers      : Boolean;
  7874.       N_Erlang_Stages: Boolean;
  7875.       N_Coxian_Stages: Boolean;
  7876.       C_Branch       : Boolean;
  7877.       Expon_Rate     : Boolean;
  7878.       Erlang_Rate    : Boolean;
  7879.       Coxian_Rates   : Boolean;
  7880.    end record;
  7881.  
  7882. --LINEFEED
  7883. type    NodeValueType   is
  7884.    record
  7885.       Name            : Text;
  7886.       Discip          : ServMode;
  7887.       N_Servers       : NumServers;
  7888.       P_Branch        : PbranchType;
  7889.       Dist            : ServDist;
  7890.       N_Erlang_Stages : NumErlangStages;
  7891.       N_Coxian_Stages : NumCoxianStages;
  7892.       Expon_Rates     : ExponRates (1 .. 1);
  7893.       Erlang_Rates    : ErlangRates(1 .. 1);
  7894.       Coxian_Dist     : CoxianDist;
  7895.    end record;
  7896.  
  7897. type    ReportType      is (Routing, Arrival_Frequencies, Serv_Times,
  7898.                             Serv_Requirements, Response_Times,
  7899.                             Throughput, Qlength_Distributions,
  7900.                             Normalizations, Pbranch, Model);
  7901.  
  7902. type    ShowType        is (Title, Nnodes, Order, Njobs, Node, Model);
  7903.  
  7904. type    YesNo           is (Yes, No);
  7905.  
  7906. --LINEFEED
  7907. ------------------------------------------------------------------------
  7908. --                   Procedures and Functions
  7909. ------------------------------------------------------------------------
  7910.  
  7911. procedure Check_Dist_Set           (Dist_Set: in Boolean);
  7912.   ----------------------------------------------------------------------
  7913.   -- Checks that the Distribution command has been issued.
  7914.   -- Raises Command_Error if not.
  7915.   ----------------------------------------------------------------------
  7916.  
  7917. procedure Check_Nnodes_Set         (Nnodes_Set: in Boolean);
  7918.   ----------------------------------------------------------------------
  7919.   -- Checks that the Nnode Command has been issued.
  7920.   -- Raises Command_Error if not.
  7921.   ----------------------------------------------------------------------
  7922.  
  7923. procedure Check_Nnodes_Not_Set     (Nnodes_Set: in Boolean);
  7924.   ----------------------------------------------------------------------
  7925.   -- Checks that the Nnode Command has not been issued.
  7926.   -- Raises Command_Error if it has.
  7927.   ----------------------------------------------------------------------
  7928.  
  7929. procedure Check_Node_Subcommand_Ok (Node_Set  : in Boolean;
  7930.                                     Global_Set: in GlobalStatusType);
  7931.   ----------------------------------------------------------------------
  7932.   -- Checks that Nnodes, Order, Njobs, Node commands have been issued.
  7933.   -- Raises Command_Error if not.
  7934.   ----------------------------------------------------------------------
  7935.  
  7936. procedure Check_Order_Not_Set      (Order_Set: in Boolean);
  7937.   ----------------------------------------------------------------------
  7938.   -- Checks that the Order Command has not been issued.
  7939.   -- Raises Command_Error if it has.
  7940.   ----------------------------------------------------------------------
  7941.  
  7942. procedure Check_N_Stages_Set       (N_Stages_Set: in Boolean);
  7943.   ----------------------------------------------------------------------
  7944.   -- Checks that the Nstages command has been issued.
  7945.   -- Raises Command_Error if not.
  7946.   ----------------------------------------------------------------------
  7947.  
  7948. procedure Display (Message       : in String;
  7949.                    Is_Prompt_Mode: in Boolean := False);
  7950.   ----------------------------------------------------------------------
  7951.   -- Outputs Message to the output media and then outputs the prompt,
  7952.   -- whether it be E> (edit mode), P> (prompt mode), or
  7953.   -- I> (Infile mode). These correspond to MMImodes.
  7954.   ----------------------------------------------------------------------
  7955.  
  7956. --LINEFEED
  7957. function  Equal (V1: in Real;
  7958.                  V2: in Real) return Boolean;
  7959.   ----------------------------------------------------------------------
  7960.   -- Declares two floating point numbers equal if they are within some
  7961.   -- delta of each other.
  7962.   ----------------------------------------------------------------------
  7963.  
  7964. procedure Error   (Message: in String);
  7965.   ----------------------------------------------------------------------
  7966.   -- Outputs Message to the output media as an error.
  7967.   ----------------------------------------------------------------------
  7968.  
  7969. procedure Get_Cbranch (C_Branch: in out ContinProbs;
  7970.                        Mode    : in     MMImode := Edit;
  7971.                        Query   : in     Text := No_Query);
  7972.   ----------------------------------------------------------------------
  7973.   -- Gets from the user the continuation branching probabilites
  7974.   -- between stages of a Coxian distribution. If there is an input
  7975.   -- error, then if (a) mode = prompt, the user must reenter, (b)
  7976.   -- otherwise Command_Error is raised.
  7977.   ----------------------------------------------------------------------
  7978.  
  7979. procedure Get_Infile;
  7980.   ----------------------------------------------------------------------
  7981.   -- Sets the command input stream to a file.
  7982.   ----------------------------------------------------------------------
  7983.  
  7984. generic
  7985.    type Item is range <>;
  7986. procedure Get_Integer (Target     : out Item;
  7987.                        Target_Type: in  String;
  7988.                        Mode       : in  MMImode := Edit;
  7989.                        Query      : in  Text := No_Query);
  7990.   ----------------------------------------------------------------------
  7991.   -- Gets from the user either Nnodes, Njobs, Nservers, Nstages(Erlang),
  7992.   -- or Nstages(Coxian) depending on the instantiation. Input error is
  7993.   -- handled similarly to Get_Cbranch.
  7994.   ----------------------------------------------------------------------
  7995.  
  7996. procedure Get_Node_Info  (Val : in out NodeValueType;
  7997.                           Set :    out NodeStatusType);
  7998.   ----------------------------------------------------------------------
  7999.   -- Sets the records Val (except Val.Name) and Set depending on the
  8000.   -- characteristics of the node which is obtained from the network.
  8001.   ----------------------------------------------------------------------
  8002.  
  8003. procedure Get_Node_List  (Node_List: in out NodeList;
  8004.                           Nodes    : in     NodesType);
  8005.   ----------------------------------------------------------------------
  8006.   -- Builds a nodelist from a parsing of the report command.
  8007.   ----------------------------------------------------------------------
  8008.  
  8009. --LINEFEED
  8010. procedure Get_Order (Nodes  : in out NodesType;
  8011.                      N_Nodes: in     NumNodes;
  8012.                      Mode   : in     MMImode := Edit;
  8013.                      Query  : in     Text    := No_Query);
  8014.   ----------------------------------------------------------------------
  8015.   -- Gets from the user the nodes in the correct order. Input error is
  8016.   -- handled similarly to Get_Cbranch.
  8017.   ----------------------------------------------------------------------
  8018.  
  8019. procedure Get_Outfile;
  8020.   ----------------------------------------------------------------------
  8021.   -- Sets the message output to the appropriate media (terminal/file).
  8022.   ----------------------------------------------------------------------
  8023.  
  8024. Function  Get_Pbranch (Node_Def: in NodeDef) return PbranchType;
  8025.   ----------------------------------------------------------------------
  8026.   -- Converts Pbranch (branching probabilities from a node to all nodes)
  8027.   -- from the format of the Network package to the format of this pack.
  8028.   ----------------------------------------------------------------------
  8029.  
  8030. procedure Get_Pbranch (Nnodes   : in  NumNodes;
  8031.                        P_Branch : out PbranchType;
  8032.                        Mode     : in  MMImode := Edit;
  8033.                        Query    : in  Text := No_Query);
  8034.   ----------------------------------------------------------------------
  8035.   -- Gets from the user Pbranch as described in the previous function.
  8036.   -- Input error is handled similarly to Get_Cbranch.
  8037.   ----------------------------------------------------------------------
  8038.  
  8039. generic
  8040.    type IndexTyp is range <>;
  8041.    type Floating is digits <>;
  8042.    type Vector   is array (IndexTyp range <>) of Floating;
  8043. procedure Get_Rates (Rates: in out Vector;
  8044.                      Mode : in     MMImode := Edit;
  8045.                      Query: in     Text    := No_Query);
  8046.   ----------------------------------------------------------------------
  8047.   -- Gets from the user either Exponential, Erlang, or Coxian rates,
  8048.   -- depending on the instantiation. Input error is
  8049.   -- handled similarly to Get_Cbranch.
  8050.   ----------------------------------------------------------------------
  8051.  
  8052. generic
  8053.    type Item is (<>);
  8054. procedure Get_Text    (Target     : out Item;
  8055.                        Target_Type: in  String;
  8056.                        Mode       : in  MMImode := Edit;
  8057.                        Query      : in  Text := No_Query);
  8058.   ----------------------------------------------------------------------
  8059.   -- Gets from the user either a command, the discipline, the
  8060.   -- distribution, a yes/no, or any other response which is an
  8061.   -- enumeration type. Input error is handled similary to Get_Cbranch.
  8062.   ----------------------------------------------------------------------
  8063.  
  8064. --LINEFEED
  8065. procedure Get_Title (Model_Title: out Text;
  8066.                      Mode       : in  MMImode := Edit;
  8067.                      Query      : in  Text := No_Query);
  8068.   ----------------------------------------------------------------------
  8069.   -- Gets the Title which will appear on all reports.
  8070.   ----------------------------------------------------------------------
  8071.  
  8072. procedure Help (Topic_Short: in Text);
  8073.   ----------------------------------------------------------------------
  8074.   -- Outputs the topic in the system help file to the output media.
  8075.   ----------------------------------------------------------------------
  8076.  
  8077. function  Index       (Node_Name: in Text;
  8078.                        Nodes    : in NodesType) return integer;
  8079.   ----------------------------------------------------------------------
  8080.   -- Finds the index of Node_Name in the array Nodes.Name.
  8081.   ----------------------------------------------------------------------
  8082.  
  8083. procedure Insert_Dummy_Nodes  (Nodes: in NodesType);
  8084.   ----------------------------------------------------------------------
  8085.   -- Inserts template nodes into the network after the order
  8086.   -- command is issued.
  8087.   ----------------------------------------------------------------------
  8088.  
  8089. function  Make_Float (From: in Text) return Text;
  8090.   ----------------------------------------------------------------------
  8091.   -- Converts ADA unacceptable float values to acceptable values.
  8092.   -- examples - 20, .55
  8093.   ----------------------------------------------------------------------
  8094.  
  8095. function  Missing_Global_Commands  (Set: in GlobalStatusType)
  8096.                                     return String;
  8097.   ----------------------------------------------------------------------
  8098.   -- Provides a list of the following commands that have not been
  8099.   -- issued: Nnodes, Order, Njobs.
  8100.   ----------------------------------------------------------------------
  8101.  
  8102. function  Missing_Node_Commands    (Set  : in NodeStatusType;
  8103.                                     Dist : in ServDist)
  8104.                                     return String;
  8105.   ----------------------------------------------------------------------
  8106.   -- Provides a list of the following commands that have not been
  8107.   -- issued: Pbranch, Discipline, Distribution, Nservers, Rates,
  8108.   -- Nstages (Erlang or Coxian), Cbranch (Coxian).
  8109.   ----------------------------------------------------------------------
  8110.  
  8111. function  Mode (Is_Prompt_Mode: in Boolean := False) return MMImode;
  8112.   ----------------------------------------------------------------------
  8113.   -- Returns the MMImode (either edit, prompt, or infile).
  8114.   ----------------------------------------------------------------------
  8115.  
  8116. --LINEFEED
  8117. procedure Put_Node_Info (Val: in NodeValueType;
  8118.                          Set: in NodeStatusType);
  8119.   ----------------------------------------------------------------------
  8120.   -- The reverse of Get_Node_Info. Replaces a node in the network
  8121.   -- with the new values in Val.
  8122.   ----------------------------------------------------------------------
  8123.  
  8124. function  Quote   (From: in Text)  return String;
  8125.   ----------------------------------------------------------------------
  8126.   -- puts From in single quotes.
  8127.   ----------------------------------------------------------------------
  8128.  
  8129. procedure Report_Set_Up (Report_Type: in ReportType;
  8130.                          N_Jobs     : NumJobs;
  8131.                          Nodes      : in NodesType);
  8132.   ----------------------------------------------------------------------
  8133.   -- Parses report command line and calls appropriate report program.
  8134.   ----------------------------------------------------------------------
  8135.  
  8136. procedure Run     (Nodes : in NodesType;
  8137.                    N_Jobs: in NumJobs);
  8138.   ----------------------------------------------------------------------
  8139.   -- Checks that all nodes have complete info and then runs the
  8140.   -- simulation.
  8141.   ----------------------------------------------------------------------
  8142.  
  8143. --LINEFEED
  8144. procedure Set_Exponential (Dist: out ServDist);
  8145.   ----------------------------------------------------------------------
  8146.   -- Sets Dist to Exponential.
  8147.   ----------------------------------------------------------------------
  8148.  
  8149. procedure Set_Nservers    (N_Servers: out NumServers;
  8150.                            Discip   : in  ServMode;
  8151.                            N_Jobs   : in  NumJobs);
  8152.   ----------------------------------------------------------------------
  8153.   -- Sets Nservers when discipline is not Fcfs.
  8154.   ----------------------------------------------------------------------
  8155.  
  8156. function  Short           (Node_Name: NodeName) return String;
  8157.   ----------------------------------------------------------------------
  8158.   -- Converts Node_Name into text with no trailing blanks.
  8159.   ----------------------------------------------------------------------
  8160.  
  8161. ------------------------------------------------------------------------
  8162. -- The following Show procedures show their value(s) to the output
  8163. -- stream specified in Outmode.
  8164. ------------------------------------------------------------------------
  8165.  
  8166. procedure Show_All    (Val      : in GlobalValueType;
  8167.                        Set      : in GlobalStatusType;
  8168.                        Out_Mode : in Outmode);
  8169.  
  8170. procedure Show_Njobs  (N_Jobs   : in NumJobs;
  8171.                        Set      : in Boolean;
  8172.                        Out_Mode : in OutMode);
  8173.  
  8174. procedure Show_Nnodes (N_Nodes  : in NumNodes;
  8175.                        Set      : in Boolean;
  8176.                        Out_Mode : in OutMode);
  8177.  
  8178. procedure Show_Node   (Node_Name: in Text;
  8179.                        Out_Mode : in OutMode);
  8180.  
  8181. procedure Show_Node   (ND       : in NodeDef;
  8182.                        Out_Mode : in OutMode);
  8183.  
  8184. procedure Show_Order  (Nodes    : in NodesType;
  8185.                        Set      : in Boolean;
  8186.                        Out_Mode : in OutMode);
  8187.  
  8188. procedure Show_Title  (Title    : in Text;
  8189.                        Set      : in Boolean;
  8190.                        Out_Mode : in Outmode);
  8191.  
  8192. procedure Update_NoQueue_Nodes (N_Jobs: in NumJobs);
  8193.   ----------------------------------------------------------------------
  8194.   -- Updates the nodes in the network which have a No_Queue discipline
  8195.   -- so that Nservers = Njobs.
  8196.   ----------------------------------------------------------------------
  8197.  
  8198. function  Verified (Query: Text) return Boolean;
  8199.   ----------------------------------------------------------------------
  8200.   -- Lets the user verify an action with yes/no.
  8201.   ----------------------------------------------------------------------
  8202.  
  8203. procedure Welcome;
  8204.   ----------------------------------------------------------------------
  8205.   -- Displays the program welcome banner.
  8206.   ----------------------------------------------------------------------
  8207.  
  8208. end MMI;
  8209. --LINEFEED
  8210. with Network      ; use Network;
  8211. with Real_Mat_Pak ; use Real_Mat_Pak;
  8212. with Help_Setup   ;
  8213.  
  8214. package body MMI is
  8215.  
  8216.    Help_Directory  : Text :=  Help_Setup.Help_Directory ;
  8217.  
  8218.    Help_Ext        : Text := Help_Setup.Help_File_Name_Ext;
  8219.  
  8220.    Title_Max_Length: Constant Positive:= 50;
  8221.  
  8222. ------------------------------------------------------------------------
  8223. ------------------------------------------------------------------------
  8224.  
  8225.    procedure Check_Dist_Set (Dist_Set: in Boolean) is
  8226.  
  8227.    begin
  8228.  
  8229.       if not Dist_Set then
  8230.          Error ("The Distribution has not been set.");
  8231.          raise Command_Error;
  8232.       end if;
  8233.  
  8234.    end Check_Dist_Set;
  8235.  
  8236. ------------------------------------------------------------------------
  8237. ------------------------------------------------------------------------
  8238.  
  8239.    procedure Check_Nnodes_Set (Nnodes_Set: in Boolean) is
  8240.  
  8241.    begin
  8242.  
  8243.       if not Nnodes_Set then
  8244.          Error ("Nnodes has not been set.");
  8245.          raise Command_Error;
  8246.       end if;
  8247.  
  8248.    end Check_Nnodes_Set;
  8249.  
  8250. ------------------------------------------------------------------------
  8251. ------------------------------------------------------------------------
  8252.  
  8253.    procedure Check_Nnodes_Not_Set (Nnodes_Set: in Boolean) is
  8254.  
  8255.    begin
  8256.  
  8257.       if Nnodes_Set then
  8258.          Error ("Nnodes has already been set. Use 'Reset'.");
  8259.          raise Command_Error;
  8260.       end if;
  8261.  
  8262.    end Check_Nnodes_Not_Set;
  8263. --LINEFEED
  8264. procedure Check_Node_Subcommand_Ok (Node_Set  : in Boolean;
  8265.                                     Global_Set: in GlobalStatusType) is
  8266.  
  8267. begin
  8268.  
  8269.    if not Node_Set then
  8270.       Error ("The following command(s) must first be issued: " &
  8271.          Missing_Global_Commands(Global_Set) & " Node.");
  8272.       raise Command_Error;
  8273.    end if;
  8274.  
  8275. end Check_Node_Subcommand_Ok;
  8276.  
  8277. ------------------------------------------------------------------------
  8278. ------------------------------------------------------------------------
  8279.  
  8280. procedure Check_N_Stages_Set (N_Stages_Set: in Boolean) is
  8281.  
  8282. begin
  8283.  
  8284.    if not N_Stages_Set then
  8285.       Error ("Nstages has not been set.");
  8286.       raise Command_Error;
  8287.    end if;
  8288.  
  8289. end Check_N_Stages_Set;
  8290.  
  8291. ------------------------------------------------------------------------
  8292. ------------------------------------------------------------------------
  8293.  
  8294. procedure Check_Order_Not_Set (Order_Set: in Boolean) is
  8295.  
  8296. begin
  8297.  
  8298.    if Order_Set then
  8299.       Error ("Order has already been set. Use 'Reset'.");
  8300.       raise Command_Error;
  8301.    end if;
  8302.  
  8303. end Check_Order_Not_Set;
  8304.  
  8305. ------------------------------------------------------------------------
  8306. ------------------------------------------------------------------------
  8307.  
  8308. procedure Display (Message       : in String;
  8309.                    Is_Prompt_Mode: in Boolean := False) is
  8310. begin
  8311.  
  8312.    if Is_Prompt_Mode then
  8313.       Write ("", Spacing => Single);
  8314.    end if;
  8315.  
  8316.    Write (Message, Spacing => Single);
  8317.    Write (MMImode'Image(Mode(Is_Prompt_Mode))(1 .. 1) & "> ");
  8318.  
  8319. end Display;
  8320. --LINEFEED
  8321. function Equal (V1: in Real;
  8322.                 V2: in Real) return Boolean is
  8323.  
  8324. begin
  8325.  
  8326.    return Abs(V1-V2) < 1.0E-3;
  8327.  
  8328. end Equal;
  8329.  
  8330. ------------------------------------------------------------------------
  8331. ------------------------------------------------------------------------
  8332.  
  8333. procedure Error (Message: in String) is
  8334.  
  8335. begin
  8336.  
  8337.    Write("Error. " & Message & " Rest of input line ignored.",
  8338.       Terminal_Out, Single);
  8339.    Flush_Input;
  8340.  
  8341. end Error;
  8342. --LINEFEED
  8343. procedure Get_Cbranch (C_Branch: in out ContinProbs;
  8344.                        Mode    : in     MMImode := Edit;
  8345.                        Query   : in     Text    := No_Query) is
  8346.  
  8347.    Response : Text;
  8348.    Zero_Prob: Boolean;
  8349.  
  8350. begin
  8351.  
  8352.    loop
  8353.       begin
  8354.          if Mode = Prompt and C_Branch'Length > 1 then
  8355.             Display (Strng(Query), Is_Prompt_Mode);
  8356.          end if;
  8357.  
  8358.          Zero_Prob := False;
  8359.          for Idx in NumCoxianStages(1) .. C_Branch'Length-1 loop
  8360.             Response := Txt(Token);
  8361.             Set (C_Branch(Idx), Make_Float(Response));
  8362.             if C_Branch(Idx) = 0.0 then
  8363.                Zero_Prob := True;
  8364.                exit;
  8365.             end if;
  8366.          end loop;
  8367.  
  8368.          if Zero_Prob then
  8369.             Error ("A Cbranch value is 0.0");
  8370.             if Mode /= Prompt then
  8371.                raise Command_Error;
  8372.             end if;
  8373.          else
  8374.             return;
  8375.          end if;
  8376.  
  8377.       exception
  8378.          when EOF | Command_Error =>
  8379.             raise;
  8380.          when others              =>
  8381.             Error ("Cbranch value" & Quote(Response) &
  8382.                "not in range 0.0 .. 1.0, excluding 0.0");
  8383.             if Mode /= Prompt then
  8384.                raise Command_Error;
  8385.             end if;
  8386.       end;
  8387.    end loop;
  8388.  
  8389. end Get_Cbranch;
  8390. --LINEFEED
  8391. procedure Get_Infile is
  8392.  
  8393.    Name: Text := Txt(Token);
  8394.  
  8395. begin
  8396.  
  8397.    if Get_Media(Input) = Terminal then
  8398.       Openf (Input, Strng(Name));
  8399.       Set_Media (Input, File);
  8400.    else
  8401.       Error ("Nested infiles are not allowed.");
  8402.    end if;
  8403.  
  8404. exception
  8405.    when others =>
  8406.       Error ("Input file '" & Strng(Name) & "' could not be opened.");
  8407.  
  8408. end Get_Infile;
  8409.  
  8410. ------------------------------------------------------------------------
  8411. ------------------------------------------------------------------------
  8412.  
  8413. procedure Get_Integer (Target     : out Item;
  8414.                        Target_Type: in  String;
  8415.                        Mode       : in  MMImode := Edit;
  8416.                        Query      : in  Text    := No_Query) is
  8417.    Response: Text;
  8418.  
  8419. begin
  8420.  
  8421. loop
  8422.    begin
  8423.       if Mode = Prompt then
  8424.          Display (Strng(Query), Is_Prompt_Mode);
  8425.       end if;
  8426.  
  8427.       Response := Txt(Token);
  8428.       Target   := Item'Value (Strng(Response));
  8429.       exit;
  8430.  
  8431.    exception
  8432.       when EOF    =>
  8433.          raise;
  8434.       when others =>
  8435.          Error (Target_Type & Quote(Response) & "not in range " &
  8436.             Item'Image(Item'First) & " .. " & Item'Image(Item'Last));
  8437.          if Mode /= Prompt then
  8438.             raise Command_Error;
  8439.          end if;
  8440.    end;
  8441. end loop;
  8442.  
  8443. end Get_Integer;
  8444. --LINEFEED
  8445. procedure Get_Node_Info  (Val : in out NodeValueType;
  8446.                           Set :    out NodeStatusType) is
  8447.  
  8448.    ND      : NodeDef;
  8449.    SD      : ServDisc;
  8450.  
  8451. begin
  8452.  
  8453.    Get_Node (Strng(Val.Name,NodeName'Length), ND);
  8454.  
  8455.    Set := (Discip    => True,
  8456.            P_Branch  => True,
  8457.            Dist      => True,
  8458.            N_Servers => True,
  8459.            others    => False);
  8460.  
  8461.    SD := Node_Serv_Disc (ND);
  8462.  
  8463.    Val.P_Branch  := Get_Pbranch (ND);
  8464.    Val.Discip    := SD.Serv_Mode;
  8465.    Val.N_Servers := SD.Num_Servers;
  8466.    Val.Dist      := SD.Serv_Funct.Serv_Dist;
  8467.  
  8468.    case Val.Dist is
  8469.       when Exponential =>
  8470.          Val.Expon_Rates(1)  := SD.Serv_Funct.Expon_Rate;
  8471.          Set.Expon_Rate      := True;
  8472.       when Erlang      =>
  8473.          Val.N_Erlang_Stages := SD.Serv_Funct.Num_Erlang_Stages;
  8474.          Set.N_Erlang_Stages := True;
  8475.          Val.Erlang_Rates(1) := SD.Serv_Funct.Erlang_Rate;
  8476.          Set.Erlang_Rate     := True;
  8477.       when Coxian      =>
  8478.          Val.Coxian_Dist     := SD.Serv_Funct.Coxian_Dist;
  8479.          Val.N_Coxian_Stages := Val.Coxian_Dist.Num_Coxian_Stages;
  8480.          Set.N_Coxian_Stages := True;
  8481.          Set.Coxian_Rates    := True;
  8482.          Set.C_Branch        := True;
  8483.    end case;
  8484.  
  8485. exception
  8486.    when others =>
  8487.       Error ("Node" & Quote(Val.Name) & "is not found.");
  8488.  
  8489. end Get_Node_Info;
  8490. --LINEFEED
  8491. procedure Get_Node_List  (Node_List: in out NodeList;
  8492.                           Nodes    : in     NodesType) is
  8493.  
  8494.    Tok:      Text;
  8495.    Idx:      Positive;
  8496.    use Net_Stats.Node_List_Handler;
  8497.  
  8498. ------------------------------------------------------------------------
  8499.  
  8500.    procedure Check_Node (Tok: in Text) is
  8501.  
  8502.    begin
  8503.  
  8504.       if Index (Tok, Nodes) = 0 then
  8505.          Error ("Node name" & Quote(Tok) & "is invalid.");
  8506.          raise Command_Error;
  8507.       end if;
  8508.  
  8509.    end Check_Node;
  8510.  
  8511. ------------------------------------------------------------------------
  8512.  
  8513. begin
  8514.  
  8515.    Dispose (Node_List);
  8516.    Tok := Txt(Token);
  8517.  
  8518.    if Tok = Txt("(") then
  8519.       Tok := Txt(Token);
  8520.       Idx := 1;
  8521.       while (Tok /= Txt(")")) loop
  8522.          Check_Node (Tok);
  8523.  
  8524.          Insert (Node_List, Strng(Tok,NodeName'Length), After);
  8525.  
  8526.          if Idx > Nodes.Name'Length then
  8527.             Error ("More nodes have been specified than in the model.");
  8528.             raise Command_Error;
  8529.          end if;
  8530.  
  8531.          Tok := Txt(Token);
  8532.          Idx := Idx + 1;
  8533.       end loop;
  8534.    elsif Up_Case(Tok) = Txt("ALL") then
  8535.       for Nodex in Nodes.Name'Range loop
  8536.          Insert (Node_List, Nodes.Name(Nodex), After);
  8537.       end loop;
  8538.    else
  8539.       Check_Node (Tok);
  8540.       Insert (Node_List, Strng(Tok,NodeName'Length), After);
  8541.    end if;
  8542. end Get_Node_List;
  8543.  
  8544. --LINEFEED
  8545. procedure Get_Order (Nodes:   in out NodesType;
  8546.                      N_Nodes: in     NumNodes;
  8547.                      Mode   : in     MMImode := Edit;
  8548.                      Query  : in     Text    := No_Query)   is
  8549.  
  8550.    Bad_Nodes: Exception;
  8551.    Blank    : NodeName := (others => ' ');
  8552.    Save     : Text;
  8553.    Node     : Text;
  8554.  
  8555. begin
  8556.  
  8557.    Nodes := (N_Nodes, (others => Blank));
  8558.    loop
  8559.       begin
  8560.          if Mode = Prompt then
  8561.             Display (Strng(Query), Is_Prompt_Mode);
  8562.          end if;
  8563.  
  8564.          for Nodex in 1 .. N_Nodes loop
  8565.             Node := Txt(Token);
  8566.  
  8567.             if (Nodex = 1 and Next_Token_Exists) and then
  8568.                Node = Txt("(") then
  8569.                   Node := Txt(Token);
  8570.             end if;
  8571.  
  8572.             if Nodex = N_Nodes and Next_Token_Exists then
  8573.                Save := Txt(Token);
  8574.                if Save /= Txt(")") then
  8575.                   Replace_Token(Save);
  8576.                end if;
  8577.             end if;
  8578.  
  8579.             if Length(Node) > NodeName'Length then
  8580.                Error("Node name" & Quote(Node) & "exceeds " &
  8581.                   Strng(Txt(NodeName'Length)) & " characters.");
  8582.                raise Bad_Nodes;
  8583.             end if;
  8584.  
  8585.             Save := Up_Case(Node);
  8586.             if Save = Txt("ALL") or Save = Txt("FROM") or
  8587.                Save = Txt("BY")  or Save = Txt("TO") then
  8588.                   Error("A node name cannot be one of: " &
  8589.                      "all, by, from, to.");
  8590.                   raise Bad_Nodes;
  8591.             end if;
  8592.  
  8593.             if Index(Node,Txt("(")) > 0 or Index(Node,Txt(")")) > 0 then
  8594.                Error("A node name cannot contain '(' or ')'.");
  8595.             end if;
  8596.  
  8597.             Nodes.Name(Nodex) := Strng(Node,NodeName'Length);
  8598.  
  8599.          end loop;
  8600. --LINEFEED
  8601.        for Nodex1 in 1 .. N_Nodes loop
  8602.             for Nodex2 in Nodex1+1 .. N_Nodes  loop
  8603.                if Nodes.Name (Nodex1) = Nodes.Name (Nodex2) then
  8604.                   Error ("Node name '" & Short(Nodes.Name(Nodex1)) &
  8605.                      "' is not unique.");
  8606.                   raise Bad_Nodes;
  8607.                end if;
  8608.             end loop;
  8609.          end loop;
  8610.  
  8611.          return;
  8612.  
  8613.       exception
  8614.          when Bad_Nodes =>
  8615.             if Mode /= Prompt then
  8616.                raise Command_Error;
  8617.             end if;
  8618.          when others    =>
  8619.             raise;
  8620.       end;
  8621.    end loop;
  8622.  
  8623. end Get_Order;
  8624. --LINEFEED
  8625. procedure Get_Outfile is
  8626.  
  8627.    Name: Text := Txt(Token);
  8628.  
  8629. begin
  8630.  
  8631.    If Get_Media (Report) = File then
  8632.       Closef    (Report);
  8633.       Set_Media (Report, Terminal);
  8634.    end if;
  8635.  
  8636.    if not Equal (Up_Case(Name), Txt("TERMINAL")) then
  8637.       Openf     (Report, Strng(Name));
  8638.       Set_Media (Report, File);
  8639.    end if;
  8640.  
  8641. exception
  8642.    when EOF    =>
  8643.       raise;
  8644.    when others =>
  8645.       Error ("Output file could not be opened.");
  8646.  
  8647. end Get_Outfile;
  8648.  
  8649. ------------------------------------------------------------------------
  8650. ------------------------------------------------------------------------
  8651.  
  8652. Function  Get_Pbranch (Node_Def: in NodeDef) return PbranchType is
  8653.  
  8654.    Pbranch : RealVector;
  8655.    P_Branch: PbranchType;
  8656.  
  8657. begin
  8658.  
  8659.    Pbranch := Node_Connect_Prob (Node_Def);
  8660.    P_Branch:= (Last_Index_Of(Pbranch), (others => 0.0));
  8661.  
  8662.    for Nodex in P_Branch.Val'Range loop
  8663.       P_Branch.Val(Nodex) := Probs (Real'(Value_Of(Pbranch,Nodex)));
  8664.    end loop;
  8665.  
  8666.    return P_Branch;
  8667.  
  8668. end Get_Pbranch;
  8669. --LINEFEED
  8670. procedure Get_Pbranch (Nnodes   : in  NumNodes;
  8671.                        P_Branch : out PbranchType;
  8672.                        Mode     : in  MMImode := Edit;
  8673.                        Query    : in  Text    := No_Query) is
  8674.  
  8675.    Sum     : Real;
  8676.    Response: Text;
  8677.    Pbranch : PbranchType := (Nnodes, (others => 0.0));
  8678.  
  8679. begin
  8680.  
  8681.    loop
  8682.       begin
  8683.          if Mode = Prompt then
  8684.             Display (Strng(Query), Is_Prompt_Mode);
  8685.          end if;
  8686.  
  8687.          Sum := 0.0;
  8688.          for Nodex in 1 .. Nnodes loop
  8689.             Response := Txt(Token);
  8690.             Set (Pbranch.Val(Nodex), Make_Float(Response));
  8691.             Sum := Sum + Real (Pbranch.Val(Nodex));
  8692.          end loop;
  8693.  
  8694.          if Equal (Sum, 1.0) then
  8695.             P_Branch := Pbranch;
  8696.             exit;
  8697.          else
  8698.             Error ("The branching probabilities do not sum to 1.0");
  8699.             if Mode /= Prompt then
  8700.                raise Command_Error;
  8701.             end if;
  8702.          end if;
  8703.  
  8704.       exception
  8705.          when EOF           =>
  8706.             raise;
  8707.          when Command_Error =>
  8708.             raise;
  8709.          when others        =>
  8710.             Error ("Pbranch value" & Quote(Response) &
  8711.                "not in range 0.0 .. 1.0");
  8712.             if Mode /= Prompt then
  8713.                raise Command_Error;
  8714.             end if;
  8715.       end;
  8716.    end loop;
  8717.  
  8718. end Get_Pbranch;
  8719. --LINEFEED
  8720. procedure Get_Rates (Rates: in out Vector;
  8721.                      Mode : in     MMImode := Edit;
  8722.                      Query: in     Text    := No_Query) is
  8723.  
  8724.    Sum     : Real;
  8725.    Response: Text;
  8726.  
  8727. begin
  8728.  
  8729.    loop
  8730.       begin
  8731.          if Mode = Prompt then
  8732.             Display (Strng(Query), Is_Prompt_Mode);
  8733.          end if;
  8734.  
  8735.          for Ratex in Rates'Range loop
  8736.             Response := Txt(Token);
  8737.             Set (Real(Rates(Ratex)), Make_Float(Response));
  8738.          end loop;
  8739.  
  8740.          exit;
  8741.  
  8742.       exception
  8743.          when EOF    =>
  8744.             raise;
  8745.          when others =>
  8746.             Error ("Rate" & Quote(Response) & "not in range " &
  8747.                   Strng(Txt(Floating'Small)) & " .. " &
  8748.                   Strng(Txt(Floating'Large)));
  8749.             if Mode /= Prompt then
  8750.                raise Command_Error;
  8751.             end if;
  8752.       end;
  8753.    end loop;
  8754.  
  8755. end Get_Rates;
  8756. --LINEFEED
  8757. procedure Get_Text    (Target     : out Item;
  8758.                        Target_Type: in  String;
  8759.                        Mode       : in  MMImode := Edit;
  8760.                        Query      : in  Text    := No_Query) is
  8761.  
  8762.    Response: Text;
  8763.    Sum     : Integer;
  8764.    Match   : Item;
  8765.  
  8766. begin
  8767.  
  8768. loop
  8769.    begin
  8770.       if Mode = Prompt then
  8771.          Display (Strng(Query), Is_Prompt_Mode);
  8772.       end if;
  8773.  
  8774.       Response := Txt(Token);
  8775.  
  8776.       Sum := 0;
  8777.       For Val in Item'First .. Item'Last loop
  8778.          if Index (Up_Case(Txt(Item'Image(Val))),
  8779.                    Up_Case(Response))                = 1 then
  8780.             Match := Val;
  8781.             Sum   := Sum + 1;
  8782.          end if;
  8783.       end loop;
  8784.  
  8785.       if    Sum = 0 then
  8786.          Error (Target_Type & Quote(Response) & "is invalid.");
  8787.          if Mode /= Prompt then
  8788.             raise Command_Error;
  8789.          end if;
  8790.       elsif Sum = 1 then
  8791.          Target := Match;
  8792.          return;
  8793.       else
  8794.          Error (Target_Type & Quote(Response) & "is not unique.");
  8795.          if Mode /= Prompt then
  8796.             raise Command_Error;
  8797.          end if;
  8798.       end if;
  8799.    end;
  8800. end loop;
  8801.  
  8802. end Get_Text;
  8803. --LINEFEED
  8804. procedure Get_Title (Model_Title: out Text;
  8805.                      Mode       : in  MMImode := Edit;
  8806.                      Query      : in  Text := No_Query) is
  8807.  
  8808.    Response: Text;
  8809.  
  8810. begin
  8811.  
  8812.    loop
  8813.       begin
  8814.          if Mode = Prompt then
  8815.             Display (Strng(Query), Is_Prompt_Mode);
  8816.             Response := Txt(Token);
  8817.             Replace_Token (Response);
  8818.          end if;
  8819.  
  8820.          Response := Remove_Leading (Remove_Trailing (
  8821.             Input_Line," ")," ");
  8822.  
  8823.          if Length(Response) <= Title_Max_Length then
  8824.             Model_Title := Response;
  8825.             return;
  8826.          else
  8827.             Error ("The title exceeds " & Strng(Txt(Title_Max_Length)) &
  8828.                " characters.");
  8829.             if Mode /= Prompt then
  8830.                raise Command_Error;
  8831.             end if;
  8832.          end if;
  8833.       end;
  8834.    end loop;
  8835.  
  8836. end Get_Title;
  8837. --LINEFEED
  8838. procedure Help (Topic_Short: in Text) is
  8839.  
  8840.    Topic_Long: Text;
  8841.  
  8842. ------------------------------------------------------------------------
  8843.  
  8844.    procedure Open_Help_File (Path: in String) is
  8845.  
  8846.    begin
  8847.  
  8848.       Openf (Help, Path);
  8849.  
  8850.    exception
  8851.       when others =>
  8852.          Error ("The file '" & Path & "' could not be opened.");
  8853.          raise Command_Error;
  8854.  
  8855.    end Open_Help_File;
  8856.  
  8857. ------------------------------------------------------------------------
  8858.  
  8859.    procedure Read_Line (Line: out String) is
  8860.  
  8861.    begin
  8862.  
  8863.       Line := (Line'Range => ' ');
  8864.       Read (Line);
  8865.  
  8866.    exception
  8867.       when EOF    =>
  8868.          Closef (Help);
  8869.          raise;
  8870.       when others =>
  8871.          Error ("An error has been encountered while reading the " &
  8872.                 "help file.");
  8873.          Closef (Help);
  8874.          raise Command_Error;
  8875.    end Read_Line;
  8876. --LINEFEED
  8877.    procedure Find_Index_Keyword is
  8878.  
  8879.       Line: String (1..80) := (others => ' ');
  8880.  
  8881.    begin
  8882.  
  8883.       while Line(1) /= '%' loop
  8884.          Read_Line (Line);
  8885.       end loop;
  8886.  
  8887.    exception
  8888.       when EOF    =>
  8889.          Error ("The help index is invalid.");
  8890.          raise Command_Error;
  8891.       when others =>
  8892.          raise;
  8893.  
  8894.    end Find_Index_Keyword;
  8895. --LINEFEED   
  8896.    procedure Check_Topic_In_Index (Topic_Short: in  Text;
  8897.                                    Topic_Long : out Text) is
  8898.  
  8899.       Line          : String (1..80);
  8900.       Topic_To_Check: Text;
  8901.       Count         : Integer := 0;
  8902.  
  8903.    begin
  8904.  
  8905.       loop
  8906.          Read_Line (Line);
  8907.          exit when Line(1) = '%';
  8908.  
  8909.          Topic_To_Check := Up_Case(Before(Txt(Line),Txt(" ")));
  8910.          if Index (Topic_To_Check, Up_Case(Topic_Short)) = 1 then
  8911.             Topic_Long := Topic_To_Check;
  8912.             Count      := Count + 1;
  8913.          end if;
  8914.       end loop;
  8915.  
  8916.       if    Count = 0 then
  8917.          Error (Quote(Topic_Short) & "is not a help topic.");
  8918.          Closef (Help);
  8919.          raise Command_Error;
  8920.       elsif Count > 1 then
  8921.          Error (Quote(Topic_Short) & "is not a unique help topic.");
  8922.          Closef (Help);
  8923.          raise Command_Error;
  8924.       end if;
  8925.  
  8926.    exception
  8927.       when EOF    =>
  8928.          Error ("End of file was reached while reading the help " &
  8929.                 "index.");
  8930.          raise Command_Error;
  8931.       when others =>
  8932.          raise;
  8933.  
  8934.    end Check_Topic_In_Index;
  8935. --LINEFEED 
  8936.    procedure Display_Index is
  8937.  
  8938.       Column     : Positive := 61;
  8939.       Index_Topic: Text;
  8940.       Line       : String (1..80);
  8941.  
  8942.    begin
  8943.  
  8944.       Write ("Help is available on the following topics:",
  8945.          Terminal_Out, Double);
  8946.  
  8947.       loop
  8948.          Read_Line (Line);
  8949.          exit when Line(1) = '%';
  8950.  
  8951.          Index_Topic := Before(Txt(Line),Txt(" "));
  8952.          Column := ((Column + 19) mod 80) + 1;
  8953.          Set_Column (Column);
  8954.          Write (Strng(Index_Topic));
  8955.       end loop;
  8956.  
  8957.       Write (" ", Spacing=>Single);
  8958.  
  8959.    exception
  8960.       when EOF    =>
  8961.          Error ("End of file was reached while reading the help " &
  8962.                 "index.");
  8963.          raise Command_Error;
  8964.       when others =>
  8965.          raise;
  8966.  
  8967.    end Display_Index;
  8968. --LINEFEED   
  8969.    procedure Display_Topic (Topic_Long: in Text) is
  8970.  
  8971.       Line: String (1..80);
  8972.  
  8973.    begin
  8974.  
  8975.       begin
  8976.          loop
  8977.             Read_Line (Line);
  8978.             exit when Equal (Up_Case (Before (Txt(Line), Txt(" "))),
  8979.                              Txt('%') & Topic_Long);
  8980.          end loop;
  8981.  
  8982.       exception
  8983.          when EOF    =>
  8984.             Error ("The topic has no information available.");
  8985.             raise Command_Error;
  8986.          when others =>
  8987.             raise;
  8988.       end;
  8989.  
  8990.       begin
  8991.          loop
  8992.             Read_Line (Line);
  8993.             exit when Line(1) = '%';
  8994.             Write (Strng(Remove_Trailing(Txt(Line)," ")),
  8995.                Spacing=>Single);
  8996.          end loop;
  8997.  
  8998.       end;
  8999.  
  9000.    end Display_Topic;
  9001.  
  9002. ------------------------------------------------------------------------
  9003.  
  9004. begin
  9005.  
  9006.    Open_Help_File (Strng(Help_Directory) & "index" & Strng(Help_Ext));
  9007.    Find_Index_Keyword;
  9008.  
  9009.    if Up_Case(Topic_Short) = Txt("INDEX") then
  9010.       Display_Index;
  9011.    else
  9012.       Check_Topic_In_Index (Topic_Short, Topic_Long);
  9013.       Closef (Help);
  9014.       Open_Help_File (Strng(Help_Directory & Topic_Long & Help_Ext));
  9015.       Display_Topic (Topic_Long);
  9016.    end if;
  9017.  
  9018.    Closef (Help);
  9019.  
  9020. exception
  9021.    when EOF     =>
  9022.       null;
  9023.    when others  =>
  9024.       raise;
  9025.  
  9026. end Help;
  9027. --LINEFEED
  9028. function  Index       (Node_Name: in Text;
  9029.                        Nodes    : in NodesType) return integer is
  9030.  
  9031. begin
  9032.  
  9033.    for Nodex in Nodes.Name'Range loop
  9034.       if Strng(Node_Name,NodeName'Length) = Nodes.Name(Nodex) then
  9035.          return Nodex;
  9036.       end if;
  9037.    end loop;
  9038.  
  9039.    return 0;
  9040.  
  9041. end Index;
  9042.  
  9043. ------------------------------------------------------------------------
  9044. ------------------------------------------------------------------------
  9045.  
  9046. procedure Insert_Dummy_Nodes (Nodes: in NodesType) is
  9047.  
  9048.    Connect_Probs : RealVector := Allocate(Nodes.Name'Length);
  9049.    ND            : NodeDef;
  9050.  
  9051. begin
  9052.  
  9053.    Set_Up_New_Network;
  9054.  
  9055.    for Nodex in Nodes.Name'Range loop
  9056.       Assign (Connect_Probs, Nodex, 0.0);
  9057.    end loop;
  9058.  
  9059.    for Nodex in Nodes.Name'Range loop
  9060.       Insert_Node (Create_Node (Nodes.Name(Nodex), False, (Fcfs, 1,
  9061.          (Exponential, 1.0)), Connect_Probs), After);
  9062.    end loop;
  9063.  
  9064. end Insert_Dummy_Nodes;
  9065.  
  9066. ------------------------------------------------------------------------
  9067. ------------------------------------------------------------------------
  9068.  
  9069. function Make_Float (From: in Text) return Text is
  9070.  
  9071. begin
  9072.  
  9073.    if Index (From, Txt(".")) = 0 then
  9074.       return Txt("0") & From & Txt(".0");
  9075.    else
  9076.       return Txt("0") & From;
  9077.    end if;
  9078.  
  9079. end Make_Float;
  9080. --LINEFEED
  9081. function Missing_Global_Commands (Set: in GlobalStatusType)
  9082.                                   return String is
  9083.  
  9084.    List : Text := Txt("");
  9085.  
  9086. begin
  9087.  
  9088.    if not Set.N_Nodes then
  9089.       List := List & Txt("Nnodes,");
  9090.    end if;
  9091.  
  9092.    if not Set.Order then
  9093.       List := List & Txt("Order,");
  9094.    end if;
  9095.  
  9096.    if not Set.N_Jobs then
  9097.       List := List & Txt("Njobs,");
  9098.    end if;
  9099.  
  9100.    return Strng (List);
  9101.  
  9102. end Missing_Global_Commands;
  9103. --LINEFEED
  9104. function  Missing_Node_Commands (Set : NodeStatusType;
  9105.                                  Dist: ServDist)
  9106.                                                        return String is
  9107.  
  9108.    List          : Text := Txt("");
  9109.  
  9110. begin
  9111.  
  9112.    if not Set.P_Branch then
  9113.       List := List & Txt("Pbranch,");
  9114.    end if;
  9115.  
  9116.    if not Set.Discip then
  9117.       List := List & Txt("Discipline,");
  9118.    end if;
  9119.  
  9120.    if not Set.Dist then
  9121.       List := List & Txt("Distribution,");
  9122.    end if;
  9123.  
  9124.    if not Set.N_Servers then
  9125.       List := List & Txt("Nservers,");
  9126.    end if;
  9127.  
  9128.    case Dist is
  9129.       when Exponential =>
  9130.          if not Set.Expon_Rate then
  9131.             List := List & Txt("Rate,");
  9132.          end if;
  9133.       when Erlang      =>
  9134.          if not Set.N_Erlang_Stages then
  9135.             List := List & Txt("Nstages,");
  9136.          end if;
  9137.  
  9138.          if not Set.Erlang_Rate then
  9139.             List := List & Txt("Rate,");
  9140.          end if;
  9141.       when Coxian      =>
  9142.          if not Set.N_Coxian_Stages then
  9143.             List := List & Txt("Nstages,");
  9144.          end if;
  9145.  
  9146.          if not Set.C_Branch then
  9147.             List := List & Txt("Cbranch,");
  9148.          end if;
  9149.  
  9150.          if not Set.Coxian_Rates then
  9151.             List := List & Txt("Rates,");
  9152.          end if;
  9153.    end case;
  9154.  
  9155.    return Strng(List);
  9156.  
  9157. end Missing_Node_Commands;
  9158. --LINEFEED
  9159. function Mode (Is_Prompt_Mode: in Boolean := False)  return MmiMode is
  9160.  
  9161. begin
  9162.    if Is_Prompt_Mode then
  9163.       return Prompt;
  9164.    elsif Get_Media(Input) = File then
  9165.       return Infile;
  9166.    else
  9167.       return Edit;
  9168.    end if;
  9169.  
  9170. end Mode;
  9171.  
  9172. ------------------------------------------------------------------------
  9173. ------------------------------------------------------------------------
  9174.  
  9175. procedure Put_Node_Info  (Val  : in NodeValueType;
  9176.                           Set  : in NodeStatusType) is
  9177.  
  9178.    Connect_Probs : RealVector;
  9179.    List          : Text := Txt (Missing_Node_Commands(Set, Val.Dist));
  9180.    Found         : Boolean;
  9181.    Node_Name     : NodeName := Strng(Val.Name, NodeName'Length);
  9182.  
  9183. begin
  9184.  
  9185.    if Length(List) > 0 then
  9186.       Error ("The following command(s) have not been issued: " &
  9187.              Strng(List));
  9188.       raise Command_Error;
  9189.    end if;
  9190.  
  9191.    Connect_Probs := Allocate (Val.P_Branch.Val'Length);
  9192.    for Nodex in Val.P_Branch.Val'Range loop
  9193.       Assign (Connect_Probs, Nodex, Val.P_Branch.Val(Nodex));
  9194.    end loop;
  9195.  
  9196.    case Val.Dist is
  9197.       when Exponential =>
  9198.          Found := Replace_Node (Node_Name, Create_Node (Node_Name, True,
  9199.             (Val.Discip, Val.N_Servers, (Exponential,
  9200.             Val.Expon_Rates(1))), Connect_Probs));
  9201.       when Erlang      =>
  9202.          Found := Replace_Node (Node_Name, Create_Node (Node_Name, True,
  9203.             (Val.Discip, Val.N_Servers, (Erlang, Val.N_Erlang_Stages,
  9204.             Val.Erlang_Rates(1))), Connect_Probs));
  9205.       when Coxian      =>
  9206.          Found := Replace_Node (Node_Name, Create_Node (Node_Name, True,
  9207.             (Val.Discip, Val.N_Servers, (Coxian, Val.Coxian_Dist)),
  9208.             Connect_Probs));
  9209.    end case;
  9210.  
  9211. end Put_Node_Info;
  9212. --LINEFEED
  9213. function Quote (From: in Text)  return String is
  9214.  
  9215. begin
  9216.  
  9217.    return " '" & Strng(From) & "' ";
  9218.  
  9219. end Quote;
  9220. --LINEFEED
  9221. procedure Report_Set_Up (Report_Type: in ReportType;
  9222.                          N_Jobs     : NumJobs;
  9223.                          Nodes      : in NodesType) is
  9224.  
  9225.    Node_List : NodeList;
  9226.    type        FromToBy is (From, To, By);
  9227.    From_To_By: FromToBy;
  9228.    type        ListArray is array (FromToBy) of NodeList;
  9229.    Lists     : ListArray;
  9230.    type        NaturalArray is array (FromToBy) of Natural;
  9231.    Naturals  : NaturalArray;
  9232.  
  9233. ------------------------------------------------------------------------
  9234.  
  9235.    procedure Get_From_To_By (Lists: in out ListArray) is
  9236.  
  9237.       Tok: Text;
  9238.  
  9239.    begin
  9240.  
  9241.       for Idx in Lists'Range loop
  9242.          Tok := Txt(Token);
  9243.          if Up_Case(Tok) = Up_Case(Txt(FromToBy'Image(Idx))) then
  9244.             Get_Node_List (Lists(Idx), Nodes);
  9245.          else
  9246.             Replace_Token (Tok);
  9247.             Get_Node_List (Lists(Idx), Nodes);
  9248.          end if;
  9249.       end loop;
  9250.  
  9251.    end Get_From_To_By;
  9252.  
  9253. --LINEFEED
  9254.    begin
  9255.  
  9256.    case Report_Type is
  9257.       when Arrival_Frequencies =>
  9258.          Get_Node_List (Node_List, Nodes);
  9259.          Display_Arrival_Freqs (Node_List);
  9260.       when Routing             =>
  9261.          Get_From_To_By (Lists);
  9262.          Display_Routing (Lists(From), Lists(To), Lists(By));
  9263.       when Serv_Times          =>
  9264.          Get_Node_List (Node_List, Nodes);
  9265.          Display_Serv_Times (Node_List);
  9266.       when Serv_Requirements   =>
  9267.          Get_From_To_By (Lists);
  9268.          Display_Service (Lists(From), Lists(To), Lists(By));
  9269.       when Response_Times      =>
  9270.          Get_Node_List (Node_List, Nodes);
  9271.          Display_Response_Times (Node_List);
  9272.       when Throughput          =>
  9273.          Get_Node_List (Node_List, Nodes);
  9274.          Display_Q_Lengths (Node_List);
  9275.       when Qlength_Distributions =>
  9276.          Get_Node_List (Node_List, Nodes);
  9277.          Display_Q_Length_Dists (Node_List);
  9278.       when Normalizations      =>
  9279.          null;
  9280.          Display_GNorms;
  9281.       when Pbranch             =>
  9282.          null;
  9283.          Display_Pbranch;
  9284.       when Model               =>
  9285.          null;                 -- this was done in main routine.
  9286.    end case;
  9287.  
  9288.    Dispose(Node_List);
  9289.    for Idx in Lists'Range loop
  9290.       Dispose (Lists(Idx));
  9291.    end loop;
  9292.  
  9293. end Report_Set_Up;
  9294. --LINEFEED
  9295. procedure Run (Nodes : in NodesType;
  9296.                N_Jobs: in NumJobs) is
  9297.  
  9298.    Bad_Node: Boolean := False;
  9299.  
  9300. begin
  9301.  
  9302.    if Nodes.Name'Length = 0 then
  9303.       Error ("The model has no nodes.");
  9304.       Bad_Node := True;
  9305.    end if;
  9306.  
  9307.    for Nodex in Nodes.Name'Range loop
  9308.       if not Node_Is_Complete(Nodes.Name(Nodex)) then
  9309.          Error ("Node '" & Short(Nodes.Name(Nodex)) & "' is not set.");
  9310.          Bad_Node := True;
  9311.       end if;
  9312.    end loop;
  9313.  
  9314.    if Bad_Node then
  9315.       Error("The run command has aborted.");
  9316.       raise Command_Error;
  9317.    else
  9318.       null;
  9319.       Calculate_Stats( N_Jobs);
  9320.    end if;
  9321.  
  9322. end Run;
  9323.  
  9324. ------------------------------------------------------------------------
  9325. ------------------------------------------------------------------------
  9326.  
  9327. procedure Set_Exponential (Dist : out ServDist) is
  9328.  
  9329. begin
  9330.  
  9331.    Dist := Exponential;
  9332.    Write ("The Distribution is EXPONENTIAL, " &
  9333.       "since the Discipline is FCFS.", Spacing=>Single);
  9334.  
  9335. end Set_Exponential;
  9336. --LINEFEED
  9337. procedure Set_Nservers (N_Servers  : out NumServers;
  9338.                         Discip     : in  ServMode;
  9339.                         N_Jobs     : in  NumJobs) is
  9340. begin
  9341.  
  9342.       Write("The number of servers is ");
  9343.       case Discip is
  9344.          when NQ       =>
  9345.             Write(Strng(Txt(N_Jobs)) &
  9346.                ", since the Discipline is NQ.", Spacing=>Single);
  9347.             N_Servers := NumServers(N_Jobs);
  9348.          when P_Share  =>
  9349.             Write("1, since the Discipline is P_SHARE.",
  9350.                Spacing => Single);
  9351.             N_Servers := 1;
  9352.          when PR_LCFS  =>
  9353.             Write("1, since the Discipline is PR_LCFS.",
  9354.                Spacing => Single);
  9355.             N_Servers := 1;
  9356.          when others   =>
  9357.             null;                       -- can't get here
  9358.       end case;
  9359.  
  9360. end Set_Nservers;
  9361.  
  9362. ------------------------------------------------------------------------
  9363. ------------------------------------------------------------------------
  9364.  
  9365. function Short (Node_Name: NodeName) return String is
  9366.  
  9367. begin
  9368.  
  9369.    return Strng(Remove_Trailing(Txt(Node_Name)," "));
  9370.  
  9371. end Short;
  9372.  
  9373. --LINEFEED
  9374. procedure Show_All    (Val      : in GlobalValueType;
  9375.                        Set      : in GlobalStatusType;
  9376.                        Out_Mode : in Outmode) is
  9377.  
  9378.    End_Of_Network: Boolean;
  9379.    ND            : NodeDef;
  9380.  
  9381. begin
  9382.  
  9383.    Show_Title   (Val.Title  , Set.Title  , Out_Mode);
  9384.    Show_Nnodes  (Val.N_Nodes, Set.N_Nodes, Out_Mode);
  9385.    Show_Order   (Val.Nodes  , Set.Order  , Out_Mode);
  9386.    Show_Njobs   (Val.N_Jobs , Set.N_Jobs , Out_Mode);
  9387.  
  9388.    Move_To_First_Node (End_Of_Network);
  9389.    while not End_Of_Network loop
  9390.       Get_Node (ND);
  9391.       Show_Node (Txt(Short(Name_Of_Node(ND))), Out_Mode);
  9392.       Move_To_Next_Node (End_Of_Network);
  9393.    end loop;
  9394.  
  9395. end Show_All;
  9396.  
  9397. ------------------------------------------------------------------------
  9398. ------------------------------------------------------------------------
  9399.  
  9400. procedure Show_Njobs  (N_Jobs   : NumJobs;
  9401.                        Set      : Boolean;
  9402.                        Out_Mode : Outmode)    is
  9403.  
  9404. begin
  9405.  
  9406.    if Set then
  9407.       Write("Njobs = " & Strng(Txt(N_Jobs)), Out_Mode, Single);
  9408.    else
  9409.       Write("Njobs is not set.", Spacing=>Single);
  9410.    end if;
  9411.  
  9412.  
  9413. end Show_Njobs;
  9414. --LINEFEED
  9415. procedure Show_Nnodes (N_Nodes  : in NumNodes;
  9416.                        Set      : in Boolean;
  9417.                        Out_Mode : in Outmode) is
  9418.  
  9419. begin
  9420.  
  9421.    if Set then
  9422.       Write ("Nnodes = " & Strng(Txt(N_Nodes)), Out_Mode, Single);
  9423.    else
  9424.       Write ("Nodes is not set.", Spacing=>Single);
  9425.    end if;
  9426.  
  9427. end Show_Nnodes;
  9428.  
  9429. ------------------------------------------------------------------------
  9430. ------------------------------------------------------------------------
  9431.  
  9432. procedure Show_Node   (Node_Name: in Text;
  9433.                        Out_Mode : in Outmode) is
  9434.  
  9435.    ND : NodeDef;
  9436.  
  9437. begin
  9438.  
  9439.    Get_Node  (Strng(Node_Name,NodeName'Length), ND);
  9440.    if Node_Complete(ND) then
  9441.       Show_Node (ND, Out_Mode);
  9442.    else
  9443.       Write("Node" & Quote(Node_Name) &
  9444.          "is not set.", Spacing=>Single);
  9445.    end if;
  9446.  
  9447. exception
  9448.    when others  =>
  9449.       Error ("Node" & Quote(Node_Name) & "is not in the model.");
  9450.       raise Command_Error;
  9451.  
  9452. end Show_Node;
  9453.  
  9454. --LINEFEED
  9455. procedure  Show_Node (ND       : in NodeDef;
  9456.                       Out_Mode : in OutMode) is
  9457.  
  9458.    SD         : ServDisc       := Node_Serv_Disc (ND);
  9459.    SF         : ServFunct      := Node_Serv_Funct(ND);
  9460.    P_Branch   : PbranchType    := Get_Pbranch (ND);
  9461.    CD         : CoxianDist;
  9462.  
  9463. begin
  9464.  
  9465.    Write("Node = " & Name_Of_Node(ND), Out_Mode, Single);
  9466.  
  9467.    Write(" Pbranch =  ", Out_Mode);
  9468.    for Nodex in P_Branch.Val'Range loop
  9469.       if Nodex mod 10 = 0 then
  9470.          Write ("", Out_Mode, Single);
  9471.          Write ("            ", Out_Mode);
  9472.       end if;
  9473.       Write (Strng(Txt(P_Branch.Val(Nodex))) & " ", Out_Mode);
  9474.    end loop;
  9475.    Write("", Out_Mode, Single);
  9476.  
  9477.    Write(" Discipline = " & ServMode'Image(SD.Serv_Mode), Out_Mode,
  9478.       Single);
  9479.    Write(" Nservers  = " & Strng(Txt(SD.Num_Servers)),
  9480.       Out_Mode, Single);
  9481.    Write(" Distribution  = " & ServDist'Image(
  9482.       SF.Serv_Dist), Out_Mode, Single);
  9483.  
  9484. --LINEFEED 
  9485.    case SF.Serv_Dist is
  9486.       when Exponential =>
  9487.          Write("  Rate = " & Strng(Txt(SF.Expon_Rate)),
  9488.             Out_Mode, Single);
  9489.       when Erlang      =>
  9490.          Write("  Nstages = "& Strng(Txt(SF.Num_Erlang_Stages))
  9491.             ,Out_Mode, Single);
  9492.          Write("  Rate = " & Strng(Txt(SF.Erlang_Rate)),
  9493.             Out_Mode, Single);
  9494.       when COXIAN =>
  9495.          CD := Node_Cox_Dist (ND);
  9496.  
  9497.          Write("  Nstages = "& Strng(Txt(
  9498.             CD.Num_Coxian_Stages)), Out_Mode, Single);
  9499.  
  9500.          Write("  Cbranch = ", Out_Mode);
  9501.          for Idx in 1 .. CD.Num_Coxian_Stages-1 loop
  9502.             if Idx mod 10 = 0 then
  9503.                Write ("", Out_Mode, Single);
  9504.                Write ("            ", Out_Mode);
  9505.             end if;
  9506.             Write(Strng(Txt(CD.Contin_Probs(Idx))) &
  9507.                " ", Out_Mode);
  9508.          end loop;
  9509.          Write("", Out_Mode, Single);
  9510.  
  9511.          Write("  Rates =   ", Out_Mode);
  9512.          for Idx in 1 .. CD.Num_Coxian_Stages loop
  9513.             if Idx mod 8 = 0 then
  9514.                Write ("", Out_Mode, Single);
  9515.                Write ("            ", Out_Mode);
  9516.             end if;
  9517.             Write(Strng(Txt(CD.Coxian_Rates(Idx))) &
  9518.                " ", Out_Mode);
  9519.          end loop;
  9520.          Write("", Out_Mode, Single);
  9521.    end case;
  9522.  
  9523.    Write("Endnode", Out_Mode, Single);
  9524.  
  9525. end Show_Node;
  9526. --LINEFEED
  9527. procedure Show_Order  (Nodes    : in NodesType;
  9528.                        Set      : in Boolean;
  9529.                        Out_Mode : in Outmode)    is
  9530.  
  9531. begin
  9532.  
  9533.    if Set then
  9534.       Write("Order  = ", Out_Mode);
  9535.  
  9536.       for Nodex in Nodes.Name'Range loop
  9537.          if Nodex mod 8 = 0 then
  9538.             Write ("", Out_Mode, Single);
  9539.             Write ("         ", Out_Mode);
  9540.          end if;
  9541.          Write(Short(Nodes.Name(Nodex)) & " ", Out_Mode);
  9542.       end loop;
  9543.  
  9544.       Write("", Out_Mode, Single);
  9545.    else
  9546.       Write("Order is not set.", Spacing=>Single);
  9547.    end if;
  9548.  
  9549. end Show_Order;
  9550.  
  9551. ------------------------------------------------------------------------
  9552. ------------------------------------------------------------------------
  9553.  
  9554. procedure Show_Title  (Title    : in Text;
  9555.                        Set      : in Boolean;
  9556.                        Out_Mode : in Outmode)    is
  9557.  
  9558. begin
  9559.  
  9560.    if Set then
  9561.       Write("Title  = " & Strng(Title), Out_Mode, Single);
  9562.    end if;
  9563.  
  9564. end Show_Title;
  9565. --LINEFEED
  9566. procedure  Update_NoQueue_Nodes (N_Jobs: in NumJobs) is
  9567.  
  9568.    End_Of_Network: Boolean;
  9569.    ND            : NodeDef;
  9570.    SD            : ServDisc;
  9571.    Found         : Boolean;
  9572.  
  9573. begin
  9574.  
  9575.    Move_To_First_Node (End_Of_Network);
  9576.  
  9577.    while not End_Of_Network loop
  9578.       Get_Node (ND);
  9579.       SD := Node_Serv_Disc (ND);
  9580.  
  9581.       if SD.Serv_Mode = NQ and then
  9582.          SD.Num_Servers /= NumServers(N_Jobs) then
  9583.  
  9584.             SD.Num_Servers := NumServers(N_Jobs);
  9585.             Found := Replace_Node (Name_Of_Node(ND),
  9586.                                    Modify_Node (ND,SD));
  9587.             Write("Node '" & Short(Name_Of_Node(ND))
  9588.                & "' now has Nservers = " & Strng(Txt(N_Jobs)) &
  9589.                ", since the Discipline is NQ.", Spacing => Single);
  9590.       end if;
  9591.  
  9592.       Move_To_Next_Node (End_Of_Network);
  9593.    end loop;
  9594.  
  9595. end Update_Noqueue_Nodes;
  9596. --LINEFEED
  9597. function  Verified (Query: in Text) return Boolean is
  9598.  
  9599.    Answer:   YesNo;
  9600.  
  9601.    procedure Get_YesNo        is new Get_Text (YesNo);
  9602.  
  9603. begin
  9604.  
  9605.    Get_YesNo (Answer, "Response", Prompt, Query);
  9606.    return (Answer = Yes);
  9607.  
  9608. end Verified;
  9609.  
  9610. ------------------------------------------------------------------------
  9611. ------------------------------------------------------------------------
  9612.  
  9613. procedure Welcome is
  9614.  
  9615. begin
  9616.  
  9617.    Write("Welcome to QSAP version 6/20/85. Please type " &
  9618.       "'help new_user'.", Spacing => Double);
  9619.  
  9620. end Welcome;
  9621.  
  9622. end MMI;
  9623. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  9624. --qsap.ada
  9625. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  9626. --===========================================================
  9627. -- Source:     Division Software Technology and Support
  9628. --             Western Development Laboratories
  9629. --             Ford Aerospace & Communications Corporation
  9630. --             ATTN:  Ada Tools Group
  9631. -- Date   : June 1985
  9632. --===========================================================
  9633.  
  9634.  
  9635.  
  9636. with Text_Handler; use Text_Handler;
  9637. with Global_Types; use Global_Types;
  9638. with MMI_Io      ; use MMI_Io;
  9639. with MMI         ; use MMI;
  9640. with Network     ; use Network;
  9641. with Reports     ; use Reports;
  9642. with Calendar    ; use Calendar;
  9643.  
  9644. procedure Qsap is
  9645. ------------------------------------------------------------------------
  9646. -- Main procedure for the MMI. It consists of: local procedures which
  9647. -- correspond to commands, external calls to procedures in MMI
  9648. -- and MMI_Io packages which correspond to commands, external calls to
  9649. -- Network package for storing and retrieving node information in the
  9650. -- network, and a body which is a loop that is iterated once for each
  9651. -- command that is entered.
  9652. --
  9653. -- There are three modes corresponding to MMI.mmimodes. Edit mode
  9654. -- is the normal one in which the E> prompt is displayed and the
  9655. -- user supplies a command. Prompt mode is entered when the user
  9656. -- issues the Prompt command. This puts the user into a subsystem
  9657. -- in which he or she must answer all questions to make up a complete
  9658. -- model. The prompt is P>. Infile mode is entered when the user
  9659. -- issues the Infile command which redirects user input to a file
  9660. -- instead of the terminal. The prompt is I>.
  9661. ------------------------------------------------------------------------
  9662.  
  9663.  
  9664. procedure Get_Command        is new Get_Text    (CommandType);
  9665. procedure Get_Coxian_Nstages is new Get_Integer (NumCoxianStages);
  9666. procedure Get_Coxian_Rates   is new Get_Rates   (NumCoxianStages,
  9667.                                                  CoxianRate,
  9668.                                                  CoxianRates);
  9669. procedure Get_Discipline     is new Get_Text    (ServMode);
  9670. procedure Get_Distribution   is new Get_Text    (ServDist);
  9671. procedure Get_Erlang_Nstages is new Get_Integer (NumErlangStages);
  9672. procedure Get_Erlang_Rate    is new Get_Rates   (One,
  9673.                                                  ErlangRate,
  9674.                                                  ErlangRates);
  9675. procedure Get_Expon_Rate     is new Get_Rates   (One,
  9676.                                                  ExponRate,
  9677.                                                  ExponRates);
  9678. procedure Get_Njobs          is new Get_Integer (Numjobs);
  9679. procedure Get_Nnodes         is new Get_Integer (NumNodes);
  9680. procedure Get_Nservers       is new Get_Integer (NumServers);
  9681. procedure Get_Report_Type    is new Get_Text    (ReportType);
  9682. procedure Get_YesNo          is new Get_Text    (YesNo);
  9683. procedure Show_What          is new Get_Text    (ShowType);
  9684. Command               :  CommandType := Reset;
  9685. Found                 :  Boolean;
  9686. Dummy                 :  Boolean;
  9687.  
  9688. Global_Settings       :  GlobalStatusType := (others => False);
  9689.    Title_Set          :  Boolean   renames Global_Settings.Title;
  9690.    N_Jobs_Set         :  Boolean   renames Global_Settings.N_Jobs;
  9691.    N_Nodes_Set        :  Boolean   renames Global_Settings.N_Nodes;
  9692.    Order_Set          :  Boolean   renames Global_Settings.Order;
  9693.    Run_Set            :  Boolean := False;
  9694.  
  9695. Global_Values         :  GlobalValueType;
  9696.    N_Nodes            :  NumNodes  renames Global_Values.N_Nodes;
  9697.    N_Jobs             :  NumJobs   renames Global_Values.N_Jobs;
  9698.    Nodes              :  NodesType renames Global_Values.Nodes;
  9699.    Model_Title        :  Text      renames Global_Values.Title;
  9700.  
  9701. Node_Settings         :  NodeStatusType := (others => False);
  9702.    C_Branch_Set       :  Boolean   renames Node_Settings.C_Branch;
  9703.    Coxian_Rates_Set   :  Boolean   renames Node_Settings.Coxian_Rates;
  9704.    Discip_Set         :  Boolean   renames Node_Settings.Discip;
  9705.    Dist_Set           :  Boolean   renames Node_Settings.Dist;
  9706.    Erlang_Rate_Set    :  Boolean   renames Node_Settings.Erlang_Rate;
  9707.    Expon_Rate_Set     :  Boolean   renames Node_Settings.Expon_Rate;
  9708.    N_Coxian_Stages_Set:  Boolean  renames Node_Settings.N_Coxian_Stages;
  9709.    N_Erlang_Stages_Set:  Boolean  renames Node_Settings.N_Erlang_Stages;
  9710.    Node_Set           :  Boolean   renames Node_Settings.Node;
  9711.    N_Servers_Set      :  Boolean   renames Node_Settings.N_Servers;
  9712.    P_Branch_Set       :  Boolean   renames Node_Settings.P_Branch;
  9713.  
  9714. Node_Values           :  NodeValueType;
  9715.    Coxian_Dist        :  CoxianDist  renames Node_Values.Coxian_Dist;
  9716.    Discip             :  ServMode    renames Node_Values.Discip;
  9717.    Dist               :  ServDist    renames Node_Values.Dist;
  9718.    Erlang_Rates       :  ErlangRates renames Node_Values.Erlang_Rates;
  9719.    Expon_Rates        :  ExponRates  renames Node_Values.Expon_Rates;
  9720.    N_Servers          :  NumServers  renames Node_Values.N_Servers;
  9721.    N_Coxian_Stages    :  NumCoxianStages
  9722.                                     renames Node_Values.N_Coxian_Stages;
  9723.    N_Erlang_Stages    :  NumErlangStages  renames
  9724.                                     Node_Values.N_Erlang_Stages;
  9725.    Node_Name          :  Text        renames Node_Values.Name;
  9726.    P_Branch           :  PbranchType renames Node_Values.P_Branch;
  9727.  
  9728. To_Show               :  ShowType;
  9729. ------------------------------------------------------------------------
  9730. -- Procedures internal to Edit which share its variables.
  9731. -- In alphabetical order.
  9732. ------------------------------------------------------------------------
  9733.  
  9734. procedure Cbranch_Command is
  9735.  
  9736. begin
  9737.  
  9738.    Check_Dist_Set (Dist_Set);
  9739.  
  9740.    if Dist = Coxian then
  9741.       Check_N_Stages_Set (N_Coxian_Stages_Set);
  9742.       Get_Cbranch (Coxian_Dist.Contin_Probs);
  9743.       C_Branch_Set := True;
  9744.    else
  9745.       Error ("The Distribution is not COXIAN.");
  9746.    end if;
  9747.  
  9748. end Cbranch_Command;
  9749.  
  9750. ------------------------------------------------------------------------
  9751. ------------------------------------------------------------------------
  9752.  
  9753. procedure Default_IO_Settings is
  9754.  
  9755. begin
  9756.  
  9757.    Set_Media (Input,  Terminal);
  9758.    Set_Media (Report, Terminal);
  9759.    Set_Report_Echo     (True);
  9760.    Set_Terminal_Paging (False);
  9761.  
  9762. end Default_IO_Settings;
  9763. procedure Discipline_Command is
  9764.  
  9765.    Prior_Non_Fcfs : Boolean := Discip_Set and (Discip /= Fcfs);
  9766.  
  9767. begin
  9768.  
  9769.    Get_Discipline (Discip, "Discipline");
  9770.  
  9771.    if Discip = Fcfs then
  9772.       if Prior_Non_Fcfs then
  9773.          N_Servers_Set := False;
  9774.       end if;
  9775.       Set_Exponential (Dist);
  9776.       Dist_Set := True;
  9777.    else
  9778.       Set_Nservers (N_Servers, Discip, N_Jobs);
  9779.       N_Servers_Set := True;
  9780.    end if;
  9781.  
  9782.    Discip_Set := True;
  9783.  
  9784. end Discipline_Command;
  9785.  
  9786. ------------------------------------------------------------------------
  9787. ------------------------------------------------------------------------
  9788.  
  9789. procedure Distribution_Command is
  9790.  
  9791. begin
  9792.  
  9793.    if Discip_Set and (Discip = Fcfs) then
  9794.       Set_Exponential (Dist);
  9795.       Flush_Next_Token;
  9796.    else
  9797.       Get_Distribution (Dist,"Distribution");
  9798.    end if;
  9799.    Dist_Set := True;
  9800.  
  9801. end Distribution_Command;
  9802. procedure Echo_Command is
  9803.  
  9804.    Answer: YesNo;
  9805.  
  9806. begin
  9807.  
  9808.    Get_YesNo (Answer, "Yes/No response");
  9809.    Set_Report_Echo (Answer = Yes);
  9810.  
  9811. end Echo_Command;
  9812.  
  9813. ------------------------------------------------------------------------
  9814. ------------------------------------------------------------------------
  9815.  
  9816. procedure End_Node_Command is
  9817.  
  9818. begin
  9819.  
  9820.    Put_Node_Info (Node_Values, Node_Settings);
  9821.    Node_Settings := (others => False);
  9822.    Write("Node"& Quote(Node_Name) & "has been stored into the model.",
  9823.       Spacing => Single);
  9824. end End_Node_Command;
  9825.  
  9826. ------------------------------------------------------------------------
  9827. ------------------------------------------------------------------------
  9828.  
  9829. procedure Help_Command is
  9830.  
  9831. begin
  9832.  
  9833.    if Next_Token_Exists then
  9834.       Help (Txt(Token));
  9835.    else
  9836.       Help (Txt("INDEX"));
  9837.    end if;
  9838.  
  9839. end Help_Command;
  9840. function Model_Reset return Boolean is
  9841.  
  9842. begin
  9843.  
  9844.    if Verified (Txt("This will cause the current model definition to " &
  9845.       "be lost. Continue? (Yes, No)")) then
  9846.           Set_Up_New_Network;
  9847.           Global_Settings := (others => False);
  9848.           Run_Set         := False;
  9849.           Node_Settings   := (others => False);
  9850.           return True;
  9851.    else
  9852.           return False;
  9853.    end if;
  9854.  
  9855. end Model_Reset;
  9856.  
  9857. ------------------------------------------------------------------------
  9858. ------------------------------------------------------------------------
  9859.  
  9860. procedure Njobs_Command is
  9861.  
  9862. begin
  9863.  
  9864.     Get_Njobs (N_Jobs, "Njobs");
  9865.     Update_NoQueue_Nodes (N_Jobs);
  9866.     N_Jobs_Set := True;
  9867.  
  9868. end Njobs_Command;
  9869.  
  9870. ------------------------------------------------------------------------
  9871. ------------------------------------------------------------------------
  9872.  
  9873. procedure Nnodes_Command is
  9874.  
  9875. begin
  9876.  
  9877.    Check_Nnodes_Not_Set (N_Nodes_Set);
  9878.    Get_Nnodes  (N_Nodes, "Nnodes");
  9879.    N_Nodes_Set := True;
  9880.  
  9881. end Nnodes_Command;
  9882. procedure Node_Command is
  9883.  
  9884.    Nodex : Integer;
  9885.    Missing_Commands: Text := Txt(Missing_Global_Commands(Global_Settings));
  9886.  
  9887. begin
  9888.  
  9889.    if Length(Missing_Commands) > 0 then
  9890.       Error ("The following command(s) must first be issued: " &
  9891.          Strng(Missing_Commands));
  9892.       raise Command_Error;
  9893.    end if;
  9894.  
  9895.    Node_Name := Txt(Token);
  9896.    Nodex     := Index (Node_Name, Nodes);
  9897.  
  9898.    if Nodex > 0 then
  9899.       if Node_Is_Complete (Strng(Node_Name,NodeName'Length)) then
  9900.          Get_Node_Info (Node_Values, Node_Settings);
  9901.          Node_Set := True;
  9902.       else
  9903.          Node_Settings := (Node => True, others => False);
  9904.       end if;
  9905.    else
  9906.       Error ("Node '" & Strng(Node_Name) &
  9907.          "' was not specified in the order command.");
  9908.    end if;
  9909.  
  9910. end Node_Command;
  9911.  
  9912. ------------------------------------------------------------------------
  9913. ------------------------------------------------------------------------
  9914.  
  9915. procedure Nservers_Command is
  9916.  
  9917. begin
  9918.  
  9919.    if Discip_Set then
  9920.       if Discip = Fcfs then
  9921.          Get_Nservers (N_Servers, "Nservers");
  9922.       else
  9923.          Set_Nservers (N_Servers, Discip, N_Jobs);
  9924.          Flush_Next_Token;
  9925.       end if;
  9926.    else
  9927.       Get_Nservers (N_Servers, "Nservers");
  9928.    end if;
  9929.  
  9930.    N_Servers_Set := True;
  9931.  
  9932. end Nservers_Command;
  9933. procedure Nstages_Command is
  9934.  
  9935.    Old_Nstages : NumCoxianStages := N_Coxian_Stages;
  9936.    Old_Coxian  : CoxianDist      := Coxian_Dist;
  9937.  
  9938. begin
  9939.  
  9940.    Check_Dist_Set (Dist_Set);
  9941.    case Dist is
  9942.       when Erlang =>
  9943.          Get_Erlang_Nstages (N_Erlang_Stages,"Nstages");
  9944.          N_Erlang_Stages_Set := True;
  9945.       when Coxian =>
  9946.          Get_Coxian_Nstages (N_Coxian_Stages, "Nstages");
  9947.          Coxian_Dist := (N_Coxian_Stages, (others=>1.0),(others=>1.0));
  9948.  
  9949.          if N_Coxian_Stages_Set and N_Coxian_Stages <= Old_Nstages then
  9950.             if C_Branch_Set then
  9951.                for Stagex in 1 .. N_Coxian_Stages-1 loop
  9952.                   Coxian_Dist.Contin_Probs(Stagex) :=
  9953.                      Old_Coxian.Contin_Probs(Stagex);
  9954.                end loop;
  9955.             end if;
  9956.             if Coxian_Rates_Set then
  9957.                for Stagex in 1 .. N_Coxian_Stages loop
  9958.                   Coxian_Dist.Coxian_Rates(Stagex) :=
  9959.                      Old_Coxian.Coxian_Rates(Stagex);
  9960.                end loop;
  9961.             end if;
  9962.          else
  9963.             N_Coxian_Stages_Set := True;
  9964.             C_Branch_Set        := False;
  9965.             Coxian_Rates_Set    := False;
  9966.          end if;
  9967.       when others =>
  9968.          Error ("The Distribution is not ERLANG or COXIAN.");
  9969.    end case;
  9970.  
  9971. end Nstages_Command;
  9972. procedure Order_Command is
  9973.  
  9974. begin
  9975.  
  9976.    Check_Nnodes_Set (N_Nodes_Set);
  9977.    Check_Order_Not_Set (Order_Set);
  9978.    Get_Order (Nodes, N_Nodes);
  9979.    Insert_Dummy_Nodes (Nodes);
  9980.    Order_Set := True;
  9981.  
  9982. end Order_Command;
  9983.  
  9984. ------------------------------------------------------------------------
  9985. ------------------------------------------------------------------------
  9986.  
  9987. procedure Paging_Command is
  9988.  
  9989.    Answer: YesNo;
  9990.  
  9991. begin
  9992.  
  9993.    Get_YesNo (Answer, "Yes/No response");
  9994.    Set_Terminal_Paging (Answer = Yes);
  9995.  
  9996. end Paging_Command;
  9997.  
  9998. ------------------------------------------------------------------------
  9999. ------------------------------------------------------------------------
  10000.  
  10001. procedure Pbranch_Command is
  10002.  
  10003. begin
  10004.  
  10005.    Get_Pbranch (N_Nodes, P_Branch);
  10006.    P_Branch_Set := True;
  10007.  
  10008. end Pbranch_Command;
  10009. procedure Prompt_Command is
  10010.  
  10011.    Node_Id: Text;
  10012.  
  10013. begin
  10014.  
  10015.    if not Model_Reset then
  10016.       return;
  10017.    end if;
  10018.  
  10019.    Get_Title (Model_Title, Prompt,
  10020.       Txt("Enter the title (up to 50 characters) on one line."));
  10021.    Set_Title (Strng(Model_Title));
  10022.  
  10023.    Get_Nnodes (N_Nodes, "Nnodes", Prompt,
  10024.       Txt("Enter the number of nodes: "));
  10025.    Get_Order (Nodes, N_Nodes, Prompt, Txt("Enter the ") &
  10026.       Txt(Integer(N_Nodes)) & Txt(" node names in order: "));
  10027.  
  10028.    Insert_Dummy_Nodes (Nodes);
  10029.  
  10030.    Get_Njobs(N_Jobs, "Njobs", Prompt, Txt("Enter the number of jobs:"));
  10031.  
  10032.    Global_Settings := (others => True);
  10033.  
  10034.    for Nodex in Nodes.Name'Range loop
  10035.       Node_Name := Txt(Short(Nodes.Name (Nodex)));
  10036.       Node_Id   := Txt("For node ") & Node_Name & Txt(", ");
  10037.  
  10038.       Show_Order (Nodes, True, Terminal_Out);
  10039.       Get_Pbranch (N_Nodes,P_Branch,Prompt,Node_Id & Txt("enter the ")
  10040.          & Txt(Integer(N_Nodes)) & Txt(" branching probabilities ") &
  10041.          Txt("to all nodes:"));
  10042.  
  10043.       Get_Discipline (Discip, "Discipline", Prompt, Node_Id &
  10044.          Txt("enter the discipline (Fcfs, P_share, PR_lcfs, "  &
  10045.              "Nq): "));
  10046.       if Discip = FCFS then
  10047.          Get_Nservers (N_Servers, "Nservers", Prompt,
  10048.             Node_Id & Txt("enter the number of servers: "));
  10049.          Set_Exponential (Dist);
  10050.          Get_Expon_Rate (Expon_Rates, Prompt, Node_Id &
  10051.             Txt("Enter the service rate: "));
  10052.       else
  10053.          Set_Nservers (N_Servers, Discip, N_Jobs);
  10054.          Get_Distribution (Dist, "Distribution", Prompt, Node_Id & Txt(
  10055.             "Enter the distribution (EXponential, ERlang, Coxian): "));
  10056.          case Dist is
  10057.             when Exponential =>
  10058.                Get_Expon_Rate (Expon_Rates, Prompt, Node_Id &
  10059.                   Txt("enter the service rate: "));
  10060.             when ERLANG =>
  10061.                Get_Erlang_Nstages (N_Erlang_Stages, "Nstages", Prompt,
  10062.                   Node_Id & Txt("enter the number of stages:"));
  10063.                Get_Erlang_Rate (Erlang_Rates, Prompt, Node_Id &
  10064.                   Txt("enter 1 service rate for all stages: "));
  10065.             when COXIAN =>
  10066.                Get_Coxian_Nstages (N_Coxian_Stages, "Nstages", Prompt,
  10067.                   Node_Id & Txt("enter the number of stages: "));
  10068.                Coxian_Dist := (N_Coxian_Stages,
  10069.                               (others=>1.0), (others=>1.0));
  10070.                Get_Cbranch (Coxian_Dist.Contin_Probs, Prompt, Node_Id &
  10071.                   Txt("enter the ") & Txt(Integer(N_Coxian_Stages)-1) &
  10072.                   Txt(" continuation probabilities between stages: "));
  10073.                Get_Coxian_Rates (Coxian_Dist.Coxian_Rates,Prompt,Node_Id
  10074.                   & Txt("enter the ") & Txt(Integer(N_Coxian_Stages)) &
  10075.                   Txt(" service rates for each stage: "));
  10076.          end case;
  10077.       end if;
  10078.  
  10079.       Put_Node_Info (Node_Values, (others => True));
  10080.  
  10081.    end loop;
  10082.  
  10083. end Prompt_Command;
  10084. procedure Rates_Command is
  10085.  
  10086. begin
  10087.  
  10088.    Check_Dist_Set (Dist_Set);
  10089.    case Dist is
  10090.       when Exponential =>
  10091.          Get_Expon_Rate   (Expon_Rates);
  10092.          Expon_Rate_Set := True;
  10093.       when Erlang      =>
  10094.          Get_Erlang_Rate  (Erlang_Rates);
  10095.          Erlang_Rate_Set := True;
  10096.       when Coxian      =>
  10097.          Check_N_Stages_Set (N_Coxian_Stages_Set);
  10098.          Get_Coxian_Rates (Coxian_Dist.Coxian_Rates);
  10099.          Coxian_Rates_Set := True;
  10100.    end case;
  10101.  
  10102. end Rates_Command;
  10103.  
  10104. ------------------------------------------------------------------------
  10105. ------------------------------------------------------------------------
  10106.  
  10107. procedure Report_Command is
  10108.  
  10109.    Report_Type: ReportType;
  10110.    T          : Time := Clock;
  10111.  
  10112. begin
  10113.  
  10114.       Get_Report_Type (Report_Type, "report type");
  10115.       if Report_Type = Model then
  10116.          New_Page;
  10117.          Print_Title ("Model Definition", " ", T);
  10118.          Write (" ", Report, Double);
  10119.          Show_All (Global_Values, Global_Settings, Report);
  10120.       else
  10121.          if Run_Set then
  10122.             Report_Set_Up (Report_Type, N_Jobs, Nodes);
  10123.          else
  10124.             Error ("The Run command must first be issued.");
  10125.          end if;
  10126.       end if;
  10127.  
  10128. end Report_Command;
  10129. procedure Run_Command is
  10130.  
  10131. begin
  10132.  
  10133.    Run (Nodes, N_Jobs);
  10134.    Run_Set := True;
  10135.  
  10136. end Run_Command;
  10137.  
  10138. ------------------------------------------------------------------------
  10139. ------------------------------------------------------------------------
  10140.  
  10141. procedure Save_Command is
  10142.  
  10143. begin
  10144.  
  10145.    Openf (Save, Strng(Txt(Token)));
  10146.    Show_All (Global_Values, Global_Settings, Save);
  10147.    Closef (Save);
  10148.  
  10149. end Save_Command;
  10150. procedure Show_Command is
  10151.  
  10152.    Node_Show  : Text;
  10153.    Nodex      : Integer;
  10154.  
  10155. begin
  10156.  
  10157.    Show_What (To_Show, "Item to show");
  10158.    case To_Show is
  10159.       when Title    =>
  10160.          Show_Title  (Model_Title, Title_Set, Terminal_Out);
  10161.       when Nnodes   =>
  10162.          Show_Nnodes (N_Nodes,   N_Nodes_Set, Terminal_Out);
  10163.       when Order    =>
  10164.          Show_Order  (Nodes,       Order_Set, Terminal_Out);
  10165.       when Njobs    =>
  10166.          Show_Njobs  (N_Jobs,     N_Jobs_Set, Terminal_Out);
  10167.       when Node     =>
  10168.          Node_Show := Txt(Token);
  10169.          Nodex     := Index (Node_Show, Nodes);
  10170.          if Nodex > 0 then
  10171.             Show_Node (Node_Show, Terminal_Out);
  10172.          else
  10173.             Write("Node" & Quote(Node_Show) & "was not specified" &
  10174.                " in the order command.", Spacing => Single);
  10175.          end if;
  10176.       when Model    =>
  10177.          Show_All (Global_Values, Global_Settings, Terminal_Out);
  10178.    end case;
  10179.  
  10180. end Show_Command;
  10181.  
  10182. ------------------------------------------------------------------------
  10183. ------------------------------------------------------------------------
  10184.  
  10185. procedure Title_Command is
  10186.  
  10187. begin
  10188.  
  10189.    Get_Title (Model_Title);
  10190.    Title_Set := True;
  10191.    Set_Title (Strng(Model_Title));
  10192.  
  10193. end Title_Command;
  10194. ------------------------------------------------------------------------
  10195. --                     Main Procedure
  10196. ------------------------------------------------------------------------
  10197.  
  10198. begin
  10199.  
  10200.    Default_IO_Settings;
  10201.    Model_Title := Txt("Main Model");
  10202.    Welcome;
  10203.  
  10204.    loop
  10205.       begin
  10206.          Display ("");
  10207.          Get_Command (Command, "Command");
  10208.  
  10209.          if Command in NodeSubcommandType then
  10210.             Check_Node_Subcommand_Ok (Node_Set, Global_Settings);
  10211.          end if;
  10212.  
  10213.          case Command is
  10214.             when Quit         =>
  10215.                if Mode = Edit and then
  10216.                   Verified(Txt("Do you want to quit (Yes,No)?")) then
  10217.                      exit;
  10218.                end if;
  10219.             when Prompt       => Prompt_Command;
  10220.             when Help         => Help_Command;
  10221.             when Run          => Run_Command;
  10222.             when Title        => Title_Command;
  10223.             when Njobs        => Njobs_Command;
  10224.             when Nnodes       => Nnodes_Command;
  10225.             when Order        => Order_Command;
  10226.             when Node         => Node_Command;
  10227.             when Pbranch      => Pbranch_Command;
  10228.             when Discipline   => Discipline_Command;
  10229.             when Nservers     => Nservers_Command;
  10230.             when Distribution => Distribution_Command;
  10231.             when Nstages      => Nstages_Command;
  10232.             when Rates        => Rates_Command;
  10233.             when Cbranch      => Cbranch_Command;
  10234.             when Infile       => Get_Infile;
  10235.             when Outfile      => Get_Outfile;
  10236.             when Endnode      => End_Node_Command;
  10237.             when Save         => Save_Command;
  10238.             when Show         => Show_Command;
  10239.             when Report       => Report_Command;
  10240.             when Reset        => Dummy := Model_Reset;
  10241.             when Echo         => Echo_Command;
  10242.             when Paging       => Paging_Command;
  10243.          end case;
  10244.  
  10245.          if Command in NodeSubcommandType and then
  10246.             Missing_Node_Commands (Node_Settings,Dist) = "" then
  10247.                Write("Node " & Quote(Node_Name) & " is complete. Use " &
  10248.                   "'Endnode' to store into the model.", Terminal_Out,
  10249.                   Single);
  10250.          end if;
  10251.  
  10252.       exception
  10253.          when EOF               =>
  10254.             Closef (Input);
  10255.             Set_Media (Input, Terminal);
  10256.          when Command_Error     =>
  10257.             null;
  10258.          when Unstable_Solution =>
  10259.             Write("A Unstable_Solution_Exception has occurred." & 
  10260.                                       " Type 'help excepts'.");
  10261.          when others            =>
  10262.             Write("Unhandled exception raised.");
  10263.       end;
  10264.    end loop;
  10265.  
  10266.    if Get_Media(Report) = File then
  10267.       Closef (Report);
  10268.    end if;
  10269. end QSAP;
  10270. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  10271. --help.ada
  10272. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  10273.  
  10274. package body Help_Setup is
  10275. begin
  10276.      Help_Directory := Txt(":udd:facc_krg:demo:help:");
  10277.      Help_File_Name_Ext := Txt( ".hlp");
  10278. end Help_Setup;
  10279.  
  10280.