home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / ddjmag / ddj8611.zip / SHAMMAS.NOV < prev   
Text File  |  1986-12-01  |  16KB  |  690 lines

  1.  
  2. Listing 1.  Using the predefined NUMERIC_ERROR Ada exception.
  3.  
  4.  
  5. function Power(BASE, EXPONENT : FLOAT) return FLOAT is
  6.  
  7. begin
  8.  
  9.    return Exp(Exponent * Ln(Base));
  10.  
  11. -- This is the area to handle exceptions
  12. exception
  13.    when NUMERIC_ERROR =>
  14.       if Base = 0 then 
  15.           return 0;
  16.       else -- return "infinity"
  17.         return FLOAT'FIRST;
  18.       end if;
  19.  
  20. end Power;
  21.  
  22.  
  23. -*-
  24. Listing 2.  General form of exception handling block.
  25.  
  26.  
  27. procedure Big_Trouble is
  28.  
  29.    Negative_Absolute_Temperature,
  30.    Negative_Pressure, Negative_Volume : exception;
  31.  
  32.    Temperature, Pressure, Volume : FLOAT;
  33.  
  34. begin
  35.  
  36.   -- procedure to calculate temperature, Pressure and volume
  37.   -- Calculate temperature in Rankin
  38.   if Temperature < 0.0 then 
  39.       raise Negative_Absolute_Temperature;
  40.   end if;
  41.  
  42.   -- Calculate pressure and volume
  43.   if Pressure < 0.0 then
  44.       raise Negative_Pressure;
  45.   end if;
  46.  
  47.   if Volume < 0.0 then
  48.       raise Negative_Volume;
  49.   end if;
  50.  
  51.   -- other procedure statements  
  52.  
  53. exception -- handling block
  54.    when NUMERIC_ERROR =>
  55.  
  56.         -- handle bad function arguments, underflow or overflow
  57.  
  58.    when Negative_Absolute_Temperature =>
  59.  
  60.         -- handle negative absolute temperature results
  61.  
  62.    when Negative_Pressure | Negative_Volume =>
  63.  
  64.         -- handle negative pressure or volume values
  65.  
  66.    when others =>
  67.  
  68.         -- handle all other problems
  69.  
  70. end Big_trouble;
  71.  
  72. -*-
  73. Listing 3.  Ada exception handling scope.
  74.  
  75. procedure The_Boss is
  76.  
  77.    Boss_Angry : exception;
  78.  
  79.    procedure Command_Worker is
  80.  
  81.    begin
  82.  
  83.       -- sequence of statements
  84.       if income < 0.0 then raise Boss_Angry; end if;
  85.       -- sequence of statements
  86.  
  87.    end Command_Worker;
  88.  
  89.    procedure Command_Foreman is
  90.  
  91.    begin
  92.  
  93.       -- sequence of statements
  94.       Command_Worker;
  95.       -- sequence of statements
  96.    exception
  97.       when Boss_Angry =>
  98.          -- Try to deal with the boss
  99.    end Command_Foreman;
  100.  
  101. begin
  102.    -- sequence of statements
  103.    Command_Worker;
  104.    Command_Foreman;
  105.    - sequence of statements
  106.    exception
  107.       when Boss_Angry =>
  108.           -- fire foreman
  109. end The_Boss;
  110.  
  111. -*-
  112. Listing 4.  The retry approach with exception handlers.
  113.  
  114.  
  115. with TEXT_IO; use TEXT_IO;
  116.  
  117. procedure Days_of_our_lives;
  118.    type Day_Name is (Sun, Mon, Tue, Wed, Thu, Fir, Sat);
  119.    package DAY_IO is new TEXT_IO.ENUMERATION_IO (Day_Name);
  120.    use Day_IO;
  121.  
  122.    -- define time-out
  123.    Time_Out : constant integer := 5;
  124.    -- define variable
  125.    Day : Day_Name;
  126.    -- define exception
  127.    Wrong_Day : exception;
  128.  
  129. begin
  130.    for Count in 1..Time_Out loop
  131.  
  132.       PUT("What day is it?"); NEW_LINE;
  133.  
  134.       begin -- exception handling block starts here
  135.         GET(Day); NEW_LINE;
  136.         PUT("Have a nice "); PUT(Day); NEW_LINE;
  137.         exit; -- exit for loop when answer is correct
  138.  
  139.       exception
  140.          when CONSTRAINT_ERROR =>
  141.            if Count = Time_Out then
  142.               PUT("Sorry! Loop time-out");
  143.               raise Wrong_Day;
  144.            else
  145.               PUT("Sorry! No such weekday"); NEW_LINE;
  146.               PUT("You have "); PUT(Time_Out - Count);
  147.               PUT(" more times to try); NEW_LINE;
  148.               PUT("Let us try once more"); NEW_LINE;
  149.            end if;
  150.       end; -- end error handler
  151.    end loop; -- end for loop
  152. end Days_of_our_lives;
  153.  
  154.  
  155.  
  156. -*-
  157. Listing 5.  Using an alternative method with exception handlers.
  158.  
  159.  
  160. with TEXT_IO; use TEXT_IO;
  161. procedure Root is
  162.  
  163. Result, Guess1, Guess2, Accuracy : FLOAT; 
  164. Max_Iter : INTEGER;
  165. Diverge, Fatal_Error : exception;
  166.  
  167.  
  168. function F(X : FLOAT) return FLOAT is
  169.  
  170. begin
  171.    return X * X * X - 5.0;
  172. end F;
  173.  
  174.  
  175. procedure Newton(Guess, Accuracy : FLOAT; Max_Iter : INTEGER) is
  176. -- Newton's method to find the root of a function
  177.  
  178. Funct, Derivative, h, Diff : FLOAT;
  179.  
  180. begin
  181.    loop
  182.       if ABS(Guess) > 1.0 then h := 0.01 * Guess;
  183.                           else h := 0.01;
  184.       end if;
  185.  
  186.       Funct := F(Guess);
  187.       Derivative := (F(Guess + h) - Funct) / h;
  188.       Diff := Funct / Derivative;
  189.       Guess := Guess - Diff;
  190.  
  191.       Max_Iter := Max_Iter - 1;
  192.       if Max_Iter < 0 then
  193.           raise Diverge;
  194.       end if;
  195.   
  196.  
  197.       if ABS(Diff) <= Accuracy then exit; end if;
  198.    end loop;
  199.  
  200.    PUT(Guess);
  201.  
  202. end Newton;
  203.  
  204.  
  205. procedure Bisection(A, B, Accuracy : FLOAT; Max_Iter : INTEGER) is
  206. -- Bisection method to find the root of a function
  207.                    
  208. Mean, FA, FB, FM : FLOAT;
  209.  
  210. begin
  211.    FA := F(A); FB := F(B);
  212.    -- Get midpoint estimate for the root
  213.    Mean := (A + B) / 2.0;
  214.  
  215.    while ABS(A - B) > Accuracy loop
  216.  
  217.      FM := F(Mean);
  218.      -- Does A and Mean have same function sign?
  219.      if FM * FA > 0.0 
  220.      then
  221.         A := Mean; FA := FM;
  222.      else
  223.         B := Mean; FB := FM;
  224.      end if;
  225.  
  226.      -- Get midpoint estimate for the root
  227.      Mean := (A + B) / 2.0;
  228.  
  229.      Max_Iter := Max_Iter - 1;
  230.      if Max_Iter < 0 then
  231.          raise Fatal_Error;
  232.      end if;
  233.  
  234.    end loop;
  235.  
  236.    PUT(Mean);
  237.  
  238. end Bisection; 
  239.  
  240. begin -- Root --
  241.   PUT("Enter first guess for the root "); GET(Guess1); NEW_LINE;
  242.   PUT("Enter second guess for the root "); GET(Guess2); NEW_LINE;
  243.   PUT("Enter desired accuracy"); GET(Accuracy); NEW_LINE;
  244.   PUT("Enter maximum number of iterations "); GET(Max_Iter);
  245.   NEW_LINE; NEW_LINE;
  246.   PUT("Root = ");
  247.   begin -- start outer exception handler
  248.     -- Try Newton's method first
  249.     Newton(Guess1, Accuracy, Max_Iter);
  250.     exit; -- terminate program successfully
  251.   exception
  252.     when NUMERIC_ERROR | Diverge =>
  253.        begin -- start inner exception handler
  254.          -- This method will definitely work, but is slower
  255.          Bisection(Guess1, Guess2, Accuracy);
  256.          exit; -- terminate successfully with second method
  257.        exception
  258.          when others =>
  259.             PUT("Fatal Error.  Cannot recover");
  260.             NEW_LINE;
  261.        end; -- inner exception handler
  262.   end; -- outer exception handler
  263. end Root;
  264.     
  265.  
  266.  
  267. -*-
  268. Listing 6.  The clean up method used in exception handlers.
  269.  
  270.  
  271. with TEXT_IO; use TEXT_IO;
  272. procedure Root is
  273.  
  274. Result, Guess, Accuracy : FLOAT; 
  275. Max_Iter : INTEGER)
  276. Diverge : exception;
  277.  
  278.  
  279. function F(X : FLOAT) return FLOAT is
  280.  
  281. begin
  282.    return X * X * X - 5.0;
  283. end F;
  284.  
  285.  
  286. procedure Newton(Guess, Accuracy : FLOAT; Max_Iter : INTEGER) is
  287. -- Newton's method to find the root of a function
  288.  
  289. Funct, Derivative, h, Diff : FLOAT;
  290.  
  291. begin
  292.    loop
  293.       if ABS(Guess) > 1.0 then h := 0.01 * Guess;
  294.                           else h := 0.01;
  295.       end if;
  296.  
  297.       Funct := F(Guess);
  298.       Derivative := (F(Guess + h) - Funct) / h;
  299.       Diff := Funct / Derivative;
  300.       Guess := Guess - Diff;
  301.  
  302.       Max_Iter := Max_Iter - 1;
  303.       if Max_Iter < 0 then
  304.           raise Diverge;
  305.       end if;
  306.   
  307.  
  308.       if ABS(Diff) <= Accuracy then exit; end if;
  309.    end loop;
  310.  
  311.    NEW_LINE; NEW_LINE;
  312.    PUT("Root = "); PUT(Guess);
  313.    NEW_LINE; NEW_LINE;
  314. end Newton;
  315.  
  316.  
  317. begin -- Root --
  318.   PUT("Enter guess for the root "); GET(Guess); NEW_LINE;
  319.   PUT("Enter desired accuracy"); GET(Accuracy); NEW_LINE;
  320.   PUT("Enter maximum number of iterations "); GET(Max_Iter);
  321.   loop
  322.    
  323.     begin -- start exception handler
  324.       -- Try Newton's method first
  325.       Newton(Guess, Accuracy, Max_Iter);
  326.       exit; -- exit open loop and terminate program successfully
  327.     exception
  328.       when Diverge =>
  329.           PUT("Enter guess for the root "); 
  330.           GET(Guess); NEW_LINE;
  331.     end; -- exception handler
  332.   end loop;
  333. end Root;
  334.     
  335.  
  336. -*-
  337. Listing  7.   Module SafeLib0,  a subset of MathLib0  with  error 
  338. trapping features. 
  339.  
  340. DEFINITION MODULE SafeLib0;
  341. (* Definition module of SafeLib0, the safer version of MathLib0 *)
  342.  
  343. (* The EXPORT is not needed for new Modula-2 definition *)
  344. EXPORT QUALIFIED SQRT, LN, EXP, EXPRANGE; 
  345.  
  346. (* Largest argument for exp(X) that yields exp() = 9.9999E+99 *)
  347. CONST EXPRANGE = 230.26; 
  348.  
  349.  
  350. PROCEDURE SQRT(X : REAL; VAR ArgumentERROR : BOOLEAN) : REAL;
  351. (* Square root function with an argument error flag *)
  352.  
  353. PROCEDURE LN(X : REAL; VAR ArgumentERROR : BOOLEAN) : REAL;
  354. (* Natural logarithm function with an argument error flag *)
  355.  
  356.  
  357. PROCEDURE EXP(X : REAL; VAR ArgumentERROR : BOOLEAN) : REAL;
  358. (* Exponential function with an argument error flag *)
  359.  
  360.  
  361. PROCEDURE GetNext(Current, MaxFlag : CARDINAL;
  362.                   VAR Found : BOOLEAN;
  363.                   ErrorFlag : ARRAY OF BOOLEAN) : CARDINAL
  364.  
  365. END SafeLib0.
  366.  
  367.  
  368. IMPLEMENTATION MODULE SafeLib0;
  369.  
  370. FROM MathLib0 IMPORT sqrt, exp, ln;
  371.  
  372. PROCEDURE SQRT(X : REAL; VAR ArgumentERROR : BOOLEAN) : REAL;
  373. (* Square root function with an argument error flag *)
  374.  
  375. BEGIN
  376.    ArgumentERROR := FALSE;
  377.  
  378.    IF X < 0.0 THEN 
  379.        ArgumentERROR := TRUE;
  380.        X := ABS(X)
  381.    END;
  382.  
  383.    RETURN sqrt(X)
  384.  
  385. END SQRT;
  386.        
  387.  
  388. PROCEDURE LN(X : REAL; VAR ArgumentERROR : BOOLEAN) : REAL;
  389. (* Natural logarithm function with an argument error flag *)
  390.  
  391. BEGIN
  392.    ArgumentERROR := FALSE;
  393.  
  394.    IF X <= 0.0 THEN
  395.        ArgumentERROR := TRUE;
  396.        IF X < 0.0 THEN X := ABS(X)
  397.                   ELSE X := 10.0
  398.        END;
  399.    END;
  400.  
  401.    RETURN ln(X)
  402.  
  403. END LN;
  404.  
  405.  
  406. PROCEDURE EXP(X : REAL; VAR ArgumentERROR : BOOLEAN) : REAL;
  407. (* Exponential function with an argument error flag *)
  408.  
  409. BEGIN
  410.    ArgumentERROR := FALSE;
  411.  
  412.    IF X > EXPRANGE 
  413.    THEN 
  414.        ArgumentERROR := TRUE;
  415.        X := 1.0 / EXPRANGE 
  416.    END;
  417.  
  418.    RETURN exp(X)
  419.  
  420. END EXP;
  421.  
  422.  
  423. PROCEDURE GetNext(Current, MaxFlag : CARDINAL;
  424.                   VAR Found : BOOLEAN;
  425.                   ErrorFlag : ARRAY OF BOOLEAN) : CARDINAL;
  426.  
  427. VAR Last : CARDINAL;
  428.  
  429. BEGIN
  430.    Last := HIGH(ErrorFlag);
  431.    IF MaxFlag > Last THEN MaxFlag := Last END;
  432.    Found := FALSE;
  433.    WHILE (Current <= Last) AND (NOT Found) DO
  434.       IF ErrorFlag[Current] THEN Found := TRUE END;
  435.       INC(Current);     
  436.    END;
  437.  
  438.    RETURN Current
  439.  
  440. END GetNext;
  441.  
  442. END SafeLib0.
  443.  
  444.  
  445. -*-
  446. Listing  8.   Module  SafeLib1,  a  second  alternate  subset  of 
  447. MathLib0 with error trapping features. 
  448.  
  449.  
  450.  
  451. DEFINITION MODULE SafeLib1;
  452. (* Definition module of SafeLib1, the safer version of MathLib1 *)
  453.  
  454. (* The EXPORT is not needed for new Modula-2 definition *)
  455. EXPORT QUALIFIED SQRT, LN, EXP, EXPRANGE, 
  456.                  MAXERRORSTACK, ErrorStack; 
  457.  
  458. (* Largest argument for exp(X) that yields exp() = 9.9999E+99 *)
  459. CONST EXPRANGE = 230.26; 
  460.       MAXERRORSTACK = 50;
  461.       
  462.  
  463. VAR ErrorStack : RECORD
  464.                     HeightErrorStack : [0..MAXERRORSTACK];
  465.                     FuncName : ARRAY [1..MAXERRORSTACK] OF 
  466.                                      ARRAY [0..3] OF CHAR
  467.                  END;
  468.  
  469.  
  470. PROCEDURE SQRT(X : REAL) : REAL;
  471. (* Square root function *)
  472.  
  473. PROCEDURE LN(X : REAL) : REAL;
  474. (* Natural logarithm function *) 
  475.  
  476. PROCEDURE EXP(X : REAL) : REAL;
  477. (* Exponential function *)
  478.  
  479. END SafeLib1.
  480.  
  481.  
  482.  
  483.  
  484. IMPLEMENTATION MODULE SafeLib1;
  485.  
  486. FROM MathLib0 IMPORT sqrt, exp, ln;
  487.  
  488. PROCEDURE SQRT(X : REAL) : REAL;
  489. (* Square root function *)
  490.  
  491. BEGIN
  492.    IF X < 0. THEN 
  493.        PushErrorStack("SQRT");
  494.        X := ABS(X);
  495.    END;
  496.  
  497.    RETURN sqrt(X)
  498.  
  499.  
  500. END SQRT;
  501.        
  502.  
  503. PROCEDURE LN(X : REAL) : REAL;
  504. (* Natural logarithm function *)
  505.  
  506. BEGIN
  507.  
  508.    IF X <= 0.0 THEN
  509.        ArgumentERROR := TRUE;
  510.        IF X < 0.0 THEN X := ABS(X)
  511.                   ELSE X := 10.0
  512.        END;
  513.    END;
  514.  
  515.    RETURN ln(X)
  516.  
  517. END LN;
  518.  
  519.  
  520. PROCEDURE EXP(X : REAL) : REAL;
  521. (* Exponential function  *)
  522.  
  523. BEGIN
  524.  
  525.    IF X > EXPRANGE 
  526.    THEN 
  527.        ArgumentERROR := TRUE;
  528.        X := 1.0 / EXPRANGE 
  529.    END;
  530.  
  531.    RETURN exp(X)
  532.  
  533. END EXP;
  534.  
  535.  
  536. PROCEDURE ClearErrorStack;
  537.  
  538. BEGIN
  539.    ErrorStack.HeightErrorStack := 0
  540. END ClearErrorStack;
  541.  
  542.  
  543. PROCEDURE PushErrorStack(Name : ARRAY OF CHAR);
  544.  
  545. VAR I : CARDINAL;
  546.  
  547. BEGIN
  548.    WITH ErrorStack DO
  549.       INC(HeightErrorStack);
  550.  
  551.       I := 0;
  552.       WHILE (I <= HIGH(Name)) AND (Name[I] <> 0C) DO
  553.          FuncName[HeightErrorStack,I] := Name[I]
  554.       END;
  555.  
  556.       IF I < HIGH(Name) THEN FuncName[I+1] := 0C END;
  557.  
  558.   END; (* WITH *)
  559.  
  560. END PushErrorStack;
  561.  
  562.  
  563. PROCEDURE InError() : BOOLEAN;
  564.  
  565. BEGIN
  566.   RETURN (ErrorStack.HeightErrorStack > 0)
  567. END InError;
  568.  
  569. BEGIN (* Module initialization *)
  570.   ClearErrorStack
  571. END SafeLib1.
  572.  
  573.  
  574. -*-
  575. Listing  9.  Turbo  Pascal matrix inversion program  using  Turbo 
  576. Extender utilities. 
  577.  
  578.  
  579. PROGRAM INVERT;
  580.  
  581. (* Program to test speed of floating point matrix inversion.  *)
  582. (* The program will form a matrix with ones' in every member  *)
  583. (* except the diagonals which will have values of 2.          *)
  584.  
  585. CONST MAX = 140;
  586.       RArowsPerPage = 20;
  587.       RAcolsPerPage = 20;
  588.       RApagesDown   = 7;
  589.       RApagesAcross = 7;
  590.       
  591.  
  592. TYPE RAelementType = REAL;
  593. (*$I RARRAY.INC*)
  594.  
  595. VAR J, K, L : INTEGER;
  596.     DET, PIVOT, TEMPO : REAL;
  597.     A : RAarrayPtr;
  598.     CH : CHAR;
  599.  
  600. PROCEDURE SHOW_MATRIX;
  601.  
  602. BEGIN
  603.     FOR J := 1 TO MAX DO BEGIN
  604.         FOR K := 1 TO MAX DO BEGIN
  605.             WRITE(getRA(A,K,J));
  606.             WRITE('  ');
  607.         END;
  608.         WRITELN;
  609.     END;
  610. END;
  611.  
  612.  
  613. BEGIN
  614.     setupRa; (* SETUP BIGARRAY *)
  615.     makeRA(A, 1.0, noinit);
  616.     
  617.     (* Creating test matrix *)
  618.     FOR J := 1 TO MAX DO BEGIN
  619.         FOR K := 1 TO MAX DO
  620.             setRA(A, K, J, 1.0);
  621.         setRA(A, J, J, 2.0)
  622.     END;
  623.  
  624.     (* The test below will ensure that the user does not spend   *)
  625.     (* a lot of time looking at a rather obvious matrix when its *)
  626.     (* size is large.                                            *)
  627.  
  628.     IF MAX <= 10 THEN BEGIN
  629.         WRITELN('Matrix is ');
  630.         SHOW_MATRIX;
  631.         WRITELN; WRITELN;
  632.     END;
  633.  
  634.     WRITELN('Starting matrix invertion');
  635.     DET := 1.0;
  636.     FOR J := 1 TO MAX DO BEGIN
  637.         PIVOT := getRA(A,J,J);
  638.         DET := DET * PIVOT;
  639.         setRA(A,J,J,1.0);
  640.         FOR K := 1 TO MAX DO
  641.             setRA(A,J,K,(getRA(A,J,K) / PIVOT));
  642.  
  643.         FOR K := 1 TO MAX DO
  644.             IF K <> J THEN BEGIN
  645.                 TEMPO := getRA(A,K,J);
  646.                 setRA(A,K,J,0.0);
  647.                 FOR L := 1 TO MAX DO
  648.                   setRA(A,K,L, (getRA(A,K,L) - getRA(A,J,L) * TEMPO));
  649.  
  650.             END;
  651.     END; (* End of outer for-loop *)
  652.     WRITELN('PRESS <CR> to view matrix '); READLN(CH); WRITELN;
  653.     WRITELN('The inverse matrix is ');
  654.     SHOW_MATRIX;
  655.     WRITE('Determinant = ');
  656.     WRITE(DET);
  657.     WRITELN; WRITELN;
  658. END.
  659.  
  660. -*-
  661. Table 1.  Matrix inversion timings. The 8087 chip was used in all of 
  662. the benchmarks. 
  663.  
  664.  
  665. Square Matrix Size         Inversion Time      Comments
  666.  
  667.                            (hh:mm:ss.ff)
  668. ------------------         --------------     -------------
  669.  
  670.       10                   00:00:00.71         Turbo Pascal
  671.       20                   00:00:05.16          "     "
  672.       30                   00:00:17.30          "     "
  673.       50                   00:01:19.42          "     "
  674.       75                   00:04:26.61          "     "
  675.       90                   00:07:40.33          "     "
  676.      100                    overflow            "     "
  677.       
  678.      140                   01:16:33.47         Turbo Extender
  679.                                            20 by 20 page size,
  680.                                                7 pages
  681.  
  682.      140                   01:16:32.32    28 by 28 page size,
  683.                                                5 pages
  684.  
  685.      140                   01:16:33.75    35 by 35 page size,
  686.                                                4 pages
  687.  
  688.  
  689.                              [EOF]
  690.